MVCC:多版本并发控制

MVCC

  • [1. MVCC是什么](#1. MVCC是什么)
  • [2. 快照读和当前读](#2. 快照读和当前读)
    • [2.1 快照读](#2.1 快照读)
    • [2.2 当前读](#2.2 当前读)
  • [3. Read View](#3. Read View)
    • [3.1 Read View中含有什么内容](#3.1 Read View中含有什么内容)
    • [3.2 ReadView的规则](#3.2 ReadView的规则)
  • [4. MVCC整体操作流程](#4. MVCC整体操作流程)

1. MVCC是什么

  • MVCC(Multi Version Concurrency Control),多版本并发控制;
  • MVCC用于解决读-写并发问题,避免发生脏读、幻读等问题;
  • MVCC通过数据行的多个版本管理实现并发控制;
  • MVCC使InnoDB的事务隔离级别下一致性读操作得到保证,即在查询一些被其他事务正在修改的数据时,不用进入等待,而是直接读取数据被更新之前的值;
  • 不同数据库对MVCC的实现方式可能不同,且MySQL数据库中只有InnoDB引擎支持MVCC;
  • MVCC的实现依赖于:1)行记录的隐藏字段;2)Undo Log;3)Read View;
  • MVCC只针对读已提交和可重复读两种隔离级别起作用;

2. 快照读和当前读

  • MVCC锁解决的读-写冲突问题中,读指快照读;

2.1 快照读

  • 快照读即一致性读,读取的是快照数据,而非当前最新数据;
  • 不显式加锁的SELECT即属于快照读;
  • 快照读可使得即使存在读-写冲突,也可以在不加锁的情况下,实现并发读,提高并发性能;
  • 快照读基于多版本管理控制,有时读到的不一定是最新数据,有可能是之前的历史版本;
  • 快照读的前提是事务隔离级别不是串行化,否则快照读退化为当前读;

2.2 当前读

  • 当前读指读取最新数据,读取时需要保证其他事务不能对数据进行修改,因此需要对数据加锁;
  • 显式加锁的SELECT或对数据进行增删改操作都会执行当前读;

3. Read View

  • MVCC通过Read View管理Undo Log中记录的可见性,确定当前事务需要读取记录的对应版本;
  • 记录中含有三个隐藏字段:1)row_id:用于特殊情况下构建聚簇索引;2)trx_id:事务id,表示对该记录进行更新的最近事务ID;3)roll_pointer:回滚指针,用于将记录回滚到指定历史版本;
  • 记录的历史版本通过Undo Log构建,多个事务对于同一记录的修改会以Undo Log的形式保存下来,且这些log会以链表形式(通过记录中的回滚指针连接)存在,如:
  • 事务开启之时,会对当前数据库系统生成一个快照,该快照就是Read View,其中维护如:1)产生该Read View的事务ID;2)产生当前Read View时,系统中的活跃事务ID;等信息;
  • Read View的主要作用是在记录对应版本链中确认哪些版本对于当前事务是可见的;
  • 注意MVCC用于解决读-写冲突,只对应于读已提交和可重复读两种隔离级别,因此Read View的具体生成与隔离级别有关:
    1)隔离级别为读已提交时,可解决脏读问题,所以对于每一次的SELECT查询均会生成对应的Read View;
    2)隔离级别为可重复读时,可解决脏读、不可重复读以及幻读问题,所以对于某事务中的多次SELECT查询只会在第一次时生成对应的Read View;

3.1 Read View中含有什么内容

  • creator_trx_id :创建这个 Read View 的事务 ID(只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0);
  • trx_ids :表示在生成ReadView时当前系统中活跃的读写事务的事务id列表 ;
  • up_limit_id :活跃的事务中最小的事务 ID;
  • low_limit_id :表示生成ReadView时系统中应该分配给下一个事务的 id 值,low_limit_id 是系
    统最大的事务id值

3.2 ReadView的规则

访问某条记录时,通过ReadView,只需要按照下边的步骤判断记录的某个版本是否可见:

  • 如果被访问版本的trx_id 属性值与ReadView中的 creator_trx_id相同,意味着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问;
  • 如果被访问版本的trx_id 属性值小于 ReadView中的 up_limit_id 值,表明生成该版本的事务在当前事务生成ReadView前已经提交,所以该版本可以被当前事务访问;
  • 如果被访问版本的trx_id 属性值大于或等于 ReadView中的 low_limit_id 值,表明生成该版本的事务在当前事务生成ReadView后才开启,所以该版本不可以被当前事务访问;
  • 如果被访问版本的trx_id 属性值在ReadView的 up_limit_idlow_limit_id 之间 ,那就需要判断一下trx_id属性值是不是在 trx_ids 列表 中:
    1)如果在,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问;
    2)如果不在,说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问;

4. MVCC整体操作流程

当查询一条记录的时候,系统使用MVCC根据如下步骤进行读取:

  1. 首先获取事务自己的版本号,也就是事务 ID;
  2. 获取 ReadView;
  3. 查询得到的数据,然后与 ReadView 中的事务版本号进行比较;
  4. 如果不符合 ReadView 规则,就需要从 Undo Log 中获取历史快照;
  5. 最后返回符合规则的数据,如果没有找到符合规则的版本,则表示记录不存在;

参考《尚硅谷:康师傅》

相关推荐
山东布谷科技官方几秒前
布谷直播源码部署服务器关于数据库配置的详细说明
运维·服务器·数据库·直播系统源码·直播源码·直播系统搭建·直播软件开发
yanwushu1 分钟前
Xserver v1.4.2发布,支持自动重载 nginx 配置
mysql·nginx·php·个人开发·composer
爱吃喵的鲤鱼5 分钟前
linux进程的状态之环境变量
linux·运维·服务器·开发语言·c++
LuckyLay11 分钟前
Spring学习笔记_27——@EnableLoadTimeWeaving
java·spring boot·spring
易云码21 分钟前
信息安全建设方案,网络安全等保测评方案,等保技术解决方案,等保总体实施方案(Word原件)
数据库·物联网·安全·web安全·低代码
向阳121824 分钟前
Dubbo负载均衡
java·运维·负载均衡·dubbo
newxtc26 分钟前
【客观理性深入讨论国产中间件及数据库-科创基础软件】
数据库·中间件·国产数据库·国产中间件·科创
蓝眸少年CY27 分钟前
MySQL 【流程控制】函数
mysql
水月梦镜花29 分钟前
redis:list列表命令和内部编码
数据库·redis·list
DARLING Zero two♡32 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技