MySQL的LAST_INSERT_ID用法

[Net reference]


LAST_INSERT_ID() 自动返回最后一个INSERT或 UPDATE 查询中 AUTO_INCREMENT列设置的第一个表发生的值。


MySQL的LAST_INSERT_ID的注意事项:


第一、查询和插入所使用的Connection对象必须是同一个才可以,否则返回值是不可预料的。


mysql> SELECT LAST_INSERT_ID();


        -> 100


使用这函数向一个给定Connection对象返回的值是该Connection对象产生对影响AUTO_INCREMENT列的最新语句第一个AUTO_INCREMENT值的。这个值不能被其它Connection对象的影响,即它们产生它们自己的AUTO_INCREMENT值。


第二、LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID返回表b中的Id值。


第三、 假如你使用一条INSERT语句插入多个行,  LAST_INSERT_ID() 只返回插入的第一行数据时产生的值。其原因是这使依靠其它服务器复制同样的 INSERT语句变得简单。


mysql> INSERT INTO t VALUES


    -> (NULL, ‘Mary’), (NULL, ‘Jane’), (NULL, ‘Lisa’);


mysql> SELECT * FROM t;


| id | name |


+—-+——+


|  1 | Bob  |


|  2 | Mary |


|  3 | Jane |


|  4 | Lisa |


mysql> SELECT LAST_INSERT_ID();  //这就是我要说明的关键问题。


| LAST_INSERT_ID() |


|                2 |


虽然将3 个新行插入 t, 对这些行的第一行产生的 ID 为 2, 这也是 LAST_INSERT_ID()返回的值。


第四、假如你使用 INSERT IGNORE而记录被忽略,则AUTO_INCREMENT 计数器不会增量,而 LAST_INSERT_ID() 返回0, 这反映出没有插入任何记录。

一般情况下获取刚插入的数据的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。LAST_INSERT_ID是基于单个connection的, 不可能被其它的客户端连接改变。


在多线程50毫秒多线程并发情况下的测试结果:


对应输入:

thread1 before insert get 0
thread2 before insert get 0
thread0 before insert get 0

thread1 after insert get 132
thread0 after insert get 134
thread2 after insert get 133
thread1 before insert get 132 

thread0 before insert get 134
thread1 after insert get 135
thread2 before insert get 133
thread0 after insert get 136
thread2 after insert get 137
thread1 before insert get 135
thread0 before insert get 136
thread2 before insert get 137
thread1 after insert get 138
thread0 after insert get 139
thread2 after insert get 140
thread0 before insert get 139
thread1 before insert get 138
thread2 before insert get 140
thread0 after insert get 141
thread1 after insert get 142
thread2 after insert get 143
thread0 before insert get 141
thread1 before insert get 142
thread0 after insert get 144
thread2 before insert get 143
thread1 after insert get 145
thread2 after insert get 146
thread0 before insert get 144
thread1 before insert get 145
thread0 after insert get 147
thread2 before insert get 146
thread1 after insert get 148
thread2 after insert get 149
thread0 before insert get 147
thread1 before insert get 148
thread0 after insert get 150
thread2 before insert get 149
thread1 after insert get 151
thread2 after insert get 152
thread0 before insert get 150
thread1 before insert get 151
thread0 after insert get 153
thread2 before insert get 152
thread1 after insert get 154
thread2 after insert get 155
thread0 before insert get 153
thread1 before insert get 154
thread0 after insert get 156
thread2 before insert get 155
thread1 after insert get 157
thread2 after insert get 158
thread0 before insert get 156
thread0 after insert get 159
thread1 before insert get 157
thread2 before insert get 158
thread1 after insert get 160
thread2 after insert get 161


从中可以看出:

1、当connection初次实例化以后第一次用SELECT LAST_INSERT_ID() 是 0 ,而只有当持进行数据插入以后才会获得当前有效ID

2、从绿色部分可以看出,当这个connection插入数据以后到下一次插入数据之前就算有其他线程更改了数据表,那么这个connection持有的ID 也是原来的ID 而不是别的更改后的ID,直到这个connection再次插入数据才会再次更新。

因此通过这个测试验证了这个方法是在高并发情况下正确的。但是要注意多语句 插入情况。根据其特点需要灵活的代码处理,

你可能感兴趣的:(j2SE,insert,mysql,thread,多线程,reference,null)