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.
Related
I have to execute a set of prepared queries to load data in the DB (this load data dealys about 3 hours), and I'm searching the way of blocking the database while the script is executing because if other client executes any update or insert is possible that the info integrity will be break.
How can I do this?.
Thanks.
If I understood you correctly, by "block" you mean terminate your connection so that no other queries can take place. Here is how you terminate your connection in MySQLi:
for MySQLi Procedural:
mysqli_close($conn);
for MySQLi Object-oriented:
$conn->close();
In both cases, $conn is the variable that stored the connection made.
In terms of security, I don't see this being an issue because it would only be a security issue if someone had access to your $conn object, and that object is safely stored in your PHP code. Well how safe depends on so many other factors, but I hope I at least answered your initial question :)
What you are looking for is called "table locking". You may read it up on google.
You may lock either entire table or a certain row, depends on your need.
After locking a table, no other client will be able to do a locked operation on it. You may start reading from here: https://dev.mysql.com/doc/refman/5.5/en/innodb-lock-modes.html
mysqli_insert_id() is specific to the database connection -- it returns the ID of the row that this script invocation inserted most recently, not any other MySQL client. So there's no conflict if multiple applications are inserting into the database at the same time.
I am confused in 2 things first one is
specific to the database connection
and second thing
MySQL client
Please is there anyone who can explian that how mysql connections work for different clients or how these clients behave in any Application. I am sorry if it is a riddiculous question but i am confused that why it is not reflected by the data entry at the same time.
specific to the database connection
Suppose I run a PHP script that inserts a row, and then calls mysqli_insert_id(), and it tells me it generated value 1234.
Next, you also run a separate PHP script that inserts a row to the same table. We assume it generated value 1235.
Then my PHP script, still running in the same request as before, calls mysqli_insert_id() again. Does it report 1235? No -- it still reports 1234, because it will tell me only the most recent id generated during my session.
If my PHP request finishes, and then I make another PHP request, and it connects to MySQL, this counts as a new connection. Mysqli_insert_id() reports nothing by default, unless I do a new insert.
MySQL client
In this context, a mysql client is for example the PHP script that makes a connection to MySQL during one request.
A MySQL client can also be the command-line mysql tool, or a GUI interface like MySQL Workbench, or another application written in PHP or another language. The term "MySQL client" is meant to include all of these. Each client makes a connection to the MySQL database server, and each connection has its own idea of what the last insert id was.
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'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.
I google the mysql_insert_id, about the thread safe concern... ...I am worrying about I only have a one MySQL user to connect DB, so, I think mysql_insert_id is not very safe for my application. Is there any "safer" method for returning last insert id from MySQL? thank you.
As long as no two threads share one database connection you should not get any wrong ids. mysql_insert_id is stored per connection, not per user.
There is no safer method and you don't need any. mysql_insert_id() in PHP or SELECT LAST_INSERT_ID() returns the last ID per your current connection, not per user account, so you are perfectly safe here.