mysql事务中的更新 - 隔离

时间:2016-06-20 01:13:46

标签: php mysql concurrency transactions

我有以下模型

Inventory [product_name, quantity, reserved_quantity]

带数据

[Shirt, 1, 0] 
[Shorts, 10, 0]

如果在多个线程中同时执行以下代码会发生什么?

 $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();

结果可能是吗?

[Shirt, 1, 2]
[Shorts, 10, 2]

1 个答案:

答案 0 :(得分:1)

不是。 让我们看看在以下场景中会发生什么:

  1. 第一个交易开始
  2. UPDATE 衬衫 =>将在记录上设置独占行锁
  3. 第二个交易开始
  4. 第二次交易尝试UPDATE 衬衫。由于需要获取记录锁定,因此该记录已被第一次事务锁定
  5. 第一个事务提交,第二个将恢复执行并查看更新的记录
  6. 当然它只与InnoDb和类似的mysql引擎有关。 请注意,您很幸运能够以相同的顺序遍历记录。如果不是这种情况,您可能会遇到deadlock