MySQL可重复读的隔离机制下是否彻底解决了幻读?

答案:没有彻底解决。

一、什么是幻读?

同一事务内,当同一个查询在不同时间产生不同的结果集时,事务中就会出现幻读问题。

幻读 关注的是记录数量的不同。
不可重复读关注的是记录内容的不同。

二、快照读和当前读

InnoDB引擎的默认隔离级别是可重复读,它在很大程度上避免了幻读现象。两种场景下的解决方案:

  1. 针对快照读 :通过MVCC解决幻读。在可重复读的隔离级别下,事务执行中看到的数据,和该事务启动时第一个查询语句看到的数据是一致的。即使中途有其他事务插入数据,当前事务也是无法查询到的。
  2. 针对当前读 :通过next-key lock(记录锁+间隙锁)的方式解决了幻读。因为执行select ... for update语句时,会加上next-key lock,如果有其他事务在next-key lock锁的范围内插入一条记录,那么这个插入语句会被堵塞。

三、什么情况下仍会出现幻读?

  1. 快照读

    在可重复读隔离级别下,事务 A 第一次执行普通的 select 语句时生成了一个 ReadView,之后事务 B 向表中新插入了一条 id = 5 的记录并提交。接着,事务 A 对 id = 5 这条记录进行了更新操作,在这个时刻,这条新记录的 trx_id 隐藏列的值就变成了事务 A 的事务 id,之后事务 A 再使用普通 select 语句去查询这条记录时就可以看到这条记录了,于是就发生了幻读。

因为这种特殊现象的存在,所以我们认为 MySQL Innodb 中的 MVCC 并不能完全避免幻读现象。

  1. 当前读
    T1 时刻:事务 A 先执行「快照读语句」:select * from t_test where id > 100 得到了 3 条记录。
    T2 时刻:事务 B 往插入一个 id= 200 的记录并提交;
    T3 时刻:事务 A 再执行「当前读语句」 select * from t_test where id > 100 for update 就会得到 4 条记录,此时也发生了幻读现象。

要避免这类特殊场景下发生幻读的现象的话,就是尽量在开启事务之后,马上执行 select ... for update 这类当前读的语句,因为它会对记录加 next-key lock,从而避免其他事务插入一条新记录。

相关推荐
wangchunyu11435 分钟前
PostgreSQL 入门与实践:从零搭建一个 CRUD 应用
数据库·postgresql
涛思数据(TDengine)36 分钟前
从_找根因_到_搭系统_:工业 AI 实战直播(十、十一期)
大数据·数据库·人工智能·时序数据库·tdengine
qq_339191142 小时前
mysql磁盘占用排查,mysql存储空间占比统计,mysql判断哪张表占用磁盘空间大
数据库·mysql
东方护航数据恢复(深圳)2 小时前
SSD主控损坏后的芯片级提取:FTL映射表重建与NAND直读
大数据·数据库
光锥智能2 小时前
OceanBase领跑数字政府数据库选型:产品能力、市场潜力、技术潜力均居首
数据库·人工智能·oceanbase
风哥2号2 小时前
达梦DM数据库恢复工具FGDDU(FGEDU DM DUL)
数据库·达梦数据库·数据库恢复
2601_960017623 小时前
啤酒行业PLM突围战:一半科技以配方与工艺数字化重构酿造食品研发体系
数据库·科技·重构
GIS数据转换器3 小时前
智慧林草“一张图“平台
java·大数据·服务器·前端·javascript·数据库·人工智能
gis开发之家3 小时前
Spring Boot 4 深度解析,JdbcTemplate 实战——轻量级数据库操作方案
java·数据库·spring boot·后端