SQL写锁是否使其他事务重新评估事务中的所有查询

Does SQL write lock makes other transactions re-evaluate all queries in the tranasction

我对数据库锁定还很陌生,有一个基本问题。我的理解是,任何 UPDATE 语句都会锁定 table 中的行,因此,没有其他事务可以 read/write 该行。如果是这样,请考虑一个场景:

初始 table:user_id = 1,计数 = 10

交易 1:
A: UPDATE table SET count = 20 WHERE user_id = 1

交易 2:
B. 变量 b = SELECT count FROM seats WHERE user_id = 1
C. 更新席位 SET count = {b} + 1 WHERE user_id = 1

如果执行顺序是:2B - 1A - 2C,那么table中count的结果是11还是21?

如果我的理解是正确的,当执行 1A 语句时,数据库会在阻止 2C 执行的那一行上放置一个写锁。现在我的问题是,一旦 1A 完成,

事务 2 将重新评估 T2 中与该锁定行相关的所有查询(2B 和 2C)-(这将重新评估值变量 b 到 20)
OR
只重新评估其阻塞的查询(2B) -(这意味着变量 b 仍将具有其旧值 10)?

编辑:
如果 2B 和 2C 嵌套查询怎么办?类似于:
UPDATE seats SET count = (SELECT count FROM seats WHERE user_id = 1) + 1 WHERE user_id = 1

答案是……视情况而定。由于您标记了 MySQL 我假设您正在使用该 DBMS。但是哪个引擎?让我们假设 InnoDB。

您是否明确开始交易?如果你不这样做,默认情况下 InnoDB 将处于 autocommit 模式(除非你重置它)。这意味着每个语句本身就是一个事务,因此序列 2B - 1A - 2C 将显示“错误”行为。

如果您在事务中显式包含 2B 和 2C,它仍然取决于隔离级别。 InnoDB 的默认隔离级别 REPEATABLE READ 将防止“错误”行为,这同样适用于 SERIALIZABLE(最保守的级别);但是两个更乐观的级别,READ COMMITTED 和 READ UNCOMMITTED,不会。

让我们按照您描述的顺序排列步骤:

Transaction 2:
B. variable b = SELECT count FROM seats WHERE user_id = 1

假设 b 现在的值为 10。

Transaction 1:
A: UPDATE table SET count = 20 WHERE user_id = 1

这会锁定该行,直到事务 1 完成。

Transaction 2:
C. UPDATE seats SET count = {b} + 1 WHERE user_id = 1

这也想要事务1持有的锁,所以事务2必须等待

Transaction 1:
D: COMMIT

事务 1 在提交时释放它的锁。

Transaction 2:
C. UPDATE seats SET count = {b} + 1 WHERE user_id = 1

它现在可以继续了,因为它想要的锁是空闲的。

该行现在的值为 20,因为事务 1 已提交。但是事务 2 的客户端在其变量 b 中仍然具有值 10,因此它将行更新为 10 + 1,即 11.

这会覆盖事务 1 设置的值。第三个事务可能会在事务 1 提交之后和事务 2 提交之前进行查询。然后它将读取值 20。但是一旦事务 2 提交,它很快就会被覆盖。