MYSQL进阶-InnoDB引擎之MVCC

MVCC多版本并发控制基本概念

当前读

读取的是记录的最新版本,读取时要保证其他并发事务不能修改当前记录,会对当前记录加锁。比如日常操作中的:

  • select... lock in share mode (共享锁/读锁)
  • select... for update (写锁)
  • insert
  • delete
  • update

快照读

MVCC的作用:在快照读的时候通过MVCC查找对应的历史版本

简单的select... 不加锁就是简单的快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。不同隔离级别快照不同

  • read committed :每次select都生成一个读快照
  • repeatable read:开启事务后第一个select语句才是快照读的地方
  • serializable :快照会退化为当前读,每次读取到的都是最新的记录

MVCC实现原理

记录中的隐藏字段

  • DB_TRX_ID:(自增)最近修改事务ID,记录插入这条记录或者最后一次修改该记录的事务ID
  • DB_ROLL_PTR:回滚指针,指向这一条记录的上一个版本,配合undo log,指向上一个版本
  • DB_ROW_ID:隐藏主键,如果表结构没有主键,将会生成该隐藏字段

进入mysql文件目录,进入对应数据库目录,使用mysql提供的命令查看表结构,例如查看stu表空间文件:

ibd2sdi stu.ibd

在返回的columns中可见隐藏字段

undo log

  • 回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志
  • 当insert的时候,产生的undo log日志只在回滚时需要,当事务提交后,可被立即删除。
  • 而当update、delete的时候,产生的undo log不仅在回滚时需要,在快照读时也需要,不会被立即删除。

undo log版本链

 

不同事务或者相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表尾部是最早的旧记录。

readview

readview读视图,是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务( 未提交的)ID

readview中包含了四个核心字段(属性):

字段 含义
m_ids 当前活跃的事务ID集合
min_trx_id 最小活跃ID
max_trx_id 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
creator_trx_id readView创建者的事务ID

 

版本链数据访问规则:

不同的隔离级别,生成readview的时机不同:

READ COMMITTED: 在事务中每一次执行快照读时生成readView

REPEATABLE READ: 仅仅在事务第一次执行快照读时生成ReadView,后续复用该readview

RC隔离级别下的分析

在事务中每一次执行快照读时生成readView

 

例:当事务5中执行第一个查询语句时,查到的记录是蓝色框的记录。

从版本链头开始判断是否符合访问规则:

 trx_id = 4 ,不符合第一条、第二条,符合第三条,不符合第四条。故需要找到上一个版本:

 trx_id = 3,不符合第一条、第二条,符合第三条,不符合第四条。继续找上一个版本:

 trx_id = 2,不符合第一条,但是符合第二条,故找到快照版本,事务5中第一条查询语句查询到的结果是该版本数据。

类似地,当事务5中执行第二个查询语句时,查到的记录是该版本数据:

 

RR隔离级别下的分析

仅仅在事务第一次执行快照读时生成ReadView,后续复用该readview

 

套用相同的规则,事务5第一次执行快照读和第二次执行快照读读到的数据都是该版本数据:

 

 总结:

 

posted @   mooonquakes  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示