在过去的几个小时里,我研究了关于不同SQL事务隔离级别的文档,发现MySQL在默认情况下使用了可重复的读隔离,并做了一些实验。据我所知,正在进行的事务中的selects应该看到相同的数据,除非相同的事务对其进行更新。在使用原子增量(例如update table set age=age+1 where id=1)时,我发现了一个不可重复的读取。
我的测试表由两列id和age以及一个条目1, 20组成。
在2个会话中运行以下命令,我得到一个不可重复的读取:
Transaction 1 Transaction 2
--------------- -------------------
begin; begin;
select * from test; select * from test;
+----+-----+ +----+-----+
| id | age | | id | age |
+----+-----+ +----+-----+
| 1 | 20 | | 1 | 20 |
+----+-----+ +----+-----+
update test set \
age=age+1 where id=1;
select * from test; select * from test;
+----+-----+ +----+-----+
| id | age | | id | age |
+----+-----+ +----+-----+
| 1 | 21 | | 1 | 20 |
+----+-----+ +----+-----+
commit;
select * from test;
-- age = 20
update test set age=age+1 where id=1;
select * from test;
-- Expected age=21
-- got age=22 => Non-Repeatable Read 为什么更新使用的值与select返回的值不同?假设我执行了一次select操作,并在更新行之后将返回值递增1。我会得到不同的结果。
发布于 2020-10-18 03:51:40
来自右侧列的连接的更新操作将阻塞,直到左侧的事务完成。如果您希望在两个连接上都使用可重复读取,则需要在两个连接上使用BEGIN / COMMIT。
发布于 2020-10-21 12:35:29
运行这类代码的正确方法是在第一个SELECT的末尾使用FOR UPDATE。如果没有它,你就是在自找麻烦,就像你发现的那样。
我认为发生的事情是(在右边的连接中):
https://stackoverflow.com/questions/64406381
复制相似问题