MySQL当前读和快照读

1.当前读和快照读
  • 当前读:读取的是记录的最新版本,并且读取之后还要保证其他并发事务不能修改当前记录,对读取的记录加锁
    当前读:select…lock in share mode,select…for update
    当前读:update,delete,insert

  • 快照读:可能读取的并不是当前记录的最新版本,可能是之前的历史版本
    快照读:不加锁的非阻塞读,select
    不加锁的条件是在当前事务隔离级别是非serializable前提下才成立,在SE下面,由于是串行读,所以此时的快照读也退化成当前读,即select…lock in share mode模式;
    之所以出现快照读,是基于提高并发性能的考虑;
    快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免的加锁操作,因此开销更低

2.RC和RR级别下的当前读和快照读
  • 在RC隔离级别下:
    当前读和快照读读取的结果是一样的
  • 在RR隔离级别下:
    快照读有可能读到数据的历史版本
    也有可能读到数据的当前版本
    创建快照的时机决定了读取数据的版本
    快照读 ==> 另外一个线程修改 ==>当前读 ==> 快照读(最后这次快照读,读取的是历史版本)
    另外一个线程修改 ==> 当前读 ==> 快照读(最后这次快照读,读取的是当前版本)
3.RC和RR级别下的InnoDB的快照读(即非阻塞读)是如何实现的
  • 数据行里的隐式字段DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID
    DB_TRX_ID:最后一次修改改行记录的事务的ID
    DB_ROLL_PTR: 回滚指针,即写入回滚端undo日志记录,如果该行记录被更新,则undo log records包含重建该行记录被更新之前状态所包含的信息
    DB_ROW_ID:行ID,用来生成默认聚簇索引

  • undo 日志
    当我们对行记录做了变更操作时,就会存undo记录
    undo记录中存储的是老版数据,当一个旧的事物需要读取数据时,为了能读取到老版本的数据,需要顺着undo链,找到满足其可见性的记录
    undo log主要分为两种insert undo log和update undo log
    —insert undo log 事务对新纪录insert产生的undo log,只在事务回滚时需要,并且在事务提交后就可以立即丢弃
    —update undo log 事务对记录进行delete或者update时,产生的undo log,不仅在事务回滚时需要,快照读也需要,所以不能随便删除,只有当数据库所使用的快照中不涉及该记录,对应的回滚日志才会被perge线程删除
    在这里插入图片描述
    在这里插入图片描述

  • read view
    做可见性判断
    记录当前处于活动状态的所有事务ID,RR级别下,第一次快照读时创建,RC级别下,每次快照读均会创建新的
    遵循一个可见性算法:主要是将要修改的DB_TRX_ID取出来,与系统其他活跃事务ID做对比,如果大于或者等于这些ID的话,就通过DB_ROLL_PTR指针去取出undo log从上层往下层的DB_TRX_ID,直到小于这些活跃事务ID为止,这样就保证了我们获取的事务版本是当前可见的最稳定的版本

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值