I have following model
Inventory [product_name, quantity, reserved_quantity]
with data
[Shirt, 1, 0]
[Shorts, 10, 0]
What happens if following code is executed in multiple threads at the same time?
$changes = [
['name' => 'Shirt', 'qty' => 1],
['name' => 'Shorts', 'qty' => 1],
];
$db->startTransaction();
foreach($changes as $change){
$rowsUpdated = $db->exec("UPDATE inventory
SET reserved_quantity = reserved_quantity + $change['qty']
WHERE product_name = $change['name']
and quantity >= reserved_quantity + $change['qty']");
if($rowsUpdated !== 1)
$db->rollback();
exit;
}
$db->commit();
Is it possible that the result will be?
[Shirt, 1, 2]
[Shorts, 10, 2]
It's not. Lets see what would be happening in the following scenario:
UPDATE
Shirt => an exclusive row lock will be set on the recordUPDATE
Shirt. As it would need to obtain a record lock it would wait as this record has already been locked by the first transactionOf course it's only relevant to InnoDb and similar mysql engines. Please note that you're lucky enough that traversing the records in the same order. If it were not the case you might run into a deadlock