慎用MySQL的LAST_INSERT_ID函数
2014-10-13 17:27:04 阿炯

本站赞助商链接,请多关照。 在应用中,需要得到刚插入或修改的一条数据的id,因为这个字段是该表内部生成的。自动返回最后一个INSERT或UPDATE查询中 AUTO_INCREMENT列设置的第一个表发生的值。

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

mysql> SELECT LAST_INSERT_ID();

产生的ID每次连接后保存在服务器中。这意味着函数向一个给定客户端返回的值是该客户端产生对影响AUTO_INCREMENT列的最新语句第一个AUTO_INCREMENT值的。这个值不能被其它客户端影响,即它们产生它们自己的AUTO_INCREMENT值。这个行为保证了能够找回自己的ID而不用担心受其它客户端的影响力,而且不需要加锁处理。

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

假如你使用一条INSERT语句插入多个行, LAST_INSERT_ID() 只返回插入的第一行数据时产生的值。

LAST_INSERT_ID 是与表无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID返回表b中的Id值,所以这个特点具有全局性。

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

mysql> INSERT INTO t VALUES (NULL, ‘Mary’), (NULL, ‘FreeOA’), (NULL, ‘Lisa’);

mysql> SELECT * FROM t;
| id | name |
| 1 | Bob  |
| 2 | Mary |
| 3 | FreeOA |
| 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是基于连接的,只要每个线程都使用独立的连接对象,LAST_INSERT_ID函数将返回该连接对AUTO_INCREMENT列最新的insert or update操作生成的第一个记录id。LAST_INSERT_ID是基于单个连接的, 不可能被其它的客户端连接所影响。

在实际的应用中,比如:某表中插入了一条记录,需要在其入库后,对其进行一点小的处理,采用了触发器实现,调用last_insert_id()函数时,返回的id确不是刚插入的记录的id(同一连接),所以在应用时用这个方法是不可取的。