今天跟人讨论php高并发下的LAST_INSERT_ID的正确性问题,一开始大家都比较模糊,后来经过大家共同查询资料,对这个问题有了比较清晰的了解,特发此文,以为纪念。
首先看mysql中的LAST_INSERT_ID()的官方说法:
LAST_INSERT_ID()自动返回最后一个INSERT或UPDATE查询中AUTO_INCREMENT列设置的第一个表发生的值。
MySQL的LAST_INSERT_ID的注意事项:
第一、查询和插入所使用的Connection对象必须是同一个才可以,否则返回值是不可预料的。
第二、LAST_INSERT_ID是与表无关的,如果向表a插入数据后再向表b插入数据,LAST_INSERT_ID返回表b的Id值。 www.2cto.com
第三、假如你使用一条INSERT语句插入多个行, LAST_INSERT_ID() 只返回插入的第一行数据时产生的值。
第四、假如你使用 INSERT IGNORE而记录被忽略,则AUTO_INCREMENT 计数器不会增量,而 LAST_INSERT_ID() 返回0, 这反映出没有插入任何记录。
根据这四条原则,我们讨论的高并发网站访问时的插入后取自增长值其实主要是跟第一条规则和第二条规则有关。即要保证LAST_INSERT_ID的正确性,必须同一个connection,并且LAST_INSERT_ID要紧跟在insert中执行。所以如果是数据库缓存池公用connection可能会出问题,多线程操作在insert后面由执行了别的insert时也会出问题。
而php的数据库连接本身是页面级的,这样就保证了不会出现缓冲池的情况,然后php页面执行本身也是单线程的,这样就保证了顺序编写的LAST_INSERT_ID肯定是紧跟在insert之后执行的,中间不会有别的insert执行。 www.2cto.com
综上所述,php的页面级、单线程其实已经保证了mysql的LAST_INSERT_ID天然就是正确的,跟高并发并没有关系。即php中,mysql的LAST_INSERT_ID总是正确的,随便用把,没有问题的。
作者 赵开锦