首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL隔离级别可重复读取和更新中的原子增量

MySQL隔离级别可重复读取和更新中的原子增量
EN

Stack Overflow用户
提问于 2020-10-18 03:16:16
回答 2查看 132关注 0票数 3

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

我的测试表由两列idage以及一个条目1, 20组成。

在2个会话中运行以下命令,我得到一个不可重复的读取:

代码语言:javascript
复制
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。我会得到不同的结果。

EN

回答 2

Stack Overflow用户

发布于 2020-10-18 03:51:40

来自右侧列的连接的更新操作将阻塞,直到左侧的事务完成。如果您希望在两个连接上都使用可重复读取,则需要在两个连接上使用BEGIN / COMMIT。

票数 1
EN

Stack Overflow用户

发布于 2020-10-21 12:35:29

运行这类代码的正确方法是在第一个SELECT的末尾使用FOR UPDATE。如果没有它,你就是在自找麻烦,就像你发现的那样。

我认为发生的事情是(在右边的连接中):

  • 右侧的第二个SELECT执行了“可重复读取”,结果仅获得20个。
  • 更新发现已提交21个,因此将其更改为22。
  • 第三个SELECT new您已更改行,因此它重新读取它,得到22。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64406381

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档