【问题标题】:Does `UPDATE SET WHERE` have concurrency issues?`UPDATE SET WHERE` 有并发问题吗?
【发布时间】:2017-12-24 10:29:05
【问题描述】:

考虑下面的陈述

UPDATE SET is_locked = 1 WHERE id = 1 and is_locked = 0;

并发更新下是否存在一致性问题?为什么?

(MySQL 5.7,事务隔离级别为REPEATABLE-READ)

【问题讨论】:

    标签: mysql concurrency innodb


    【解决方案1】:

    不,它不需要,因为更新需要对正在更新的记录进行排他锁,而 innodb 一次不会授予超过 1 个记录的排他锁。

    【讨论】:

    • 谢谢。问题是我已经读过更新需要对包括参考手册在内的几个地方进行排他锁,但大多数都是为了使用 FOR UPDATE。我不确定在这种情况下 UPDATE 和 FOR UPDATE 之间是否有任何区别。
    • For update 子句与选择一起使用。下次请在您的问题中包含这些要点,而不是在单独的后续评论中。
    • 呃,根据使用情况不同,但这是一个完全不同的问题。
    • 他们都使用同一个排他锁吗?
    • 是的,它们确实使用相同的排他锁——不同之处在于用法。
    【解决方案2】:

    (针对某些 cmets)

    在许多(不是所有)情况下,这是要遵循的模式:

    BEGIN;
    SELECT ... FOR UPDATE;
    use the data from the SELECT to make decisions, then
    UPDATE the row(s) selected
    COMMIT.
    

    如果您离开FOR UPDATE,那么其他一些连接可能会潜入并更改行,只是让您的UPDATE 破坏这些更改。 (当然,也有“OK”的情况。)

    至于

    UPDATE tbl SET is_locked = 1 WHERE id = 1 and is_locked = 0;
    

    没有问题。该声明,无论您如何运行它,都是“原子的”。没有其他联系可以潜入并与您混淆。 (不过,它在逻辑上是幂等的,所以这不是问题。)

    “不管”是指autocommitBEGINtx_isolation_mode

    【讨论】:

      猜你喜欢
      • 2012-11-20
      • 2017-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多