InnoDB存储引擎对MVCC实现

news/2024/11/1 14:22:26/

MVCC(多版本并控制)

概念:MVCC 是一种并发控制机制。

作用:多个并发事务同时读写数据库时保持数据的一致性和隔离性

实现:在每个数据行上维护多个版本的数据来实现的。当一个事务要对数据库中的数据进行修改时,MVCC 会为该事务创建一个数据快照,而不是直接修改实际的数据行。

1、读操作

事务执行读操作的时候,会使用快照读取,事务不会读取其他事务尚未提交的修改。

2、写操作

事务执行写操作的时候,会生成一个新的数据版本,并将修改后的数据写入数据库。(原始版本的数据仍然存在,供其他事务使用快照读取)

3、事务提交和回滚
  • 事务提交后,所做的修改将成为数据库的最新版本,并且对其他事务可见。
  • 事务回滚时,所做的修改将被撤销,对其他事务不可见。
4、版本回收

防止数据库中的版本无限增长,MVCC会定期进行版本回收,从而释放空间。

总结:MVCC创建多个版本 和 使用快照读取来实现并发控制。读操作使用旧数据版本的快照,写操作创建新版本,并确保原始版本仍可以使用 。

一致性非锁定读

实现:加一个版本号 / 时间戳字段,查询时,将当前可见的版本号与对应记录的版本号进行对比,如果记录的版本号小于可见版本,则表示该记录可见。

多版本控制就是读非锁定读的实现。如果读取的行正在执行DELETEUPDATE操作,这时读取操作不会去等待行上锁的释放,InnoDB存储引擎会去读取行的快照(快照读)

锁定读

在锁定读下,读取的数据是数据的最新版本,这种读也被称为当前读,同时,锁定读会对读取到的记录加锁。

存在问题:如果是当前读,每次读取的都是最新数据,两次查询中间,如果有其他事务插入数据,就会导致幻读,所以,InnoDB在实现可重复读时,如果执行的是当前读,则会对读取的记录使用Next-key Lock,来防止其他事务在间隙间插入数据。

InnoDB 对MVCC的实现

在内部,InnoDB存储引擎为每行数据添加了三个隐藏字段

  • DB_TRX_ID(6字节):表示最后一次插入或更新该行的事务 id。此外,delete 操作在内部被视为更新,只不过会在记录头 Record header 中的 deleted_flag 字段将其标记为已删除
  • DB_ROLL_PTR(7字节) 回滚指针,指向该行的 undo log 。如果该行未被更新,则为空
  • DB_ROW_ID(6字节):如果没有设置主键且该表没有唯一非空索引时,InnoDB 会使用该 id 来生成聚簇索引

Undo-log(撤销日志)

作用:

  1. 事务回滚:事务回滚时用于将数据恢复到修改前的样子
  2. MVCC:当读取记录时,若该记录被其他事务占用或当前版本对该事务不可见,则可以通过undo log读取之前的版本数据,以此实现非锁定读

RC 和 RR隔离级别下MVCC的差异

在事务隔离级别 RCRR (InnoDB 存储引擎的默认事务隔离级别)下,InnoDB 存储引擎使用 MVCC(非锁定一致性读),但它们生成 Read View 的时机却不同

  • 在 RC 隔离级别下的 每次select 查询前都生成一个Read View (m_ids 列表)
  • 在 RR 隔离级别下只在事务开始后 第一次select 数据前生成一个Read View(m_ids 列表)

MVCC + Next-key Lock 防止幻读

InnoDB存储引擎在 RR 级别下通过 MVCCNext-key Lock 来解决幻读问题:

1、执行普通select,此时会以MVCC快照读的方式读取数据

在快照读的情况下,RR 隔离级别只会在事务开启后的第一次查询生成 Read View ,并使用至事务提交。所以在生成 Read View 之后其它事务所做的更新、插入记录版本对当前事务并不可见,实现了可重复读和防止快照读下的 “幻读”

2、执行 select…for update/lock in share mode、insert、update、delete 等当前读

在当前读下,读取的都是最新的数据,如果其它事务有插入新的记录,并且刚好在当前事务查询范围内,就会产生幻读!InnoDB 使用 Next-key Lock 来防止这种情况。当执行当前读时,会锁定读取到的记录的同时,锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读


http://www.ppmy.cn/news/1543605.html

相关文章

一种基于机器学习的面向内生安全系统的入侵修复方式

摘要:本文主要是根据上课老师所提供的题目以及平时上课的学习,结合自己的理解按照要求设计的一种基于机器学习等方法的面向内生安全系统的入侵修复方式和系统,虽然大部分只是一种猜想并未实际实现,但是所体现的创新性等也是有可取…

Lua 函数

Lua 函数 Lua 是一种轻量级的编程语言,广泛用于游戏开发、脚本编写和其他应用程序中。在 Lua 中,函数是一等公民,这意味着它们可以被赋值给变量,作为参数传递给其他函数,甚至可以作为其他函数的返回值。本文将详细介绍…

Rust 力扣 - 1423. 可获得的最大点数

文章目录 题目描述题解思路题解代码题解链接 题目描述 题解思路 题目所求结果存在下述等式 可获得的最大点数 所有卡牌的点数之和 - 长度为(卡牌数量 - k)的窗口的点数之和的最小值 我们遍历长度为(卡牌数量 - k)的窗口&#…

springboot2.x使用SSE方式代理或者转发其他流式接口

文章目录 1.需求描述2.代码2.1.示例controller2.2.示例service2.3.示例impl 3.测试 1.需求描述 使用SSE的方式主要还是要跟前端建立一个EventSource的链接,有了这个连接,然后往通道里写入数据流,前端自然会拿到流式数据,写啥拿啥…

同城行业交流圈子/交友圈子论坛系统有哪些开源架构与优势解析

开源架构 前端 Vue.js与uni-app框架:前端常采用Vue.js框架,特别是结合uni-app进行跨平台开发。uni-app是一个使用Vue.js开发所有前端应用的框架,支持编译为H5、小程序、App等多个平台,实现代码的一次编写,多端运行。…

【机器学习】有监督学习·由浅入深讲解分类算法·Fisher算法讲解

博主简介:努力学习的22级计算机科学与技术本科生一枚🌸博主主页: Yaoyao2024往期回顾: 【机器学习】深入浅出讲解贝叶斯分类算法每日一言🌼: Rivers know this:There is no hurry. We shall get there. 0、…

单例 C++ 懒汉+恶汉

单例设计模式是一种创建型设计模式,确保一个类只有一个实例,减少了内存的开销,并提供一个全局访问点访问该实例。 私有化构造函数、拷贝构造函数、赋值函数 ,定义一个类的私有静态对象成员,定义一个公共的访问该实例静…

一文解析——如何月入过万不是梦

在TikTok(简称TK)这个充满活力的短视频平台上,想要实现大规模的商业价值,有效的账号管理和引流策略至关重要。而TK防关联引流系统的出现,无疑为众多品牌和营销者提供了一个高效、低成本的管理和增长解决方案。通过这一…