Could PDO::lastInsertId() be inaccurate? [duplicate] - php

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.

Related

Confusion regarding the consistency of Last_insert_id [duplicate]

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.

MySQL Last Insert and multiple web servers [duplicate]

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.

How can I solve this Solr/MySQL race condition?

I'm experiencing a very strange problem whereby my Solr index is not able to see a change just written to a MySQL database on another connection.
Here is the chain of events:
The user initiates an action on the website that causes a row to be added to a table in MySQL.
The row is added via mysql_query() (no transactions). If I query the database again from the same connection I can naturally see the change I just made.*
A call is immediately sent to a Solr instance via curl to tell it to do a partial update of its index using the Data Import Handler.
Solr connects to the MySQL database via a separate JDBC connection (same credentials and everything) and executes a query for all records updated since its last update.
At this point, however, the results returned to Solr do not include the last-added row, unless I insert a sleep() call immediately after making the change to the database and before sending the message to Solr.
*Note that if I actually do query the database at this point though, this takes enough time for the change to actually be picked up by Solr. The same occurs if I simply sleep(1) (for one second).
What I'm looking for is some reliable solution that can allow me to make sure the change will be seen by Solr before sending it the refresh message. According to all documentation I've found, however, the call to mysql_query() should already be atomic and synchronous and should not return control to PHP until the database has been updated. Therefore there doesn't appear to be any function I can call to force this.
Does anyone have any advice/ideas? I'm banging my head over this one.
Check what the auto-commit is set to when inserting the record. Chances are the record just inserted is in the same database session and thus is seen (but isn't committed). After this, some event causes the commit to occur and hence another thread/session can then "see" the record. Also check the transaction isolation level settings.
I typically do not use the Data Import handler and would have the update in the website trigger a mechanism (either internal or external) to update the record into Solr using the appropriate Solr Client for the programming language being used. I have personally not had a lot of luck with the Data Import Handler in the past and as a result have preferred to use custom code for synchronizing Solr with the corresponding data storage platform.

Using MySQL last insert id for the same user

I'm using the mysql_insert_id within my code to get an auto increment.
I have read around and it looks like there is no race condition regarding this for different user connections, but what about the same user? Will I be likely to run into race condition problems when connecting to the database using the same username/user but still from different connection sessions?
My application is PHP. When a user submits a web request my PHP executes code and for that particular request/connection session I keep a persistent SQL connection open in to MySQL for the length of that request. Will this cause me any race condition problems?
None for any practical purpose, If you execute the last_id request right after executing your insert then there is practically not enough time for another insert to spoil that. Theoretically might be
possible
According to PHP Manual
Note:
Because mysql_insert_id() acts on the last performed query, be sure to
call mysql_insert_id() immediately after the query that generates the
value.
Just in case you want to double check you can use this function to confirm your previous query
mysql_info
The use of persistent connections doesn't mean that every request will use the same connection. It means that each apache thread will have its own connection that is shared between all requests executing on that thread.
The requests will run serially (one after another) which means that the same persistent connection will not be used by two threads running at the same time.
Because of this, your last_insert_id value will be safe, but be sure that you check the result of your inserts before using it, because it will return the last_insert_id of the last successful INSERT, even if it wasn't the last executed INSERT.

mysql_insert_id and mysql_pconnect

I've been using mysql_pconnect to establish all DB connections on my PHP site, with the theory that it's more efficient (debatable, I know).
I went to use mysql_insert_id to get the ID from a recent INSERT and it occurred to me that given the multi-threaded nature of web requests, I can't guarantee that another PHP script using the same pconnection has made a DB INSERT before my call to mysql_insert_id.
This is kind of a huge deal as I see no other way to guarantee atomicity of the INSERT and ID retrieval, as the ID is not returned by the INSERT query (or I don't know how to get it).
So basically I can never use mysql_pconnect if I want to have thread-safe INSERTS and ID retrieval?
mysql_insert_id() returns the last id within context of the current connection session. Thus avoiding race-condition problems. There's a bunch of notes/comments regarding this on the php.net manual for mysql_insert_id()
More Info:
PHP/MySQL insert row then get 'id'
How bad is using SELECT MAX(id) in MYSQL instead of mysql_insert_id() in PHP?
get id of last inserted record without using mysql_insert_id()
This should be easy to test:
<?php
// connection already established
mysql_query("INSERT INTO table VALUES('foo', 'bar')");
sleep(15);
echo mysql_insert_id();
Then see if you can fool it by slamming it with requests during the sleep period.. and check the insert_id results.
mysql_pconnect means that the connection won't be closed from the php module to the mysql.As there is an overhead of creating a new connection so it can be beneficial if you are creating a lot of connections.
As php executes a request in a single thread.And most probably you will be using 1 connection to the database a call to INSERT and subsequent call to ID retrieval is gonna be ATOMIC.
The MYSQL connection taken by 1 php thread can't be used by another php thread while it is still being in used which ensure atomicity.

Categories