前言
众所周知,MySQL的在RR隔离级别下查询数据,是可以保证数据不受其它事物影响,而在RC隔离级别下只要其它事物commit后,数据都会读到commit之后的数据,那么事物隔离的原理是什么?是通过什么实现的呢?那肯定是通过MVCC机制(Multi-Version Concurrency Control,即多版本并发控制),这是很多人知道的,但是我之前没有好好分析过其实现原理,所以写下此篇博文记录下!
注:MySQL的InnoDB引擎之所以能够支持高性能的并发性能,就是由于MySQL的MVCC机制(归功于undo log、Read-View、),但是本篇不对MVCC过多的介绍。
一、RC与RR隔离级别
我们分别开启RC与RR隔离级别实验说明,首先假设有account账户表,在事务ABC开启前,账户中的余额balance为1,即
select balance from account =1; # 结果为1
1.1 RR事务隔离级别下查询结果
当在RR事务隔离级别分别开启三个事务,在不同时间段内做如下操作
- 事务A(显式开启事务,手动commit提交):查询余额
- 事务B(显式开启事务,手动commit提交):对id=1的余额加1
- 事务C(不显式开启事务,自动提交):对id=1的余额加1
我们从时间逻辑上分为三个阶段,分析结果
- 第一阶段:事务A立马开始事务,随后事务B也紧跟着立马开始事务,然后事务C首先更新balance为2成功,当前balance=2;
- 第二阶段:事务B更新balance的值,此时先读到当前balance最新值为2,随后set balance=balance+1成功,当前balance=3;
- 第三阶段:事务A查询balance的值,此时的值为1(这里为什么等于1呢,是怎么实现的呢?不应该是当前最新值3吗?这就是本篇博文讨论的重点),最后commit结束事务,紧接着事务B也commit结束事务
最后事务A读取balance的结果是1,理所当然,RR即为可重复读,即一个事务在执行过程中看到的数据,总是跟这个事务启动时看到的数据是一致的,当前事务不管有没有提交,都不会影响数据,我只需要读取基于快照的数据即可,这就是快照读。但是我们要讨论的是如何在MVCC机制下实现?
注:begin/start transaction 命令并不是一个事务的起点,在执行到它们之