MVCC真的一定能解决幻读么

前言

在Mysql里面我们知道事务的隔离级别从高到低依次是serializable(串行化)、REPETABLE---READ(可重复读)、Read Commit(读已提交)、 Read UnCommint(读未提交),并且如果不设置好事务的隔离级别的话,又回出现一系列的问题,如脏读、幻读、不可重复读的情况,从而会操成我们在业务逻辑查询的时候出现数据不一致的情况,最常见的问题就是支付、扣减、查询账户数据不一致的问题;

MVCC多版本并发机制

MVCC最主要是用来解决大部分数据库幻读的情况,在几种情况里面其实最难解决的就是数据的幻读,脏读和不可重复读的问题,通过设置RR隔离级别就可以实现;

快照读

这里有一个快照读的概念,相对另外的一个概念就是当前读,读取当前最新的数据,相当于在select 后面加了 for update 锁;

sql 复制代码
SELECT * FROM TABLE FOR UPDATE

这里的快照读,快照到底存在哪里呢,当然是存在Mysql的日志文件里面了,UndoLog当中,UndoLog是Mysql中的事务文件,会存储更新前的数据,需要回滚的时候会回滚到之前记录的快照数据;

隐式字段

数据库行记录的隐式字段,是除去我们定义可见字段的另外一些后台隐藏字段,其作用也是非常大的;

  • db_row_id:如果表中没有定义主键id,那么在生成的时候自动创建row_id隐藏主键;
  • db_trx_id:事务id,会记录最新一次修改的事务id
  • db_roll_ptr:回滚指针,指向UndoLog中上一个快照版本

Read View

Read View主要解决我们通过快照,具体应该找到哪个当前这个事务的快照,因为UndoLog会存储很多快照,需要读取本次事务的快照;

  • trx_ids:未提交事务的id列表
  • low_limit_id:下一个事务的id
  • up_limit_id:未提交事务的最小id
  • creator_trx_id:创建Read View事务id

开启事务,这个事务ID是自增长,事务大的ID可以看到事务小的ID的变更结果;

双RR隔离级别情景

场景一:

创建table_user表,插入3条数据

  1. 查询:

2. 新增:

sql 复制代码
begin;
insert into table_user(id,age,name,create_time) VALUES(null,19,'xxx',now());
commit;
  1. 再次查询: 原理上应该是查询到我们insert这条数据;
csharp 复制代码
select * from table_user where age>15 and age<22;

但是实际上查询到的还是之前的数据,由此可以见两个事务在没加锁的情况下,进行快照读,读到了之前的数据

场景二:

在之前场景下,后面我们在通过update语句更新表中那条之前插入的数据;

csharp 复制代码
//更新之前插入的数据
update table_user set name ='xxx0508' where age =19;

查询结果:

可以看到我们更新了插入的那条数据之前,再次查询发现可以查到之前插入的那条数据,这里通过UPDATE操作,其实就是触发当前读的操作,没做进行快照读,当前读可以看到通过update提交的数据。

分析

经过前面的场景二 的确在在查询的时候会出现幻读的情况,一个事务中既有快照读 、又有当前读是的确会产生幻读的;

总结

如果想真正意义上的解决幻读,要不就采用隔离级别的最高级别序列化,当前在性能方面会影响很大,并发场景效率及其的低,所以不推荐,要么就使用RC的隔离级别,在支持一定量并发的前提下,避免了死锁的发生,也是一种不错的选择; 如果用RR的级别,在事务开始前进行加锁,产生gap锁,也可以有效的避免幻读;

相关推荐
喪彪33 分钟前
MySQL新手教学
数据库·mysql·adb
他日若遂凌云志2 小时前
深入剖析 Fantasy 框架的消息设计与序列化机制:协同架构下的高效转换与场景适配
后端
快手技术2 小时前
快手Klear-Reasoner登顶8B模型榜首,GPPO算法双效强化稳定性与探索能力!
后端
二闹2 小时前
三个注解,到底该用哪一个?别再傻傻分不清了!
后端
用户49055816081252 小时前
当控制面更新一条 ACL 规则时,如何更新给数据面
后端
林太白2 小时前
Nuxt.js搭建一个官网如何简单
前端·javascript·后端
码事漫谈2 小时前
VS Code 终端完全指南
后端
该用户已不存在3 小时前
OpenJDK、Temurin、GraalVM...到底该装哪个?
java·后端
怀刃3 小时前
内存监控对应解决方案
后端
HMBBLOVEPDX3 小时前
MySQL的多版本并发控制(MVCC):
数据库·mysql·mvcc