本文主要是介绍MySQL事务及MVCC,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
MySQL事务-MVCC
- 可重复读隔离级别,事务T启动的时候会创建一个视图read-view,之后事务T执行期间,即使有其他事务修改了数据,事务T仍然不受影响。
- 假如一个事务要更新一行,如果刚好有另一个事务的行锁,那么它就会被锁住,进入等待状态。那么当这个事务获取到行锁要更新事务的时候,读到的值是什么?
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`k` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);
事务A | 事务B | 事务C |
---|
start transaction with consistent snapshot | | |
| start transaction with consistent snapshot; | |
| | update t set k = k+1 where id = 1; |
| update t set k = k + 1 where id = 1; select k from t where id = 1 | |
select k from t where id = 1; commit; | | |
| commit; | |
- begin/start transaction 命令不是事务的起点。
- 在执行到他们第一个操作InnoDB表的语句,事务才启动。
- 如果想要马上启动一个事务,可以使用start transaction with consistent snapshot。
- 第一种启动方式,一致性视图实在执行第一个快照读语句时创建的。
- 第二种方式,一致性视图是在执行start transaction with consistent snapshot时创建的。
- 在MySQL中,有两个视图概念。
- 一个是view,它是一个查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。创建视图的语法是create view …,而它的查询方法与表一样。
- 另一个是InnoDB在实现MVCC时用到的一致性视图。即consistent read view,用于支持RC(Read committed,读提交)和RR(Repeatable Read,可重复读)隔离级别的实现。
它没有物理结构,作用时事务执行期间用来定义“我能看到什么数据”。
“快照”在MVCC里怎么工作。
-
在可重复读隔离级别下,事务在启动时就有一个快照,这个快照基于整库。
-
InnoDB中每个事务都由一个唯一的事务ID(transaction id)。它是在事务开始的时候想InnoDB的事务系统申请的,按申请顺序严格递增。
-
每行数据也有多个版本,每次事务更新都会生成新的数据版本,同时旧的数据版本被保留,在新的数据版本中能够直接拿到。
-
数据表中的一行记录,其实可能有多个版本(row),每个版本都有自己的row_trx_id。
-
如下图:
-
语句更新会生成undo log(回滚日志)
- undo log 位置
- 在上图中每个版本之间的虚线就是undo log,V1,V2,V3并不是物理意义上存在的,而是每次根据当前版本和undo log计算出来的。
- 比图需要V2的时候,就是通过V4一次执行U3、U2算出来的。
InnoDB怎么定义“100G”快照
- 可重复读:一个事务启动的时候,能够看到所有已经提交的事务结果。但是之后,这个事务执行期间,其他事务的更新对它不可见。
- 一个事务对相应数据必须要在它启动之前。如果是启动之后生成的,则找到它的上一个版本,如果上一个版本也不可见,则继续向前找。
- InnoDB为每个事务构造了一个数组,用来保存这个事务启动的瞬间,当前正在“活跃”的所有事务ID。“活跃”:启动了还没有提交。
- 数组里面事务ID的最小值记为低水位,当前系统里面已经创建过的事务ID的最大值加1记为高水位。
- 这个视图数组和高水位,就组成了当前事务的一致性视图。
- 事务版本的可见性规则,就是基于数据的row trx_id和这个一致性视图的对比结果得到的。
-
视图数组把所有的row trx_id分成不同情况。
-
-
对于事务启动瞬间,一个数据版本的row trx_id,有几种可能:
- 如果落在绿色部分,表示这个版本是已提交事务或者当前事务自己生成的,这个数据是可见的。
- 如果落在红色部分,表示这个版本是有将来启动的事务生成的,不可见。
- 落在黄色有两种情况:
- 若row trx_id在数组中,表示这个版本是由还没提交的事务生成,不可见。
- 若row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。
-
对于图1中的数据来说,如果有一个事务,它的低水位是18,那么当它访问这一行数据时,就会从V4通过U3计算出V3,所以在它看来,这一行的值时11.
-
因此,InnoDB利用“所有数据都有多个版本”的特性,实现了“秒级创建快照”的能力。
这篇关于MySQL事务及MVCC的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!