PDO + PHP的lastInsertId()问题

3
如果例如当用户点击链接时,自动插入一行新记录,然后PHP代码请求最后插入的ID,并且同时有其他用户插入另一行记录,这样返回的ID实际上可能不是我期望的ID,那么这会造成问题吗? 我错了吗?有没有一种方法可以在不产生“安全漏洞”的情况下完成相同的操作?(例如从准备好的语句中或其他方法...)P.S ID是自动生成的。谢谢。
3个回答

5

正如手册中所提到的:

LAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value representing the first automatically generated value that was set for an AUTO_INCREMENT column by the most recently executed INSERT statement to affect such a column. For example, after inserting a row that generates an AUTO_INCREMENT value, you can get the value like this:

mysql>SELECT LAST_INSERT_ID();
    ->195

The currently executing statement does not affect the value of LAST_INSERT_ID(). Suppose that you generate an AUTO_INCREMENT value with one statement, and then refer to LAST_INSERT_ID() in a multiple-row INSERT statement that inserts rows into a table with its own AUTO_INCREMENT column. The value of LAST_INSERT_ID() will remain stable in the second statement; its value for the second and later rows is not affected by the earlier row insertions. (However, if you mix references to LAST_INSERT_ID() and LAST_INSERT_ID(expr), the effect is undefined.)

If the previous statement returned an error, the value of LAST_INSERT_ID() is undefined. For transactional tables, if the statement is rolled back due to an error, the value of LAST_INSERT_ID() is left undefined. For manual ROLLBACK, the value of LAST_INSERT_ID() is not restored to that before the transaction; it remains as it was at the point of the ROLLBACK.

因此,LAST_INSERT_ID()始终是事务安全的(即使您不使用事务)。

lastInsertId()是由PDO驱动程序本身提供的,可能是一个实际的SQL查询语句,也可能不是。虽然这可能仍然完全正确,但仅凭这个还不够确定! - Rudi Visser

4

3
为了解决这个问题,您需要使用事务
这将从根本上隔离您的插入操作,只要您的Insert/lastInsertId()调用在同一事务中,它就能正常工作。

所以应该是这样的,对吧?:1)$dbh->beginTransaction(); 2)插入代码 + lastInsertId() 3)$dbh->commit(); - Asaf
1
@xTCx 没错;如果在事务中出现了问题,你还可以选择回滚(rollback)来撤销你所做的操作 :) - Rudi Visser
3
如果不是完全错误,那么这个答案就存在误导。lastInsertId() 的基本功能与连接相关,它将返回调用它的连接中最后插入的 ID。请参考此答案,以获得更好的解答。 - Adi
3
A- 我同意你的评论。 B- OP没有提到事务。建议人们实现事务来解决不存在的问题是荒谬的。虽然总体上你确实提供了有用的建议,但在这个问题的背景下,你的回答并不实用。 - Adi
@Adnan 我不同意;他询问了一种不会出现问题的方法 - 我建议使用事务来解决这个问题。这样做可以解决问题,因此答案是完全有效的。 - Rudi Visser
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接