当前位置: 首页 > news >正文

MVCC(多版本并发控制)机制

1. MVCC(多版本并发控制)机制

MVCC 的核心就是 Undo Log+ Read View,“MV”就是通过 Undo Log 来保存数据的历史版本,实现多版本的管理,“CC”是通过 Read View 来实现管理,通过 Read View 原则来决定数据是否显示。同时针对不同的隔离级别,Read View 的生成策略不同,也就实现了不同的隔离级别。

1.1. MVCC的概念

MVCC的概念:

MVCC(Multiversion Concurrency Control,多版本并发控制)是一种基于乐观锁思想实现事务隔离的技术,核心是:

  • 保存数据的多个版本(历史快照)
  • 读取时通过版本号判断是否可见,无需加锁

MVCC解决的问题:

  1. 读写之间阻塞的问题,通过 MVCC 可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。
  2. 降低了死锁的概率。这是因为 MVCC 采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。
  3. 解决一致性读的问题。一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。

快照读vs当前读:

类型

描述

是否加锁

快照读

读取的是历史版本(不加锁)

当前读

读取的是最新版本数据(加锁)

快照读示例:

SELECT * FROM player WHERE ...  -- 快照读(不加锁)

当前读示例:

SELECT * FROM player LOCK IN SHARE MODE;  -- 加锁读
UPDATE player SET ...                     -- DML 操作

1.2. MVCC 的实现原理(InnoDB中)

当查询一条记录的时候,系统如何通过多版本并发控制技术找到它:

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

InnoDB中存储记录的多个版本的方法:

1. 事务版本号(Transaction ID)

  • 每个事务启动时,InnoDB 分配唯一的递增事务 ID。
  • 用于判断操作先后顺序。

2. 行记录的隐藏列

InnoDB 的叶子段存储了数据页,数据页中保存了行记录,而在行记录中有一些重要的隐藏字段。

InnoDB 为每条记录维护隐藏字段:

字段名

含义

db_row_id

隐藏行 ID,用于创建聚集索引

db_trx_id

最后修改该行记录的事务 ID

db_roll_ptr

回滚指针,指向 Undo Log 的位置

3. Undo Log(撤销日志)

  • 用于保存行记录的历史版本。
  • 以链表形式连接历史版本,支持回滚和快照读取。

Read View 的作用与原理

1. Read View 定义:

  • 一个事务启动时生成的视图,记录当前活跃事务的 ID 列表。
  • 用于判断某行记录是否对当前事务可见。

2. Read View主要字段:

字段

含义

trx_ids

当前活跃事务 ID 集合(未提交事务)

low_limit_id

trx_ids 中最大事务 ID

up_limit_id

trx_ids 中最小事务 ID

creator_trx_id

当前事务 ID(即创建此 Read View 的事务)

3. Read View的可见性判断规则:

  • T < up_limit_id → 可见(提交早)
  • T > low_limit_id → 不可见(提交晚)
  • up_limit_id < T < low_limit_id
  • T ∈ trx_ids → 不可见(事务未提交)
  • T ∉ trx_ids → 可见(事务已提交)

4. 事务隔离级别下 Read View 行为

隔离级别

Read View 获取频率

是否避免不可重复读

读已提交

每次 SELECT 创建新 Read View

可重复读

第一次 SELECT 后复用 Read View

        1. 在隔离级别为读已提交(Read Commit)时,一个事务中的每一次 SELECT 查询都会获取一次 Read View。

如果 Read View 不同,就可能产生不可重复读或者幻读的情况。

        2. 当隔离级别为可重复读的时候,就避免了不可重复读,这是因为一个事务只在第一次 SELECT 的时候会获取一次 Read View,而后面所有的 SELECT 都会复用这个 Read View。

1.3. InnoDB解决幻读的方法

在可重复读的情况下,InnoDB 可以通过 Next-Key 锁 +MVCC 来解决幻读问题。

出现幻读的原因是在读已提交的情况下,InnoDB 只采用记录锁(Record Locking)。

InnoDB 三种行锁的方式:

  • 记录锁:针对单个行记录添加锁。
  • 间隙锁(Gap Locking):可以帮我们锁住一个范围(索引之间的空隙),但不包括记录本身。采用间隙锁的方式可以防止幻读情况的产生。
  • Next-Key 锁:帮我们锁住一个范围,同时锁定记录本身,相当于间隙锁 + 记录锁,可以解决幻读的问题。

在隔离级别为可重复读时,InnoDB 会采用 Next-Key 锁的机制,帮我们解决幻读问题。

相关文章:

  • C++双线程交替打印奇偶数(活泼版)
  • 【java】aes,salt
  • CAN通信波特率异常的危害
  • K M G T P E Z
  • SAR ADC 比较器噪声分析(一)
  • 数据结构 - 数相关计算题
  • RabbitMQ集群与负载均衡实战指南
  • Blob文件导出:FileReader是否必需?✨
  • 静态资源js,css免费CDN服务比较
  • Nacos | 三种方式的配置中心,整合Springboot3.x + yaml文件完成 0错误 自动刷新(亲测无误)
  • 【C语言】函数指针及其应用
  • C++中单例模式详解
  • 使用 C/C++ 和 OpenCV 调用摄像头
  • Codeforces Round 1025 (Div. 2)
  • C++哈希
  • 数据结构 --- 顺序表
  • grid网格布局
  • Linux基础开发工具
  • 委托从入门到入土
  • Vscode 解决 #include <> 找不到的问题
  • 徐州市鼓楼区建设局网站/网络推广是干什么的
  • 廊坊公司网站建设/韩国比分预测
  • 贵阳seo技术/宁波网站关键词优化代码
  • 模板网站做外贸好不好/中国十大广告公司排行榜
  • 建一个所在区域网站需要多少资金/广告联盟平台挂机赚钱
  • 广州微网站开发/seo实战教程