事务隔离级别和MVCC多版本并发控制

1.事务并发执行带来的问题

1.1 脏写(更新丢失)

A事务覆盖了B事务更新的内容,B事务刚才的更新操作被A给覆盖掉了,称之为脏写

1.2 脏读

A事务读取到了B事务已经修改但还没有提交的内容。如果此时B回滚,那么A读取的数据就是脏数据,这个情况称之为脏读

1.3 不可重复读(模糊读)

A事务同一个SQL查询语句前后查询出来的结果不一致,叫不可重复读

1.4 幻读

A事务事先通过SQL查询出某个符合条件的记录,后续由于B事务添加了这个符合条件的记录,那么A事务再次查询的时候就比第一次多了一些记录,称之为幻读。简单说:A事务读取到了B事务新增的数据。

2.四大隔离级别

隔离级别脏读不可重复读幻读
读未提交 Read unCommitted可能可能可能
读已提交 Read Committed不可能可能可能
可重复读 Repeatable Read(默认)不可能不可能可能
串行化 Serializable不可能不可能不可能

3.MVCC多版本并发控制底层原理

3.1 undo_log版本链

InnoDB为每条记录都分配了trx_idroll_pointer两个隐藏字段,在事务中可作为事务ID和回滚指针的作用,这个回滚指针指向的就是undo日志对应的记录。
在这里插入图片描述

通过版本链就可以对同一条记录来做事务并发访问相同记录的行为,这种机制叫多版本并发控制 Mulit-Version Concurrent Control简称MVCC

3.2 Read View (一致性视图)

对于读未提交和串行化这两种隔离级别不需要进行多版本的并发控制,因为读未提交直接读取最新的记录就好,而串行化是通过锁的机制来保证。所以MVCC控制的是读已提交和可重复读这两种隔离级别。事务的隔离本质上就是数据的可见性问题,InnoDB提供了一个Read View视图来帮助事务找到自己事务可见的数据。Read View本质就是保存了当前系统中活跃事务的ID号集合,通过undo版本链来对比事务ID大小,然后结合不同的隔离级别来做可见性的判断。Read View的结构如下:

     - m_ids:生成read view时,当前系统活跃的事务ID集合。
     - min_trx_id:当前系统活跃的最小事务ID,也就是m_ids的最小值。
     - max_trx_id:当前系统活跃的最大事务ID的下一个编号。
     - creator_trx_id:当前事务的事务ID。

Read View对数据可见性的流程如下:

     1. 如果该条记录的trx_id == creator_trx_id,说明就是自己读取自己事务做的更改,可见。
     1. 如果该条记录的trx_id < min_trx_id,说明这个记录是一个很老的事务提交后的数据,可见。
     1. 如果该条记录的trx_id >= max_trx_id,说明这个记录修改的事务是一个刚开始的新事务,不可见。
     1. 如果该条记录的trx_id处于min和max之间,则判断trx_id是否在m_ids集合中,如果在活跃事务集合中说明这条记录对应的事务修改还没提交,不可见。如果不在集合中,说明已经提交了,可见。

这个过程会通过遍历undo日志链表来依次判断是否可见,如果可见就读取,否则不可见。

3.2.1 读已提交隔离级别每一次读取都会生成一个Read View

由于在事务过程中,每次读取的SQL语句都会生成新的Read View,所以视图快照里能够即时的刷新和感知到其它事务做出的提交,能够达到读已提交的要求。

3.2.2 可重复读隔离级别只会第一次读取生成一个Read View,后续的读取都是复用第一次的视图快照

由于需要保证一个事务中的可重复读的要求,所以只需要生成一个Read View即可,后续的查询语句都依赖于第一次这个视图快照,达到可重复读的效果。
如果多个事务都是通过MVCC的快照读,在可重复读的级别下,不会发生幻读问题。但是如果其中有事务通过锁的当前读,就会有幻读问题。
数据库存在id=1的数据,事务A和B都开启事务并且执行select,事务B新增id=2的数据后commit,事务A,读的话读不到id=2的数据,但是update是可以操作id=2的数据的。这就是幻读的一种表现。

4.undo和undo记录的回收

update的undo日志由于需要支持MVCC,所以日志记录不能立即回收。如果系统中最早产生的Read View不在访问这些日志,那么这些日志就可以回收掉,InnoDB后台线程会将最早生成的Read View取出来检查事务undo日志的文件头信息的事务ID号,来筛选回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Minor王智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值