带有“where”事务的单个更新语句安全吗?

use*_*646 6 mysql innodb

据我所知,单个更新语句是原子的,该行将在更新过程中被锁定。但是,当存在“何处”原因时,它仍然是原子的吗?

例如:

table: ABC
-------------
|colA | colB|
-------------
|123  | 0   |

--update 1
update ABC set colA=456, colB=1 where colB=0;

--update 2
update ABC set colA=556, colB=2 where colB=0;
Run Code Online (Sandbox Code Playgroud)

由于where原因,更新时会先检查colB值并找到表中的该行,然后锁定该行进行更新,对吧?如果同时执行更新1和更新2,是否有可能两者都成功执行并且其中一个覆盖另一个的值?

是不是像下面这样写比较好?

START TRANSACTION;
  update ABC set colA=456, colB=1 where colB=0;
COMMIT;
Run Code Online (Sandbox Code Playgroud)

Eva*_*oll 4

为了理智,我们只假设 inno

如果同时执行更新1和更新2,是否有可能两者都成功执行并且其中一个覆盖另一个的值?

不,这不是 MVCC 的工作原理。并且在事务中包装单个语句不会执行任何操作。它们实际上已经包含在交易中。

第一个事务将从 ABC 读取,使用行级锁挂起更新锁定它,使用更新后的值写入新行,并将其设置为表中的活动状态。

第二个事务将从 ABC 读取,如果该行被锁定,它将阻塞。如果没有,它将锁定待更新的行,用更新后的值写入新行,并将其设置为在新表上有效。如果它被锁定,它将等待直到锁释放并重新检查该行。

有趣的是,已提交读的默认隔离级别并不能防止幻写。因此,如果两个事务同时启动,它们都会从同一个快照中读取数据。但是,如果一个 txn1 写入更新,它实际上会修改 txn2 正在读取的快照。因此,虽然您无法读取修改后的数据(幻像读取),但当您尝试写入数据时,您正在与同一主副本进行交互。

建议:如果可能,升级到真实数据库

有关更多信息,请阅读MariaDB 上有关事务隔离的文档