一、前言
众所周知,MySQL的在RR隔离级别下查询数据,是可以保证数据不受其它事物影响,而在RC隔离级别下只要其它事物commit后,数据都会读到commit之后的数据,那么事物隔离的原理是什么?是通过什么实现的呢?那肯定是通过MVCC机制(Multi-Version Concurrency Control
,即多版本并发控制)。
注:MySQL的InnoDB引擎之所以能够支持高性能的并发性能,就是由于MySQL的MVCC机制(归功于undo log、Read-View、),但是本篇不对MVCC过多的介绍。
参考资料:《MySQL实战45讲》系列,虽然讲解的比较清晰,但是仍然需要理解,比如关于视图数组部分我认为是相比较而言没有解释清楚,所以结合资料与自己见解加以记录!
二、RC与RR隔离级别
我们分别开启RC与RR隔离级别实验说明,首先假设有account账户表,在事务ABC开启前,账户中的余额balance为1,即
select balance from account =1; # 结果为1
2.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 命令并不是一个事本文来源gaodai#ma#com搞@@代~&码*网2务的起点,在执行到它们之后的第一个操作InnoDB表的语句,事务才真正启动。如果你想要马上启动一个事务,可以使用start transaction with consistent snapshot 这个命令。
2.2、RC事务隔离级别下查询结果
同样地,我们在RC隔离下,开启事务ABC,观察事务A最后的balance结果。
最后事务A读取balance的结果是2,理所当然,RC即为读可提交,字面意思就是其他事务只要提交后,当前事务我就能立马读取到最新当前值,这就是当前读。但是我们要讨论的是如何在MVCC机制下实现?
实际上这是因为实现MVCC时用到的一致性读视图,即consistent read view,用于支持RC(Read Committed,读提交)和RR(Repeatable Read,可重复读)隔离级别的实现。
三、事务隔离在MVCC的实现
在探讨MVCC如何实现事务隔离前,我们需要知道是视图数组、一致性视图等概念,才能帮助更好理解MVCC帮助事务实现了隔离。