This question already has answers here:
Is it possible for mysqli_insert_id to return an incorrect id in high traffic applications?
(5 answers)
Closed 9 years ago.
I am to the point now where I need to scale to multiple web servers plus a db server, instead of hosting mysql, and the site on the same box.
I use 'mysqli_insert_id' in php to return a key value for another following operation. As I scale out and more users hit the site, is this still a reliable method for getting the last insert ID? If for some reason, two requests hit almost simultaneously, is there any chance that using mysqli_insert_id could return the wrong insert ID since both inserts and select calls would happen seemingly instantly?
From the MySQL Documentation:
For LAST_INSERT_ID(), the most recently generated ID is maintained in
the server on a per-connection basis. It is not changed by another
client. It is not even changed if you update another AUTO_INCREMENT
column with a nonmagic value (that is, a value that is not NULL and
not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns
simultaneously from multiple clients is perfectly valid. Each client
will receive the last inserted ID for the last statement that client
executed.
So yes, mysqli_insert_id will remain a reliable method for getting the last insert ID.
Related
I'm trying to make some SQLÂ Server code also run on MySQL, and I just hit this land mine. Google says the normal approach is to simply do your insert and then select last_insert_ID() to find out what got written.
This does not strike me as safe in a multi-user environment, though. There's a narrow window there where another user could insert something and cause a bad return value. How do I safely insert and obtain the key of the inserted record?
From LAST_INSERT_ID(), LAST_INSERT_ID(expr)
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions.
So unless your inserts for multiple users would happen to be made over the same database connection, you have nothing to worry about.
This is a problem that has been haunting me for some time. I have a PHP Web application built on Zend. For a particular feature, I have around 10-20 MySQL queries that get executed within a transaction. Out of these queries, some queries are used to delete values and others to insert values. 99% of the time everything works perfectly. But every now and again, some values are not inserted into the tables. I tried the following to debug this but to no avail:
Logged all MySQL queries by setting log = /var/log/mysql/mysql.log in my.cnf file. The necessary queries are being logged and when I execute them manually, the insert takes place correctly.
Checked the return value after the insert and it returns the primary key of the table.
Checked using newrelic if there was any unusual traffic on the server at these instances, but found out that it was ok
It does not seem to be an issue with the code and I am somehow inclined to believe that it has to be some issues with the MySQL DB.
Updated
Another strange thing that I want to mention with regards to this is:
In one table the primary key is auto-incremented. After the insert; the return value gives me the auto incremented value in the log (eg: 32363). But when I check the table, I can find 32362 and 32364, but not 32363.
This question already has answers here:
MySQL and PDO: Could PDO::lastInsertId theoretically fail?
(2 answers)
Closed 8 years ago.
I've got a page calling a script via AJAX which could be asynchronously called multiple times simultaneously from the same parent page. This script uses require_once to access a configuration script with the database handler. Will the script call a unique instance of this handler each time, or if multiple copies are open will they all be using the same instance and causing undesirable results when I attempt to get the ID of the last insert from that instance of the script?
Just to be clear, this is the command I'm referencing:
$DBH->lastInsertId()
Thanks!
The documentation says
This method may not return a meaningful or consistent result across different PDO drivers, because the underlying database may not even support the notion of auto-increment fields or sequences.
That being said, I've never had a problem using lastInsertId with MySQL. It's always worked.
This ostensibly wraps a call to MySQL's LAST_INSERT_ID()
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client.
i.e. it should be safe to use even if you are facing frequent requests.
$DBH->lastInsertId() retrieves, in case of MySQL, the result of last_insert_id() function.
The last_insert_id() is session based, which means that if you have 2 PHP scripts running, you will only get the ones last_insert_id that were generated by each script.
The ID that was generated is maintained in the server on a
per-connection basis. This means that the value returned by the
function to a given client is the first AUTO_INCREMENT value generated
for most recent statement affecting an AUTO_INCREMENT column by that
client. This value cannot be affected by other clients, even if they
generate AUTO_INCREMENT values of their own. This behavior ensures
that each client can retrieve its own ID without concern for the
activity of other clients, and without the need for locks or
transactions.
MySQL and PDO: Could PDO::lastInsertId theoretically fail?
As noted in the documentation:
Note: This method may not return a meaningful or consistent result
across different PDO drivers, because the underlying database may not
even support the notion of auto-increment fields or sequences.
I am having a problem with my web application that I've built.
It takes and processes customer orders through a web service.
Now, it does a check of MySQL to make sure this order hasn't been processed before, but lately, we have been getting some duplicates. The time between these two orders is 1 millisecond apart.
I know this is my application and I should know this, but it is more of a generic question:
Is it possible that the 1 millisecond difference could be the difference between MySQL writing a record to its database, and my application checking for that record? If MySQL was taking this time to write its record, I can see that it would be possible for 2 duplicate orders to sneak through.
It appears that it is allowing duplicates because it is checking if the order already exists, and determines that it doesnt.
If so- are there any better ways of preventing duplicates from coming into my system?
You need to check whether the order exists and conditionally insert it in a single transaction.
If you first perform a SELECT and separately an INSERT, you leave a window open where the same INSERT can happen.
If you use a unique index on a field that makes your orders unique (e.g. Order ID), the second attempt to insert the same data would fail in a manner that you could gracefully handle.
Is it possible to queue client requests for accessing database in MySQL. I am trying to do this for concurrency management. MySQL Locks can be used but somehow I am not able to get the desired outcome.
Effectively what I am trying to do is:
INSERT something in a new row
SELECT a column from that row
Store that value in a variable
The issue comes up when two different clients INSERT at the same time, thus variables for both clients store the value of the last INSERT.
I worked the following alternative, but it failed in a few test runs, and the bug is quite evident:
INSERT
LOCK Table
SELECT
Store
UNLOCK
Thanks!
My best guess is that you have an auto-increment column and want to get its value after inserting a row. One option is to use LAST_INSERT_ID() (details here and here).
If this is not applicable, then please post some more details. What exactly are you trying to do and what queries are being fired?