Loading

五、事务隔离的具体实现(Mysql实战45讲笔记-基础)

7. 事务隔离的具体实现

不可重复读:

事务开启的时候创建视图 -> 之后事务执行期其他事务修改了数据,当前事务查看到的和开始事务时的一样。从此看出,事务读数据的时候是隔离的。

但是当前事务修改数据的时候,如果其他事务先对该行数据进行修改,则触发行锁,需要等其他事务执行完,释放锁后,才能执行。这里感觉事务又不是隔离的。

从下面的例子中来解释

mysql> 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);

image-20210409100746266

注意

  • start/begin transaction : 用此命令开启的事务,视图不是马上创建,而是在执行到它们之后的第一个操作InnoDB语句,事务才真正的启动
  • start transaction witch consistent snapshot :马上启动事务,创建视图
  • 这里默认是autocommit =1

查询结果:

  • 事务a:查询的数据是1
  • 事务b:查询的数据是3
  • 事务c: 没有显示开启/提交事务,但是update语句本身就一个事务,语句完成后就自动提交

解释:

mysql中有两个视图概念:

  • view:查询语句定义的虚拟表,通过执行查询语句生成的结果创建视图。创建语法 create view,查询方法和表一样。
  • 一致性读视图(用于InnoDB实现MVCC):用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。

这里讲解的是“一致性读视图”,下面简称视图。

视图生成方式:

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

  1. 事务启动时,生成基于整个数据库视图。
  2. 生成方式:不是将现有的数据都copy一份
    1. 事务启动,去InnoDB申请一个顺序唯一的事务ID(tra_id)
    2. 每行数据也与一个row tra_id
    3. 事务更新数据的时候,会将tra_id 赋值给修改行的row tra_id,同时该行的旧数据和row tra_id也会保留(不是物理存储,而是通过undo log和当前版本推算出的)
    4. 行数据修改的过程,会生成 undo log(回滚日志),下图中的 u1、u2、u3
    5. v1、v2、v3不是物理存在的,而是通过当前版本和undo log计算出来的

image-20210409104409781

视图作用流程:

  1. 事务开始,记录当前所有“活跃事务-没有提交的事务”记成一个数组
    • 低水位:事务id最小值
    • 高水位:事务id最大值+1(就是当前事务id)
  2. 查询数据的时候,通过row tra_id 和 事务数组进行对比来判断,该数据时候可显示

image-20210409111756222

  • 在事务数组中:
    • 是当前事务id:当前事务进行修改的,可显示
    • 当前事务开启的事务还没提交:不能显示
  • 不在事务数组中:
    • 比低水位小:已经提交的事务,可以显示
    • 比高水位高:是当前事务开启后,开启的事务修改的,不能显示

举例:

image-20210409112123751

流程:

image-20210409112926248

posted @ 2021-04-13 15:29  半瓶牛奶🥛  阅读(80)  评论(0编辑  收藏  举报