MySQL系列:和你聊聊事务隔离级别

1.前言

不管是系统开发还是面试,事务相关知识一直都是绕不开的话题,足以看出事务的重要性。由于事务内容多且复杂,有的东西不在涉及范围内,本文也就个人的了解来说下事务隔离级别

2.事务特性

  • Atomicity(原子性)
  • Consistency(一致性)
  • Isolation(隔离性)
  • Durability(持久性)

3.事务隔离级别

  • 读未提交:一个事务可以读取到其它事务未提交的内容
  • 读提交:一个事务只可以读取到其它事务已提交的内容,无法读取到其它事务未提交的内容
  • 可重复读:一个事务开启后读到的数据和事务执行过程中读取到的数据是一致的
  • 串行化:读加读锁,写加写锁

3.1 事务示例

如图所示,一共有4个事务在执行,那么针对事务5的两次读取操作在读提交可重复读隔离级别下的结果分别是多少?

3.2 读提交结果

序号 第一次读取结果 第二次读取结果
1 李四 王五

3.3 可重复读结果

序号 第一次读取结果 第二次读取结果
1 李四 李四

3.4 理论分析

通过对比,可以发现同一个事务的两次查询结果在读提交可重复读隔离级别下是不一样的,具体原因是什么样的呢?

根据读提交隔离级别的描述(一个事务可以读取到另一个事务已经提交的数据)可以得知:事务5的第二次查询是可以读取到事务3提交的数据

根据可重复读隔离级别的描述(一个事务开启后读到的数据和该事务执行过程中读取到的数据是一致的)可以得知:事务5的第二次查询和第一次查询的结果是一样的,因此第二次的查询结果也是李四

3.5 技术分析

3.5.1 回滚日志

MySQL记录的每次更新操作都会有相关回滚日志,针对如上更新,对应的回滚日志如下图所示

3.5.2 多版本并发控制

一条记录在系统中存在多个版本也就是MVCC(Multiversion Concurrency Control)

3.5.3 Read View

MySQL执行查询语句会生成对应的Read ViewRead View存在如下属性:

  • m_id:当前活跃事务id集合
  • min_trx_id:当前活跃最小事务id
  • max_trx_id:预分配事务id,当前活跃最大事务id + 1
  • creator_trx_id:当前事务id

3.5.1中可以了解到一条记录会同时存在多个版本,那么每次读取的时候会读取哪个版本呢?其实每次读取都是从最新版本开始读,依照规则判断当前版本是否满足,满足则返回,不满足则跳过。

3.5.4 以READ ViewA为例

此处用读提交隔离级别进行分析

通过对上图示例分析可以得知Read ViewA当前活跃事务id集合为(3, 4, 5),最小事务id为3,预分配事务id为6,当前事务id为5

每次读取都是从最新版本开始读,那么此处就是从赵六这个版本开始读,只不过需要遵循一定规则:

  • 如果当前版本事务id等于Read View当前事务id,可以访问(满足条件结束)
  • 如果当前版本事务id小于最小事务id,说明事务已经提交,可以访问(满足条件结束)
  • 如果当前版本事务id大于等于预分配事务id,说明事务在视图生成后开启,不可以访问(满足条件结束)
  • 如果当前版本事务id大于最小事务id并且小于预分配事务id,并且不在活跃事务id集合中,可以访问

基于规则,逐条验证

赵六记录对应事务id = 4,Read ViewA事务id = 5

  • 第一条规则 4不等于5 不满足
  • 第二条规则 4不小于3,不满足
  • 第三条规则 4不大于等于6,不满足
  • 第四条规则 4在3和6之间,但是4在活跃事务id集合中,不满足

王五记录对应事务id = 3Read ViewA事务id = 5

  • 第一条规则 3不等于5 不满足
  • 第二条规则 3不小于3,不满足
  • 第三条规则 3不大于等于6,不满足
  • 第四条规则3不在3和6之间,不满足

李四记录对应事务id = 2Read ViewA事务id = 5

  • 第一条规则 2不等于5 不满足
  • 第二条规则 2小于3,说明创建Read ViewA的时候李四这条记录已经提交,满足条件,可以得知Read ViewA读取到的结果为李四

3.5.5 以READ ViewB为例

此处用读提交隔离级别进行分析

通过对上图示例分析可以得知Read ViewB当前活跃事务id集合为(4, 5),最小事务id为4,预分配事务id为6,当前事务id```为5

王五对应事务id = 3Read ViewB事务id = 5

  • 第一条规则 3不等于5 不满足
  • 第二条规则 3小于4,说明创建Read ViewB的时候王五这条记录已经提交,满足条件,可以得知Read ViewB读取到的结果为王五

4.小结

本文主要跟你介绍了事务特性,事务隔离级别,并针对读提交隔离级别进行了理论与技术分析,希望能让你对事务隔离级别有一个更清晰的认识。