【问题标题】:Updates in mysql transaction - isolationmysql 事务中的更新 - 隔离
【发布时间】:2016-06-20 01:13:46
【问题描述】:

我有以下型号

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]

【问题讨论】:

    标签: php mysql concurrency transactions


    【解决方案1】:

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

    1. 第一个事务开始
    2. UPDATE 衬衫 => 将在记录上设置排他锁
    3. 事务开始
    4. 第二事务尝试UPDATE衬衫。因为它需要获得一个记录锁,所以它会等待,因为这条记录已经被 first 事务锁定了
    5. 第一个事务提交,第二个事务将恢复执行并查看更新的记录

    当然它只与 InnoDb 和类似的 mysql 引擎有关。 请注意,您很幸运能够以相同的顺序遍历记录。如果不是这样,您可能会遇到deadlock

    【讨论】:

    • 谢谢你!所以行锁一直存在,直到事务没有提交或回滚,即使我没有使用 select for update 明确要求它?
    • 非常感谢!你是对的。我刚刚做了一些原型设计,并按照您的描述工作。
    猜你喜欢
    • 1970-01-01
    • 2011-12-17
    • 2011-02-24
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多