MySQL事务及MVCC

2021/8/1 2:05:53

本文主要是介绍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的执行流程
事务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。

  • 如下图:

  • 1.行状态变更


语句更新会生成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分成不同情况。

  • 2.数据版本可见性规则

  • 对于事务启动瞬间,一个数据版本的row trx_id,有几种可能:

    1. 如果落在绿色部分,表示这个版本是已提交事务或者当前事务自己生成的,这个数据是可见的。
    2. 如果落在红色部分,表示这个版本是有将来启动的事务生成的,不可见。
    3. 落在黄色有两种情况:
      1. 若row trx_id在数组中,表示这个版本是由还没提交的事务生成,不可见。
      2. 若row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。
  • 对于图1中的数据来说,如果有一个事务,它的低水位是18,那么当它访问这一行数据时,就会从V4通过U3计算出V3,所以在它看来,这一行的值时11.

  • 因此,InnoDB利用“所有数据都有多个版本”的特性,实现了“秒级创建快照”的能力。



这篇关于MySQL事务及MVCC的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程