mysql 事务(Mvcc)学习笔记

 一、前置知识点

1.1事务四大特性(acid)

  • 原子性:一个事务的操作要么全部成功,要么全部失败
  • 一致性:事务完成时,数据保存一致状态,我的理解就是保持数据的正确性,例如AB转账后的总金额不变
  • 隔离性:不同事务之间相互独立
  • 持久性:事务的提交和回滚,对数据库的改变是永久的

1.2事务操作之间会产生的问题

  • 脏读:一个事务读到另外一个事务没有提交的数据
  • 不可重复读:一个事务的两次读取之间,另外一个事务操作了数据,针对同一个数据读到了不同的结果
  • 幻读:一个事务的两次读取之间,另外一个事务操作了数据,读到了不同行数的数据

1.3 事务的隔离级别

  • 读未提交:三个问题都没解决
  • 读已提交RC:解决脏读
  • 可重复读RR:解决脏读和不可重复读和部分的幻读
  • 串行化:全部解决,事务之间串行执行

1.4 表的三个隐藏字段

  • DB_TRX_ID: 最后一次修改这条数据的事务id
  • DB_ROLL_PTR: 指向该记录的上一个版本
  • DB_ROW_ID:主键id,如果建表的时候没有设置主键的M

二、Mvcc

在InnoDB存储引擎中是用Mvcc实现RC和RR的,会给每个事务分配一个自增的ID,

2.1ReadView

每次读取之前生成一个ReadView,这个ReadView有四个数据

  1. 当前活跃的事务id(也就是还没有提交的事务id)
  2. 活跃事务id中最小值
  3. 分配给下一个事务的id
  4. 当前事务id

2.2 Undo log

当事务对某条数据进行操作时,会将当前数据复制生成一条Undo log日志,然后将当前数据的操作事务id修改

2.3 查询过程

RC隔离级别是在每次普通SELECT的时候生成一个ReadVIew
RR隔离级别是在事务开启的时候生成一个ReadView,后续的SELECT都只用这个

在查询的时候需要将数据的操作事务id和ReadView进行比较,我的理解就是确保读到的是提交的数据

  1. 如果操作事务id < ReadView活跃事务id的最小id,说明操作这个数据的事务已经提交了,可见
  2. 如果操作事务id >= ReadView分配给下一个事务的id,说明操作这个数据的事务在ReadView之后生成,无法确认是否提交,不可见
  3. 如果操作事务id介于两者之间,且不在活跃事务id中,说明操作这个数据的事务已经提交,可见
  4. 如果操作事务id介于两者之间,且在活跃事务id中,就要分两种情况,等于ReadView的当前事务id,可见(自己读自己肯定没问题吧),不等于就不可见(说明没提交)

2.4 为什么Mvcc能解决脏读、不可重复读

在RC隔离级别下每次普通SELECT前生成一个ReadView,去Undolog版本链进行比较,按照比较规则一定读到的一定是提交的数据,所以解决脏读,但没解决不可重复读,因为两次读取之间有其他事务修改事务并提交,两次读取还是会不一样

在RR隔离级别下,事务开启的时候生成ReadView,就算两次读取之间有其他事务操作了数据并提交,因为每次读取的ReadView都一样,其他的事务要么处于在ReadView的活动事务id中,要么大于等于分配给下一个事务的id,都不可见

2.5 为什么Mvcc能解决部分幻读,而不是全部

按照RR的逻辑也解决不可重复读也解决了幻读啊?这里先介绍一个概念,当前读和快照读,当前读就是读的是所有提交的数据,而快照读读的是ReadView匹配规则的数据

会有这么一种情况,如果两次读取之间另外一个事务新增了一条数据,并且当前事务修改了那条数据,那么那条数据的操作事务id就从另外一个事务变成了当前事务,所以就可见了,自然两次读取之间就读到了不同数量的数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值