【发布时间】:2012-07-09 20:21:32
【问题描述】:
如果例如当用户单击链接时,会自动插入新行,然后php代码请求最后插入的id,同时插入另一行另一个用户,所以返回的 id 实际上不是我期望的那个..?
我错了吗?有没有办法在没有“安全”漏洞的情况下做同样的事情?
(比如可能来自准备好的声明或其他东西......)
P.S id 是自动生成的。
谢谢。
【问题讨论】:
标签: php mysql database pdo lastinsertid
如果例如当用户单击链接时,会自动插入新行,然后php代码请求最后插入的id,同时插入另一行另一个用户,所以返回的 id 实际上不是我期望的那个..?
我错了吗?有没有办法在没有“安全”漏洞的情况下做同样的事情?
(比如可能来自准备好的声明或其他东西......)
P.S id 是自动生成的。
谢谢。
【问题讨论】:
标签: php mysql database pdo lastinsertid
如manual中提到的:
LAST_INSERT_ID()(不带参数)返回一个BIGINT(64 位)值,该值表示 第一个自动生成的值,该值由 most 为AUTO_INCREMENT列设置最近执行了INSERT语句来影响这样的列。例如,插入一行生成AUTO_INCREMENT值的行后,可以得到这样的值:mysql>SELECT LAST_INSERT_ID(); ->195当前执行的语句不影响
LAST_INSERT_ID()。假设您生成一个AUTO_INCREMENT值 用一个语句,然后参考LAST_INSERT_ID()多行INSERT将行插入到表中的语句 拥有AUTO_INCREMENT列。LAST_INSERT_ID()的值将保持不变 在第二个语句中稳定;第二次及以后的价值 rows 不受早期行插入的影响。 (但是,如果你 混合对LAST_INSERT_ID()和LAST_INSERT_ID(expr)的引用,即 效果未定义。)如果前面的语句返回错误,则值为
LAST_INSERT_ID()未定义。对于事务表,如果 语句由于错误而回滚,值为LAST_INSERT_ID()未定义。对于手动回滚,值LAST_INSERT_ID()没有恢复到交易前的状态;它 保持在ROLLBACK 的位置。
所以,LAST_INSERT_ID() 始终是事务安全的(即使您不使用事务)。
【讨论】:
lastInsertId() 由 PDO 驱动程序本身提供,可能是也可能不是对 SELECT LAST_INSERT_ID(); 的实际 SQL 查询。虽然这可能仍然完全正确,但仅基于此还不能确定!
在成功INSERT 后,MySQL 服务器将插入 ID 作为OK 消息的一部分传输。此 ID 存储在 PDO 中,因此无需往返服务器 PDO 就可以安全地为您的连接返回正确的 ID。
参考:http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#OK_Packet
【讨论】:
为了解决这个问题,您可以使用transaction。
这基本上会将您的插入与其他插入隔离开,因此只要您的 Insert/lastInsertId() 调用在同一个事务中,它就可以正常工作。
【讨论】:
$dbh->beginTransaction(); 2) 插入代码 + lastInsertId() 3) $dbh->commit();
rollback :)
lastInsertId() 的底层功能是连接感知的。因此它将返回调用它的连接最后插入的 ID。如需更好的答案,请查看this one。