mysql - MySQL 隔离级别可重复读取和更新中的原子增量
问题描述
最近几个小时,我研究了有关不同 SQL 事务隔离级别的文档,发现 MySQL 默认使用可重复读取隔离,并做了一些实验。据我了解,正在进行的事务中的选择应该看到相同的数据,除非同一事务对其进行更新。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
为什么更新使用的值与选择返回的值不同?想象一下,我会做一个选择,并在更新行之后将返回的值增加一个。我会得到不同的结果。
解决方案
右侧列上的连接中的 UPDATE 操作阻塞,直到左侧的事务完成。如果您想在两个连接上进行可重复读取,则需要在两个连接上都使用 BEGIN / COMMIT。
推荐阅读
- python-3.x - 如何使用 Firefox 驱动程序在 Python selenium 中处理多个窗口
- android - 每个实体的 Android MVVM ViewModel 和存储库?
- javascript - 将两个对象数组合并在一起es6
- r - 如何将 geom_text 标签正确定位到这些 geom_col 数据?
- javascript - Mozilla firefox 和 Internet Explorer 中的脚本错误加载失败
- python - python中的sql选择查询问题
- android - 使用 Espresso 按其在 ViewPager 中的位置匹配 RecyclerView
- android - WearableListenerService onCreate() 从未调用
- stm32 - stm32工厂引导加载程序可能被openocd覆盖?
- javascript - 无法编译使用 OpenLayers 的 TypeScript 代码