I am using InnoDB and have the following table
officeRechNr
year | month | id |
------------------------
2016 | 7 | 2 |
2016 | 6 | 5 |
2016 | 5 | 6 |
My script works as follows:
Get id from officeRechNr from current year and month
Increase id by one and update in officeRechNr
Echo increased id
So if the script would be executed one after another, I would expect:
New id is 3
New id is 4
New id is 5
I assumed that this behaves differently when I execute the script parallel.
Here is my script:
$db = new mysqli("localhost","user","pass","db");
$year = date("Y");
$month = date("m");
$stmt = $db->prepare('SELECT zahl FROM officeRechNr WHERE jahr = ? AND monat = ?');
$stmt->bind_param('ii', $year, $month);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$number = $row['zahl'] + 1;
sleep(20);
$stmt = $db->prepare('UPDATE officeRechNr set zahl = ? WHERE jahr = ? and monat = ?');
$stmt->bind_param('iii',$number, $year, $month);
$stmt->execute();
echo "New id is $number";
I executed both scripts simultaneously, so I assumed $number must be equal to 3 for both scripts and then they sleep for 20 seconds. Therefore I would expect
New id is 3
New id is 3
to my surprise, the outcome was
New id is 3
New id is 4
I thought I need to write-lock the database to achieve this result, as explained in Lock mysql table with php.
Why did I not get the expected outcome? Does this script always return different id's - even if executed at exact same time?
It seems like your webserver is unable to execute more than one request at a time.
What this means, in practice, is that even if you open your script in two different times, the server will not execute the second request before the first one is finished.
The timeline looks like this:
Of course, in a production environment, a real webserver will execute multiple requests at once, which means your script is very unsafe.
Prefer using your database's builtin solutions for this (AUTO_INCREMENT
for MySQL, SERIAL
for PostgreSQL, etc).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With