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

时间:2011-12-06 21:13:13

标签: mysql thread-safety innodb atomicity

不使用显式交易,是:

update tokens set tokens = tokens + 1

保证在InnoDB中是原子的吗?

2 个答案:

答案 0 :(得分:1)

我的理解是在自动提交模式(即“没有显式事务”)中,单个语句是单个事务。由于事务是每个定义原子的,所以你的单个语句也是原子的。

但是,在评估约束时,不会在语句(即事务)级别上执行此操作,而是在处理语句时逐行执行。

如果tokens列上有唯一约束(索引),则该更新很可能因此而失败。引用同一个表的外键也是如此。

答案 1 :(得分:0)

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

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

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

  • 假设会话B的隔离级别为READ UNCOMMITTED且SELECT sum(tokens) FROM tokens→此选择可以看到部分更新(即:某些行已更新且其他行未更新)。
  • 假设会话B的隔离级别为READ COMMITTED且SELECT sum(tokens) FROM tokens→此选择无法看到部分更新,因此它将UPDATE看作是原子的。
  • 假设会话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然后某些程序逻辑添加这两个值→这些SELECT可以看到不同的MVCC快照→不同的更新,
  • 假设会话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然后某些程序逻辑添加这两个值→这些SELECT无法看到不同的MVCC快照→他们看到相同的更新,