Loading

极客--事务到底是隔离还是不隔离

可重复读隔离级别,事务T启动的时候会创建一个read-view,之后事务T执行期间,即使其他事务修改了数据,事务T看到仍然在启动时看到的一样。也就是说,一个可重复读的隔离级别下执行的事务,好像与世无争,不受影响,那么等到事务自己获取到行锁更新数据的时候,它读到的是什么呢?
image

begin/start transaction命令并不是一个事务的起点,在执行到它们之后的第一个Innodb语句,事务才真正启动,可以使用start transaction with consistent snapshot这个命令

  • 第一种启动方式在执行第一个快照语句的时候创建的。
  • 第二种启动方式,一致性视图在执行start transaction with consistent snapnot时创建
  • update语句本身就是一个事务

在Mysql里,有两个视图的概念

  • 一个是view.它是查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。创建视图语法是create view...,而它的查询方法与表一样
  • 另一个是Innodb在实现MVCC时用到一致性视图,即consitent read view 用于支持RC和RR隔离级别

快照在MVCC里面是怎样工作的

在可重复读隔离级别下,事务启动的时候就拍了一个快照,这个快照是基于整库的。(那岂不是很慢?)

  • Innodb里面每个事务都有一个唯一ID,叫做transactionID,他是在事务开始的时候Innodb的事务系统申请的,严格按照申请顺序严格递增
  • 而每行数据也都是有多个版本,每次事务更新数据的时候,都会生成一个新的数据版本,并且吧transaction_id赋值给这个数据版本的事务ID,记为row_trx_id。同时,旧的数据版本也要保留,并且在新的数据版本中,能够有信息可以直接拿到它
    image

undolog

  • 图中v1 v2 v3并不是真实存在的,而是每次需要的时候根据当前版本与undo log计算出来的。需要V2的时候,就需要通过v4依次执行U3 U2算出来
  • 也就是可重复读隔离级别下,在它启动之后生成的版本号是不认得,他也要找到上一个版本
  • 实现上Innodb为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在活跃的所有事务ID,活跃指的是启动了但没提交
  • 数组里面事务ID最小值记作低水位,当前系统里面创建过的事务ID最大值加1记作高水位
    image
当前事务启动瞬间,一个数据版本的row_trx_id有以下几种可能:
  1. 如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的
  2. 如果落在红色部分,这个版本由将来事务自己生成的,这个数据也是可见的。
  3. 如果落在黄色部分,分为两种情况
    a.若row_trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见
    b.若row_trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见
Innodb利用所有数据都有多个版本的特性,实现了秒级快照能力

更新语句都是先读后写,而这个读,只能是读当前值

posted @ 2022-09-19 21:19  DoDo神  阅读(29)  评论(0)    收藏  举报