The ID that was generated is maintained in the server on a per-connection basis.
LAST_INSERT_ID是基于单个connection的, 不可能被其它的客户端连接改变。
可以用 SELECT LAST_INSERT_ID(); 查询LAST_INSERT_ID的值.
Important: If you insert multiple rows using a single INSERT statement, LAST_INSERT_ID() returns the value generated for the first inserted row only.
使用单INSERT语句插入多条记录, LAST_INSERT_ID只返回插入的第一条记录产生的值. 比如mysql> INSERT INTO t VALUES (NULL, 'aaaa'), (NULL, 'bbbb'), (NULL, 'cccc'); mysql> SELECT * FROM t; +----+------+ | id | name | +----+------+ | 1 | Bob | | 2 | aaaa | | 3 | bbbb | | 4 | cccc | +----+------+ mysql> SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 2 | +------------------+
ID 2 是在插入第一条记录aaaa 时产生的.
LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。
一般情况下获取刚插入的数据的id,使用select max(id) from table 是可以的。
但在多线程情况下,就不行了。在多用户交替插入数据的情况下max(id)显然不能用。
这就该使用LAST_INSERT_ID了,因为LAST_INSERT_ID是基于Connection的,只要每个线程都使用独立的Connection对象,LAST_INSERT_ID函数将返回该Connection对AUTO_INCREMENT列最新的insert or update操作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。
mysql的last_insert_id()是不是可靠的
mysql的last_insert_id()不可靠 Mysql的API有个很有意义的函数last_insert_id()。这个函数的作用是,针对auto_increment字段,返回给定的 数据库链接,上一步 INSERT 查询中产生的 AUTO_INCREMENT 的 ID 号。如果没有指定数据库链接,则使用上一个打开的连接。 很多人质疑last_insert_id()是否是可靠的,以前我也犹豫过。 事实上的结果是mysql_insert_id决不会取错。首先做个测试,在mysql_query("insert.....);之后立刻sleep(1100),其间再做些其他的insert.
然后发现在mysql_insert_id取的值都不会和其他的冲突。 看了半天mysql的代码。mysql_insert_id是这么定义的my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql){ return mysql->;last_used_con->;insert_id;}
MYSQL是个结构体,里面包括数据库链接和一些当前数据库链接的状态值,其中在MYSQL结构体里面有insert_id,mysql_insert_id函数返回的就是结构体里面的这个值。
typedef struct st_mysql{ NET net; gptr connector_fd; char *host,*user,*passwd,*unix_socket,*server_version,*host_info,*info; char *db; struct charset_info_st *charset; MYSQL_FIELD *fields; MEM_ROOT field_alloc; my_ulonglong affected_rows; my_ulonglong insert_id; my_ulonglong extra_info; unsigned long thread_id; unsigned long packet_length; unsigned int port; unsigned long client_flag,server_capabilities; unsigned int protocol_version; unsigned int field_count; unsigned int server_status; unsigned int server_language; unsigned int warning_count; struct st_mysql_options options; enum mysql_status status; my_bool free_me; my_bool reconnect; char scramble[SCRAMBLE_LENGTH+1];
my_bool rpl_pivot; struct st_mysql* master, *next_slave; struct st_mysql* last_used_slave;
struct st_mysql* last_used_con; LIST *stmts; const struct st_mysql_methods *methods; void *thd; my_bool *unbuffered_fetch_owner;} MYSQL;
把insert_id理解成max(id)是错误的,因为有并发存在。结构体里面有insert_id是针对当前MYSQL连接的,而每次mysql_query操作在mysql服务器上可以理解为一次“原子”操作。