MVCC (Multi-Version Concurrency Control)(多版本并发控制机制)

Mysql在 可重复度 事务隔离级别下,同样的sql在同一事务下多次执行查询结果相同,就算有其他事务修改数据,也不会影响当前事务的查询结果。这个隔离性就是靠MVCC(Multi-Version Concurrency Control)机制来保证的。

Mysql在 读已提交 可重复读 隔离级别下都实现了MVCC机制。但是实现原理不大一样,在 读已提交 级别是每次select生成一个版本,在 可重复读 是第一次select生成一个版本。

undo日志版本链与read view机制详解

undo日志 也叫 回滚日志 。innorDb 默认会在表中加3个隐藏字段:

1. DATA_TRX_ID :最近更新这条数据的事务ID,占6字

2. DATA_ROLL_PTR :存放指向上一个事务版本的指针,占7字节(版本链依赖于这个字段)

3. DB_ROW_ID :主键id,占6字节(表没有设置主键时会自动生成一个隐藏的主键id列)

一条数据被 增、删、改 操作后都会生成一条记录存放在 undo log 中(注意读不会生产记录),然后用 DATA_ROLL_PTR 指向上一个版本,形成一个历史版本链。 mysql 结构图 (1).png

read view(一致性 视图 。在 可重复读隔离级别 ,当事务开启,执行任何查询sql时会生成当前事务的 一致性 视图 read-view, 该视图在事务结束之前都不会变化( 如果是读已提交隔离级别在每次执行查询sql时都会重新生成 ),这个视图由执行查询时所有未提交事务id数组(数组里最小的id为 min_trx_id ,创建当前事务的id为 creator_trx_id )、已创建的最大事务id( max_trx_id ),事务里的任何sql查询结果需要从对应版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。

undo日志版本链与read-view对比规则如下:

  1. 如果被访问的事务id与 creator_trx_i d 相等,则说明此时查询的是自己修改过的记录,返回该记录。(被访问id = 当前事务id,可用)
  2. 如果被访问的事务id比 min_trx_id 要小,则说明该事务在当前事务生成 read-view 前已提交,可以返回该记录。(被访问id < 最小id,可用)
  3. 如果被访问的事务id比 max_trx_id 要大,则说明该事务在当前事务生成 read-view 之后才开启,需要在undo日志版本链里继续对比下一条事务。(被访问id > 最大id,不可用)
  4. 如果被访问的事务id在 min_trx_id max_trx_id 之间,先检查该事务id是否包含在 read-view 中,如果没包含,说明该事务已提交,可用返回记录。如果包含在 read-view 中,那么说明该事务未提交,继续对比下一条事务。(如果 最小id<被访问事务id<最大id,先判断是否在read-view中,如果在则可用,不走则继续对比)。

如果这一步看不懂,看了下一步的实例讲解就明白了

测试数据脚本:

CREATE TABLE `t_version` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ver` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
insert into t_version(ver) values (1);

下面从一个实例开始讲解MVCC的过程。注意当前隔离级别为 可重复度

MySQL中有三种开启事务的方式:

  1. begin
  2. start transaction
  3. start transaction with consistent snapshot

前两种方式,MySQL执行后不会马上创建视图,是在执行第一条select语句时才会创建,第三种方式MySQL执行后会马上创建视图。

假设初始化表t_version ,id=1, ver=1 的事务id为1

在T4时刻 ,事务8修改修改了ver = ver + 1,此时ver=2。于是 undo log 日志版本链记录如下:

在T6时刻 ,事务5查询id=1的记录。事务5开启事务时事务8还未启动,所以事务5的read-view为[3, 5]。
此时read-view中的参数为:
最小事务id:min_trx_id = 3
创建当前事务id:idcreator_trx_id = 5
最大事务id:max_trx_id = 5
接下来按照上面说的undo日志版本链与read-view对比规则进行对比:
第1步:被访问的事务id:DATA_TRX_ID=8,比最大事务id:max_trx_id=5要大 ,满足第三条,继续对比下一条日志。
第2步:被访问的事务id:DATA_TRX_ID=1,比最小事务id:min_trx_id = 3要小,满足第二条,返回DATA_TRX_ID=1的记录。

在T7时刻 ,事务5修改修改了ver = ver + 1,注意修改操作与快照无关,那个是由写锁控制的,想明白写锁看我上一篇。所以此时ver=3。于是 undo log 日志版本链记录如下:

在T8时刻 ,事务5查询id=1的记录。因为是可重复度级别,事务5的read-view保持不变为[3, 5]。
此时read-view中的参数为:
最小事务id:min_trx_id = 3
创建当前事务id:idcreator_trx_id = 5
最大事务id:max_trx_id = 5
接下来按照上面说的undo日志版本链与read-view对比规则进行对比:
第1步:被访问的事务id:DATA_TRX_ID=5,创建当前事务id:idcreator_trx_id = 5 ,满足第一条,查询的这条记录有被自己修改过,直接返回DATA_TRX_ID=5的记录。

在T9时刻 ,事务3查询 id=1 的记录。事务3开启事务时的read-view为[3]。
此时read-view中的参数为:
最小事务id:min_trx_id = 3
创建当前事务id:idcreator_trx_id = 3
最大事务id:max_trx_id = 3
接下来按照上面说的undo日志版本链与read-view对比规则进行对比:
第1步:被访问的事务id:DATA_TRX_ID=5,比最大事务id:max_trx_id = 3要大 ,满足第三条,说明该被访问的事务在当前事务生成read-view之后开启,继续对比下一条事务。
第2步:被访问的事务id:DATA_TRX_ID=8,同上
第3步:被访问的事务id:DATA_TRX_ID=1,比最小事务id:min_trx_id = 3要小,满足第二条,返回DATA_TRX_ID=1的数据。

看到这里相信原理都会了。另外mysql会判断把不需要的 undo log 清理掉,不会一直积累undo日志撑爆磁盘的。

导图(用于总结和复习)MVCC (Multi-Version Concurrency Control)(多版本并发控制机制)Mysql在可重复度事务隔离级别下,同样的sql在同一事务下多次执行查询结果相同,就算有其他事务修改数据,也不会影响当前事务的查询结果。这个隔离性就是靠MVCC(Multi-Version Concurrency Control)机制来保证的。Mysql在读已提交和可重复读隔离级别下都实现了MVCC机制。但是实现原理不大一样,在读已提交级别是每次select生成一个.. 执行增、删、改之前,先将满足条件的数据查询出来放入到临时表中 将数据操作先在临时表中完成,完成过程中如果没用出现任何问题,就将数据同步(剪切)到实际的数据表中,并返回影响行数 ;完成过程中一旦出现错误,那就将临时表中满足条件的数据清掉,并返回错误码。 1、先把要插入的数据放入临时表 2、将临时表中数据插入实际表中去 3、如果没问题,就复制. MVC C,全称Multi-Version Concurrency Control,即多 版本 并发控制 MVC C是一种 并发控制 的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 使用 MVC C的好处 多 版本 并发控制 MVC C)是一种用来解决读-写冲突的无锁 并发控制 ,在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能。 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题(后面解释)。
版本 并发控制 技术已经被广泛运用于各大数据库系统中,如Oracle,MS SQL Server 2005+, Postgre sql , Firebird, Maria等等,开源数据库 MYSQL 中流行的INNODB引擎也采用了类似的 并发控制 技术.本文就将结合实例来解析不同事务隔离等级下INNODB的 MVC C实现 原理 . 1 MVC C概述 1.1 MVC C简介 MVC C (Multi
1、什么是 MVC C? MVC C是在并发访问数据库时,通过对数据做多 版本 管理,避免因为写锁的阻塞而造成读数据的并发阻塞问题。 通俗的讲就是 MVC C通过保存数据的历史 版本 ,根据比较 版本 号来处理数据的是否显示,从而达到读取数据的时候不需要加锁就可以保证事务隔离性的效果 2、Innodb MVC C实现的核心知识点 undo log(回滚日志) 之前对undo log的作用只提到了回滚操作实现原子性,现在需要知道的另一个作用就是实现 MVC C多 版本 控制器。 undo log细分为俩种,insert时产生的undo
1、 MVC C简介 MVC C,全称Multi-Version Concurrency Control,即多 版本 井发控制, MVC C是一种 并发控制 的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 MVC C在 MysQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读写冲突。做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。 2、当前读 像select lock in s... 测试环境: Mysql 5.7.20-log 数据库默认隔离级别:RR(Repeatable Read,可重复读), MVC C主要适用于 Mysql 的读已提交(Read committed)和可重复读(Repeatable Read)隔离级别 创建一张存储引擎为test mvc c的表, sql 为: CREATE TABLE test mvc c ( id int( 11 ) DEFAULT NULL, name varchar( 11 ) DEFAULT NULL ) ENGINE=InnoDB DEFAU 全称:Multi Version Concurrency Control 是现代数据库( MySQL 、Oracle、Postgre SQL 等)引擎实现中常用的处理读写冲突的方式,目的在于提高数据库高并发下的吞吐性能。如此一来不同的事务在并发过程中,select操作可以不加锁而是通过 MVC C 机制 读取指定的 版本 历史记录,并通过一些手段保证读取的记录值符合事务所处的隔离级别,从而解决并发场景下的读写冲突。 下面是一个并发读写的例子,假如两个事务A和B按照如下顺序进行更新和读取
(1) MVC C 原理 实现思路: 通过undo_log多 版本 链条,加上开启事务时产生的readView(不同隔离级别有不同产生策略),然后再有一个查询的时候,根据readView进行判断的 机制 ,来决定读取哪个 版本 的数据。实现了多事务并发执行,保证只能读开启事务前提交的数据和当前事务修改的数据,其他情况都不会读到。解决的是读一致性问题 innodb为每行记录实现了三个隐藏字段,用于形成undo_log链 DB_TRX_ID事务id:插入或更新行的最后一个事务的事务ID(创建 版本 号),自动递增 DB_ROL
MySQL 的多 版本 并发控制 MVC C)是一种 并发控制 机制 ,它主要是为了解决并发读写冲突的问题。在 MVC C 机制 中,每个事务都可以看到数据库中的一个快照,这个快照是在事务开始时确定的。事务读取数据时,实际上是读取了该快照中的数据,而不是实际的数据。当事务需要修改数据时, MySQL 会根据数据的 版本 号来判断是否可以进行修改。 MVC C的实现 原理 主要是在每一行数据后面保存多个 版本 号,并且还需要保存该 版本 号对应的事务ID。当开始一个事务时, MySQL 会为该事务分配一个唯一的事务ID,该事务ID会被用于标记事务对应的数据 版本 号。当一个事务需要读取数据时, MySQL 会根据该事务的事务ID和 版本 号来判断是否允许读取该数据。如果该事务的事务ID小于等于该数据的 版本 号,那么就可以读取该数据。如果该事务需要修改数据,则 MySQL 会为该数据在数据库中创建一个新 版本 ,并将该新 版本 版本 号和事务ID保存下来。这样,其他事务就可以继续读取原来的 版本 ,而该事务则可以读取新 版本 并修改数据,从而实现 并发控制 。 需要注意的是, MVC C只能解决读写冲突的问题,而不能解决写写冲突的问题。此外, MVC C也会占用一定的存储空间,因为每个数据行都需要保存多个 版本 号和事务ID。因此,在使用 MVC C 机制 时,需要注意存储空间和性能方面的问题。
【错误解决】Job for ssh.service failed because the control process exited with error code.See “systemctl 26596 【错误解决】Job for ssh.service failed because the control process exited with error code.See “systemctl Ling2248: 需要update apt-get然後卸載重裝一下openssh-server. sudo apt-get update sudo apt-get remove openssh-server sudo apt-get install openssh-server sudo service ssh start 【错误解决】Job for ssh.service failed because the control process exited with error code.See “systemctl 知往不谏,望来可追: 没有那个目录 /etc/ssh# sshd -T 怎么回事啊求助 【错误解决】Job for ssh.service failed because the control process exited with error code.See “systemctl 名猿陈大浏: 差不多的意思哦 【错误解决】Job for ssh.service failed because the control process exited with error code.See “systemctl 也有可能是某个单词拼写错误。。 mysql - 第10课 - 深入理解mysql事务隔离级别与锁机制 (mysql各种锁,mysql事务隔离级别实现原理) 名猿陈大浏: 对,我图都画出来了 【问题解决】has been injected into other beans [] in its raw version as part of a circular reference,but h 【问题解决】No appropriate protocol (protocol is disabled or cipher suites are inappropriate) 【错误解决】Job for ssh.service failed because the control process exited with error code.See “systemctl