mysql MVCC总结

MVCC总结

事务隔离级别
  • 读未提交
  • 读已提交 -> 解决脏读
  • 可重复读 -> 解决不可重复读
  • 序列化 -> 解决幻读
MVCC的含义

多版本并发控制,通过维护undo日志的版本链实现读已提交和可重复读。

版本链

undo日志维护一个trx_id和roll_pointer字段,其中:

  • trx_id 标识事务的id

  • roll_pointer 指向下一个undo日志

所谓版本链,即针对某条纪录的操作(undo日志)通过roll_pointer串联起来。

ReadView

MVCC通过创建一个ReadView来判断某一操作是否对当前事务可见。

规定
  • m_ids:表示活跃的trx_id
  • min_trx_id:min(m_ids)
  • max_trx_id:即将被分配的事务id,>max(m_ids)
  • creator_trx_Id:生成该RV时的trx_id
  • c_trx_id:假设被访问的事务为c_trx_id,这是我自己定义的
规则
  1. c_trx_id=creator_trx_id,说明被访问的事务即开启RV的事务,可以访问

  2. c_trx_id<min(m_ids),说明c_trx_id的事务已经提交,可以访问

  3. c_trx_id>max(m_ids),说明c_trx_id的事务在生成RV时未提交,不可以访问

  4. c_trx_id in m_ids,说明被访问的事务是活跃事务,在创建RV时未提交,不可以访问

  5. min(m_Ids)<c_trx_id<max(m_ids) && c_trx_id not in m_ids,说明被访问的事务不是活跃事务,在创建RV时已提交,可以访问

MVCC和事务隔离级别的关系
  • 读未提交

对于读未提交,无需使用mvcc(即无需引入readview),事务可以读取未提交的事务。所以版本链头的记录永远是可见的。

  • 读已提交

每次读都重新生成RV,可以确保每次读的都是最新已提交的纪录

  • 可重复读

只有在第一次读的时候生成RV,由于RV一样,所以每次读取的内容都是一样的,即使有其他事务修改了该纪录。即快照读

  • 序列化

对于序列化,mysql使用了表级锁实现,完全隔离了其他事务。

可重复读为什么不能解决幻读问题?

首先声明,可重复读解决了幻读但没完全解决。

  • 解决幻读:由于RV一样,所以每次读取的结果都是一样,即不能看到其他事务新增的纪录。在一定程度上解决了幻读问题,但并未完全解决
  • 没完全解决:假设有以下特殊情况。

事务A根据条件查询某条数据,该数据不存在;

事务B根据这个条件插入一条数据;

事务A update这条数据

事务A再次查询这条数据。

我们的RV是事务A开启的,如果没有update操作,那么两次查询的结果都是空;如果加上update操作,相当于把新纪录的trx_id修改为事务A的id,对于当前RV是可见的(参见ReadView的规则1)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值