PDO + PHP lastInsertId() issue
-
20-06-2021 - |
题
Wouldn't there be a problem with it if for example when a user clicks on a link, a new row is automatically inserted and then the php code requests the last inserted id, and at the same time another row is inserted by another user, so the returned id is actually not the one I'm expecting..?
Am I wrong? Is there a way to do the same without that 'security' hole?
(like maybe from within the prepared statement or something...)
P.S the id is automatically generated.
Thank you.
解决方案
To counteract this you would use a transaction.
This would essentially isolate your insert from others, so as long as your Insert/lastInsertId()
call is within the same transaction, it will work just fine.
其他提示
As mentioned in the manual:
LAST_INSERT_ID()
(with no argument) returns aBIGINT
(64-bit) value representing the first automatically generated value that was set for anAUTO_INCREMENT
column by the most recently executedINSERT
statement to affect such a column. For example, after inserting a row that generates anAUTO_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 anAUTO_INCREMENT
value with one statement, and then refer toLAST_INSERT_ID()
in a multiple-rowINSERT
statement that inserts rows into a table with its ownAUTO_INCREMENT
column. The value ofLAST_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 toLAST_INSERT_ID()
andLAST_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 ofLAST_INSERT_ID()
is left undefined. For manual ROLLBACK, the value ofLAST_INSERT_ID()
is not restored to that before the transaction; it remains as it was at the point of the ROLLBACK.
So, LAST_INSERT_ID()
is always transaction-safe (even though you don't use transaction).
The MySQL Server transfers the insert ID as part of the OK
message after a successful INSERT
. This ID is stored in PDO, therefore without a round-trip to the server PDO can return you the correct ID for your connection in a safe way.
Reference: http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#OK_Packet