mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得到这个自增id的值呢?
(1)方法一 是使用last_insert_id
mysql> SELECT LAST_INSERT_ID();
产生的ID 每次连接后保存在服务器中。这意味着函数向一个给定客户端返回的值是该客户端产生对影响AUTO_INCREMENT列的最新语句第一个 AUTO_INCREMENT值的。这个值不能被其它客户端影响,即使它们产生它们自己的 AUTO_INCREMENT值。这个行为保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁或处理。
每次mysql_query操作在mysql服务器上可以理解为一次“原子”操作, 写操作常常需要锁表的, 是mysql应用服务器锁表不是我们的应用程序锁表。
值得注意的是,如果你一次插入了多条记录,这个函数返回的是第一个记录的ID值。
因为LAST_INSERT_ID是基于Connection的,只要每个线程都使用独立的Connection对象,LAST_INSERT_ID函数将返回该Connection对AUTO_INCREMENT列最新的insert or update*作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT语句插入多条记录, LAST_INSERT_ID返回一个列表。
LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。
(2)方法二是使用max(id)
使用last_insert_id是基础连接的,如果换一个窗口的时候调用则会一直返回10
如果不是频繁的插入我们也可以使用这种方法来获取返回的id值
select max(id) from stu_info;
这个方法的缺点是不适合高并发。如果同时插入的时候返回的值可能不准确。
在MySQL中,使用auto_increment类型的id字段作为表的主键。通常的做法,是通过“select max(id) from tablename”的做法,但是显然这种做法需要考虑并发的情况,需要在事务中对主表以“X锁“,待获得max(id)的值以后,再解锁。
这种做法需要的步骤比较多,有些麻烦,而且并发性也不好。有没有更简单的做法呢?答案之一是通过select LAST_INSERT_ID()这个操作。乍一看,它和select max(id)很象,但实际上它是线程安全的。也就是说它是基于数据库连接的,基于数据库连接是什么意义呢?举例说明:
1)、在连接1中向A表插入一条记录,A表包含一个auto_increment类型的id。
2)、在连接2中向A表再插入一条记录。
3)、结果:在连接1中执行select LAST_INSERT_ID()得到的结果和连接2中执行select LAST_INSERT_ID()的结果是不同的;而在两个连接中执行select max(id)的结果是相同的。
(4)python获取MySQL自增ID代码三种实现:
Python通过MySQLdb向MySQL读写数据,如果表中含有自增主键,想要获取本次插入数据的ID代码如下:
# -*- coding: UTF-8 -*- import sys reload(sys) sys.setdefaultencoding("utf-8") import MySQLdb import json class Mysql(): def return_id(self): conn = MySQLdb.connect(host=self.__my_host, user=self.__my_user, passwd=self.__my_passwd, db=self.__my_db, port=int(self.__my_port), charset=self.__my_charset) cursor = conn.cursor() # 代码块A user_id = 10010 name = "Tom" sql_insert = "insert spark_db.stu_info(user_id,name) values ('%s','%s')" % (str(user_id), str(name)) rs = cursor.execute(sql_insert) # # 代码块B # sql_update = "update spark_db.stu_info set name ='%s',user_id= '%s' where id = 40 " % (str('张三'),str(2000) ) # rs = cursor.execute(sql_update) print "此次操作影响的行数为: rs", rs # 此次插入操作影响的行数 # 方法一,使用insert_id()方法: 插入一条记录后,获取这条数据所在的自增ID print "使用insert_id()函数 ", print "conn.insert_id()", conn.insert_id() conn.commit() # 方法二,使用LAST_INSERT_ID()方法: 插入一条记录后,获取这条数据所在的自增ID print "使用LAST_INSERT_ID()函数 ", sql = ''' select LAST_INSERT_ID() ''' num = cursor.execute(sql) if num>0: print cursor.fetchall() # 方法三,使用max()方法: 插入一条记录后,获取这条数据所在的自增ID sql = ''' select max(id) from spark_db.stu_info''' print "使用max()函数 ", num = cursor.execute(sql) if num > 0: print cursor.fetchall() def test_main(): with open("./config/mysql.json", "r") as f: config_json = json.loads(f.read()) print "config_json\n", config_json mysql_client = Mysql(in_config_json=config_json['titan_db']) print "\n数据插入之前\n" num=mysql_client.execute_db("select * from spark_db.stu_info ") if num>0: print mysql_client.fetchall_db() print "\n数据插入操作\n" mysql_client.return_id() print "\n数据插入后\n" num = mysql_client.execute_db("select * from spark_db.stu_info ") if num > 0: print mysql_client.fetchall_db() if __name__ == '__main__': test_main()
代码块A的输出结果如下:
数据插入之前
({'user_id': 10010L, 'id': 27L, 'name': u'Tom'},)
数据插入操作
此次操作影响的行数为: rs 1
使用insert_id()函数 conn.insert_id() 29
使用LAST_INSERT_ID()函数 ((29L,),)
使用max()函数 ((29L,),)数据插入后
({'user_id': 10010L, 'id': 27L, 'name': u'Tom'}, {'user_id': 10010L, 'id': 29L, 'name': u'Tom'})
代码块B的输出结果如下:
数据插入操作
此次操作影响的行数为: rs 0
使用insert_id()函数 conn.insert_id() 0
使用LAST_INSERT_ID()函数 ((0L,),)
使用max()函数 ((41L,),)
所有返回自增ID只能是insert操作,而不是update操作
参考:https://blog.csdn.net/anan890624/article/details/50808515