如果不使用显式事务,则为:
update tokens set tokens = tokens + 1保证在InnoDB中是原子的?
发布于 2011-12-07 06:58:25
我的理解是,在自动提交模式下(即“没有显式事务”),一条语句就是一条事务。因为根据定义,事务是原子的,所以您的单个语句也是原子的。
然而,当涉及到评估约束时,这不是在语句(即事务)级别上完成的,而是在处理语句时逐行执行。
如果在tokens列上有一个唯一的约束(索引),那么更新很可能会因此失败。引用同一个表的外键也是如此。
发布于 2011-12-07 06:29:59
我不这么认为,我没有我的MySQL隔离级别/小抄,但我认为它在每行级别上是原子的(UPDATE将使用范围锁IIRC),但不是在每表级别上。
现在,一个比更新是否是原子的更有趣的问题是,何时更新的非原子性是可观察的。答案是READ UNCOMMITTED隔离级别的单个语句可以观察到UPDATE的非原子性,READ COMMITTED隔离级别的单个事务中的一系列相关语句可以观察到不同的更新。REPEATABLE READ和SERIALIZABLE可以看到更新,就好像它们是原子的和一致的。
想象一下两个会话。会话A具有隔离级别SERIALIZABLE,并且在包含1000行的表中执行:UPDATE tokens SET tokens = tokens + 1。
假设会话B具有隔离级别READ UNCOMMITTED并且未提交此select可以看到部分更新(即:某些行已更新而其他行不是updated).
SELECT sum(tokens) FROM tokens SELECT sum(tokens) FROM tokens此select不能看到部分更新,因此它将该更新视为具有隔离级别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 sum(tokens) FROM tokens WHERE id BETWEEN 1 AND 100; SELECT sum(tokens) FROM tokens WHERE id BETWEEN 501 AND 600,然后某些程序逻辑将这两个值相加,这些选择看不到不同的MVCC快照,它们看到相同的更新,https://stackoverflow.com/questions/8406922
复制相似问题