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
数据表中数据
假设事务A 是 操作的方式将 ID 为1的NAME 读取出来,更新到ID为2的NAME 字段中
假设事务B 是 操作的方式是更新事务A的NAME 字段为AAA
两个事务开启的顺序为
A 先开启,但是还没读取的时候 B 操作完成了
那么 我们看这个瞬间这个表的结构式什么样子的
我们需要注意的是 UPDATE 之后他的行并没有消除而是在新增了一行和标记了上一行在在事务2这个版本上被删除了。
所以事务A 版本号1的 select 语句来读取的时候还是读取的 NAME ABC的结果。
可以参照之前SELECT 的条件来读取,咱们来推演一遍
查找条件一 系统版本号在小于当前版本的ID 1 会命中 ID 1 NAME ABC 这个选项,
查找条件二 删除版本号要么为定义要么大于系统版本号 显然这边的删除版本号定义了,而且大于了事务A的事务版本号导致了能读取到这个结果
上面的这个例子也就说明了能重复读取的都是这个 ID 1 NAME ABC 的稳定结果。
实现了可重复读。
一般的MVCC 分为乐观并发控制和悲观并发控制。
InnoDB的MVCC 是通过保存两个隐藏列来实现的。一个列是保存行的创建时间,一个列是保存行的过期时间,实际上存储的不是时间值,而是系统版本号。每次开启一个新的事务系统版本号就会递增。
来看下 REPEATABLE READ 它是怎么控制的
innoDB SELECT 会根据两种条件来判断每一行的记录
a. innoDB只查找版本早于当前事务版本的数据行,(也就是行的系统版本号小于等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的要么是事务自身插入的或者修改的。
b.行的删除版本要么未定义,要么大于事务版本号。这个可以确保事务读取到的行在事务开启之前为被删除。
只有符合上面两个条件才会作为查询结果。
INSERT
innoDB 为新插入的每一行保存当前系统的版本号作为行版本号。
DELETE
innoDB 为删除的每一行保存当前系统版本号作为行删除标识
UPDATE
innoDB为新插入的一条记录,保存当前系统版本号作为版本号,同事保存当前系统版本号到原来的行作为删除记录。
保存这两个额外的字段,导致了大部分读取都不需要加锁。
上面说了一大堆理论 咱们来推演一下
现在有A,B 两个事务 版本号分别为1,2
数据表中数据
ID | NAME | CREATE_VERSION | OVER_VERSION |
1 | ABC | 0 | |
2 | DB | 0 |
假设事务B 是 操作的方式是更新事务A的NAME 字段为AAA
两个事务开启的顺序为
A 先开启,但是还没读取的时候 B 操作完成了
那么 我们看这个瞬间这个表的结构式什么样子的
ID | NAME | CREATE_VERSION | OVER_VERSION |
1 | ABC | 0 | 2 |
2 | DB | 0 | |
1 | AAA | 2 |
所以事务A 版本号1的 select 语句来读取的时候还是读取的 NAME ABC的结果。
可以参照之前SELECT 的条件来读取,咱们来推演一遍
查找条件一 系统版本号在小于当前版本的ID 1 会命中 ID 1 NAME ABC 这个选项,
查找条件二 删除版本号要么为定义要么大于系统版本号 显然这边的删除版本号定义了,而且大于了事务A的事务版本号导致了能读取到这个结果
上面的这个例子也就说明了能重复读取的都是这个 ID 1 NAME ABC 的稳定结果。
实现了可重复读。
相关文章推荐
- Mysql 的InnoDB事务方面的 多版本并发控制如何实现 MVCC
- MySQL innodb 事务的实现
- MySQL InnoDB MVCC实现原理
- Mysql Innodb中undo-log和MVCC多版本一致性读 的实现
- Mysql Innodb中undo-log和MVCC多版本一致性读的实现(源码分析)
- mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)
- MVCC实现-MYSQL INNODB MVCC实现
- Mysql事务和隔离级别(read committed, repeatable read)
- mysql MVCC之InnoDB实现
- 面试常考 MySQL优化 事务处理 MyISAM和InnoDB索引实现
- innoDB的MVCC实现方式
- MySQL中MyISAM和InnoDB对B-Tree索引不同的实现方式
- MySQL InnoDB MVCC实现原理
- MySQL innodb 事务的实现
- PostgreSQL、Oracle/MySQL和SQL Server的MVCC实现原理方式
- REPEATABLE_READ事务级别MYSQL并发小例子
- MSSQL 如何实现 MySQL 的 limit 查询方式【转存】
- MySQL的innoDB存储引擎的运作方式,数据结构等
- 深度解析MySQL—InnoDB多版本并发控制(MVCC)