首页 > 解决方案 > MySQL 隔离级别可重复读取和更新中的原子增量

问题描述

最近几个小时,我研究了有关不同 SQL 事务隔离级别的文档,发现 MySQL 默认使用可重复读取隔离,并做了一些实验。据我了解,正在进行的事务中的选择应该看到相同的数据,除非同一事务对其进行更新。update table set age=age+1 where id=1我在使用原子增量(例如)时发现了不可重复的读取。

我的测试表由两列idage一个条目组成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 

为什么更新使用的值与选择返回的值不同?想象一下,我会做一个选择,并在更新行之后将返回的值增加一个。我会得到不同的结果。

标签: mysqlsqlisolation-level

解决方案


右侧列上的连接中的 UPDATE 操作阻塞,直到左侧的事务完成。如果您想在两个连接上进行可重复读取,则需要在两个连接上都使用 BEGIN / COMMIT。


推荐阅读