在InnoDB中'更新令牌设置tokens = tokens + 1'原子?

Lim*_*beh 11 mysql innodb thread-safety atomicity

不使用显式事务,是:

update tokens set tokens = tokens + 1
Run Code Online (Sandbox Code Playgroud)

保证在InnoDB中是原子的吗?

nin*_*alj 0

我认为不是。没有我的 MySQL 隔离级别/备忘单可用,但我认为它在每行级别上是原子的(更新将使用范围锁 IIRC),但不是在每个表级别上。

\n\n

现在,比 UPDATE 是否原子性更有趣的问题是 UPDATE 的非原子性何时是可观察的。答案是,READ UNCOMMITTED 隔离级别下的单个语句可以观察到 UPDATE 的非原子性,而 READ COMMITTED 隔离级别下的单个事务中的一系列相关语句可以观察到不同的更新。REPEATABLE READ 和 SERIALIZABLE 将 UPDATE 视为原子且一致的。

\n\n

想象一下两个会话。会话 A 具有 SERIALIZABLE 隔离级别,并且执行以下操作:UPDATE tokens SET tokens = tokens + 1在具有 1000 行的表中。

\n\n
    \n
  • 假设会话 B 的隔离级别为 READ UNCOMMITTED 并且执行SELECT sum(tokens) FROM tokens\xe2\x86\x92 此选择可以看到部分更新(即:某些行已更新,其他行未更新)。
  • \n
  • 假设会话 B 具有隔离级别 READ COMMITTED 并执行SELECT sum(tokens) FROM tokens\xe2\x86\x92 此选择无法看到部分更新,因此它看到 UPDATE 就好像它是原子的一样。
  • \n
  • 假设会话 B 具有隔离级别 READ COMMITTED 并执行此操作SELECT sum(tokens) FROM tokens WHERE id BETWEEN 1 AND 100; SELECT sum(tokens) FROM tokens WHERE id BETWEEN 501 AND 600,然后某些程序逻辑将这两个值添加到 \xe2\x86\x92 这些 SELECT 可以看到不同的 MVCC 快照 \xe2\x86\x92 不同的更新,
  • \n
  • 假设会话 B 具有隔离级别 REPEATABLE READ 并执行此操作SELECT sum(tokens) FROM tokens WHERE id BETWEEN 1 AND 100; SELECT sum(tokens) FROM tokens WHERE id BETWEEN 501 AND 600,然后某些程序逻辑将这两个值添加到 \xe2\x86\x92 这些 SELECT 无法看到不同的 MVCC 快照 \xe2\x86\x92 他们看到相同的更新,
  • \n
\n