您的位置:首页 > 数据库 > MySQL

mysql innoDB的REPEATABLE READ MVCC事务实现方式

2017-09-09 21:04 513 查看
mysql大多数事务型存储引擎实现的并不是简单的行级锁,一般是基于并发考虑实现多版本控制。MVCC。

一般的MVCC 分为乐观并发控制和悲观并发控制。

InnoDB的MVCC 是通过保存两个隐藏列来实现的。一个列是保存行的创建时间,一个列是保存行的过期时间,实际上存储的不是时间值,而是系统版本号。每次开启一个新的事务系统版本号就会递增。

来看下 REPEATABLE READ 它是怎么控制的

innoDB SELECT 会根据两种条件来判断每一行的记录

a. innoDB只查找版本早于当前事务版本的数据行,(也就是行的系统版本号小于等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的要么是事务自身插入的或者修改的。

b.行的删除版本要么未定义,要么大于事务版本号。这个可以确保事务读取到的行在事务开启之前为被删除。

只有符合上面两个条件才会作为查询结果。

INSERT

innoDB 为新插入的每一行保存当前系统的版本号作为行版本号。

DELETE

innoDB 为删除的每一行保存当前系统版本号作为行删除标识

UPDATE

innoDB为新插入的一条记录,保存当前系统版本号作为版本号,同事保存当前系统版本号到原来的行作为删除记录。

保存这两个额外的字段,导致了大部分读取都不需要加锁。

上面说了一大堆理论 咱们来推演一下

现在有A,B 两个事务 版本号分别为1,2

数据表中数据

IDNAMECREATE_VERSIONOVER_VERSION
1ABC0 
2DB0 
假设事务A 是 操作的方式将 ID 为1的NAME 读取出来,更新到ID为2的NAME 字段中

假设事务B 是 操作的方式是更新事务A的NAME 字段为AAA

两个事务开启的顺序为

A 先开启,但是还没读取的时候 B 操作完成了

那么 我们看这个瞬间这个表的结构式什么样子的

IDNAMECREATE_VERSIONOVER_VERSION
1ABC02
2DB0 
1AAA2 
我们需要注意的是 UPDATE 之后他的行并没有消除而是在新增了一行和标记了上一行在在事务2这个版本上被删除了。

所以事务A 版本号1的 select 语句来读取的时候还是读取的 NAME ABC的结果。

可以参照之前SELECT 的条件来读取,咱们来推演一遍

查找条件一 系统版本号在小于当前版本的ID 1 会命中 ID 1 NAME ABC 这个选项,

查找条件二 删除版本号要么为定义要么大于系统版本号 显然这边的删除版本号定义了,而且大于了事务A的事务版本号导致了能读取到这个结果

上面的这个例子也就说明了能重复读取的都是这个 ID 1 NAME ABC 的稳定结果。

实现了可重复读。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql Innodb MVCC