MySQL 多版本并发控制 MVCC

这篇具有很好参考价值的文章主要介绍了MySQL 多版本并发控制 MVCC。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

MVCC出现背景

事务的4个隔离级别以及对应的三种异常

读未提交(Read uncommitted

读已提交(Read committed):脏读

可重复读(Repeatable read):不可重复读

串行化(Serializable):幻读

  • 脏读:一个事务读取到了另外一个事务没有提交的数据;
  • 不可重复读:在同一个事务中,两次读取同一数据,得到内容不同;
  • 幻读:同一事务中,用同样的操作读取两次,得到的记录数不同。

MySQL中,默认的隔离级别是可重复读,可以解决脏读和不可重复读的问题,但不能解决幻读的问题。如果我们需要解决幻读的问题,就需要采用串行化的方式,也就是将隔离级别提升到最高,但这样依赖就会大幅降低数据库的事务并发能力。

MVCC就是通过乐观锁的方式来解决不可重复读和幻读的问题,它可以在大多数情况下替代行级锁,降低系统的开销。

MySQL并发事务会引起更新丢失问题,解决办法是锁,主要分两类:

  • 乐观锁

​ 其实就如它的名字一样,非常乐观,总是假设比较好的情况。

​ 每次取数据的时候都认为他人不会对其修改,所以不会上锁,但是会在更新的时候进行判断,看看在此期间内有没有人去更新这个数 据,可以使用版本号机制和CAS算法实现。

  • 悲观锁

​ 与乐观锁完全相反,非常悲观,总是假设非常糟糕的情况。

​ 每次取数据的时候都认为他人会对其进行修改,所以每次拿数据的时候都会加上锁,这样别人想拿数据的话就会阻塞,除非它拿到 锁。

什么是MVCC

Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。

多版本并发控制(MVCC) 是通过保存数据在某个时间点的快照来实现并发控制的,也就是说,不管事务执行多长时间,事务内部看到的数据是不受其它事务影响的,根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

简单来说,多版本并发控制的思想就是保存数据的历史版本,通过对数据行的多个版本管理来实现数据库的并发控制。这样我们就可以通过比较版本号决定数据是否显示出来,读取数据的时候不需要加锁也可以保证事务的隔离级别。

可以认为多版本并发控制是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销耕地。虽然实现机制有所不同,但大都实现类非阻塞的读操作,写操作也只锁定必要的行。

MySQL的大多数事务性存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制。不仅是MySQL,包括OraclePostgreSQL等其它数据库系统也都实现了MVCC,但各自的实现机制不尽相同,因为MVCC没有一个统一的实现标准,典型的有乐观并发控制悲观并发控制

MVCC解决了什么问题

解决了在REPEATABLE READ和READ COMMITTED两个隔离级别下读同一行和写同一行的两个事务的并发。

  1. 读写直接阻塞的问题:通过 MVCC 可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。

    提高并发的演进思路:

    • 普通锁,只能串行执行;
    • 读写锁,可以实现读读并发;
    • 数据多版本并发控制,可以实现读写并发。
  2. 降低了死锁的概率:因为 InnoDBMVCC采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。

  3. 解决一致性读的问题:一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。

举个简单的例子:

  1. 一个事务AtxnId=100),修改了数据X,使得X=1,并且commit了。
  2. 另外一个事务BtxnId=101)开始尝试读取X,但是还X=1。但B没有提交。
  3. 第三个事务CtxnId=102)修改了数据X,使得X=2,并且提交了。
  4. 事务B又一次读取了X。这时
    • 如果事务BRead Committed,那么就读取X的最新commit的版本,也就是X=2。
    • 如果事务B是Repeatable Read。那么读取的就是当前事务(txnId=101)之前X的最新版本,也就是XtxnId=100提交的版本,即X=1。

注意,这里B不论是Read Committed,还是Repeatable Read,都不会被锁,都能立刻拿到结果。这也就是MVCC存在的意义。

快照读与当前读

快照读SnapShot Read)是一种一致性不加锁的读,是InnoDB并发如此之高的核心原因之一。

这里的一致性是指,事务读取到的数据,要么是事务开始前就已经存在的数据,要么是事务自身插入或者修改过的数据

不加锁的简单SELECT属于快照读,例如:

select * from users where id = '1';

快照读相对应的则是当前读当前读就是读取最新数据,而不是历史版本的数据。加锁的SELECT就属于当前读,例如:

select * from users where id = '1' lock in share mode;
select * from users where id = '1' for update;

MVCC就是为了实现读-写冲突不加锁,而这个读指的就是快照读,而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现

InnoDB的MVCC是如何工作的

当查询一条记录的时候,执行流程如下:

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

InnoDB是如何储存记录多个版本的

事务版本号

每开启一个事务,我们都会从数据库中获取一个事务ID(也就是事务版本号),这个事务ID是自增长的,通过ID大小,我们就可以判断事务的时间顺序。

行记录的隐藏列

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

  • DB_ROW_ID6-byte,隐藏的行ID,用来生成默认聚簇索引。如果我们创建数据表的时候没有指定聚簇索引,这时InnoDB就会用这个隐藏ID来创建聚簇索引。采用聚簇索引的方式可以提升数据的查找效率。
  • DR_TRX_ID6byte,操作这个数据的事务ID,也就是最后一个对该数据进行插入或更新的事务ID
  • DB_ROLL_PTR7byte,回滚指针,也就是指向这个记录的Undo log信息。

MySQL 多版本并发控制 MVCC,mysql,数据库,mvcc,多版本并发控制

Undo Log

InnoDB将行记录保存在了Undo Log,我们就可以在回滚段中找到它们,如下图所示:

MySQL 多版本并发控制 MVCC,mysql,数据库,mvcc,多版本并发控制

从图中能看到回滚指针将数据行的所有快照记录都通过链表的结构串联了起来,每个快照的记录都保存了当时的db_trx_id,页就是那个时间点操作这个数据的事务ID。这样如果我们想找历史数据快照,就可以通过遍历回滚指针的方式进行查找。

Read View(读视图)

什么是Read View,说白了Read View就是事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)

所以我们知道Read View主要是用来做可见性判断的,即当我们某个事务只想快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务是否能够看到哪个版本的数据,即可能是当前最新的数据,也有可能是该行记录的undo log里面的的某个版本数据。

  • trx_list 未提交事务ID列表,用来维护Read View生成时刻系统正活跃的事务ID
  • up_limit_id 记录trx_list列表中事务ID最小的ID
  • low_limit_id ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1
  • 首先比较DB_TRX_ID < up_limit_id, 如果小于,则当前事务能看到DB_TRX_ID 所在的记录,如果大于等于进入下一个判断
  • 接下来判断 DB_TRX_ID 大于等于 low_limit_id, 如果大于等于则代表DB_TRX_ID 所在的记录在Read View生成后才出现的,那对当前事务肯定不可见,如果小于则进入下一个判断
  • 判断DB_TRX_ID 是否在活跃事务之中,trx_list.contains(DB_TRX_ID),如果在,则代表我Read View生成时刻,你这个事务还在活跃,还没有Commit,你修改的数据,我当前事务也是看不见的;如果不在,则说明,你这个事务在Read View生成之前就已经Commit了,你修改的结果,我当前事务是能看见的

在可重复读(REPEATABLE READ)隔离级别下,InnoDB的MVCC是如何工作的

查询

InnoDB会根据以下两个条件检查每行记录:

  1. InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样确保事务读取的行,要么实在事务开始前已经存在的,要么是事务自身插入或者修改过的
  2. 行的删除版本要么未定义,要么大于当前事务版本号。这样可以确保事务读取到的行,在事务开始之前未被删除
插入

InnoDB未新插入的每一行保存当前系统号作为行版本号。

删除

InnoDB为删除的每一行保存当前系统版本号作为行删除标识。
删除在内部被视为更新,行中的一个特殊位会被设置为已删除。

更新

InnoDB为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。

参考文章

MySQL - MySQL InnoDB的MVCC实现机制

MySQL的多版本并发控制(MVCC)是什么?

值得收藏,揭秘 MySQL 多版本并发控制实现原理

MVCC解决了什么问题?

MVCC实现原理之ReadView(一步到位)

MVCC百度百科

脏读、不可重复读的最终解决方案——MVCC

RR有幻读问题吗?MVCC能否解决幻读?文章来源地址https://www.toymoban.com/news/detail-800066.html

到了这里,关于MySQL 多版本并发控制 MVCC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ⑩⑧【MySQL】InnoDB架构、事务原理、MVCC多版本并发控制

    个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ InnoDB逻辑存储结构 : 🚀 表空间(idb文件) :一个MySQL实例可以对应多个表空间,用于存储记录、索引等数

    2024年02月04日
    浏览(41)
  • 深入解析MVCC:多版本并发控制的数据库之道

    目录 引言 一、什么是MVCC? 二、MVCC的实现原理 2.1版本号 2.1.1版本号的作用: 2.1.2版本号的组成: 2.1.3.示例 2.2事务id 2.2.1事务ID的作用: 2.2.2事务ID的生成: 2.2.3示例: 2.3 快照(Snapshot) 2.3.1快照的作用: 2.3.2快照的实现方式: 2.3.3示例: 2.4版本链(Version Chain) 2.4.1版本链

    2024年01月24日
    浏览(61)
  • 深入探索MySQL InnoDB引擎中的多版本并发控制(MVCC)原理

    引言: 在关系型数据库领域,MySQL InnoDB引擎因其支持事务处理和并发控制的强大功能而备受青睐,其中尤为关键的一项技术就是多版本并发控制(Multi-Version Concurrency Control, MVCC)。MVCC是实现高并发环境下事务隔离性的重要手段,既能有效缓解锁竞争,又能保障数据的一致性

    2024年03月11日
    浏览(45)
  • MYSQL的多版本并发控制MVCC(Multi-Version Concurrency Control)

    MVCC 是一种用于数据库管理系统的并发控制技术,允许多个事务同时访问数据库,而不会导致读写冲突。也就是说在读写的时候,线程不用去争抢读写锁。因为加锁的过程比较耗性能。 当然很多时候还是必须的,不能避免,比如说,去ATM机取钱的时候,同时又在手机APP上进行

    2024年02月07日
    浏览(38)
  • Mysql--技术文档--MVCC(Multi-Version Concurrency Control | 多版本并发控制)

            MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决并发访问数据库时的数据一致性和隔离性问题。MVCC允许多个事务同时读取数据库的同一数据,而不会相互干扰或导致冲突。         在传统的并发控制机制中,如锁定机制,事务会对读取和写入

    2024年02月11日
    浏览(38)
  • MVCC------Mysql并发事务控制的工具

    MVCC 是 Multi-Version Concurrency Control(多版本并发控制)的缩写,是数据库系统中常用的一种并发控制方法。在MVCC 中,数据库系统可以同时维护多个版本的数据,每个事务在读取数据时会看到一个一致性的快照,从而实现并发访问而不会出现数据不一致的情况。这种机制能够提

    2024年03月14日
    浏览(85)
  • 【Mysql】MVCC版本机制的多并发

    🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风翻盘 。 🛸 Mysql专栏 : Mysql内功修炼基地 家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我

    2024年02月11日
    浏览(41)
  • 多版本并发控制MVCC

    MVCC (Multiversion Concurrency Control),多版本并发控制。顾名思义,MVCC 是通过数据行的多个版本管理来实现数据库的 并发控制 。这项技术使得在InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之,就是为了查询一些正在被另一个事务更新的行,并且可以看到它们被更

    2024年02月08日
    浏览(36)
  • mysql数据库 mvcc

      在看MVCC之前我们先补充些基础内容,首先来看下事务的ACID和数据的总体运行流程    数据库整体的使用流程: ACID流程图  mysql核心日志: 在MySQL数据库中有三个非常重要的日志binlog,undolog,redolog. mvcc概念介绍: MVCC (Multi-Version Concurrency Control): 多版本并发控制,是一种并发

    2024年02月20日
    浏览(38)
  • MVCC并发版本控制之重点ReadView

    本文大部分来自 《MySQL是怎样运行的》,这里只是简单总结,用于各位回忆和复习。 对于使用 InnoDB 存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(不知道的快去看《MySQL是怎样运行的》) trx_id :每次一个事务对某条聚簇索引记录进行改动时,都会把该事

    2024年02月09日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包