mysql之MVCC


什么是MVCC

MVCC是全名多版本并发控制,是mysql用于处理并发事务下解决数据安全性的一种无锁机制。对应的是LBCC,基于锁的并发处理控制。

并发事务下存在的数据安全问题

  1. 脏读
  2. 不可重复读
  3. 幻读
    脏读: 一个事务读取数据的过程中,读取到另一个事务未提交到数据,这种多半是事务隔离级别为读未提交
    不可重复读:在一个事务当中,多次读取相同条件的数据,发现多次读取的数据有差异,不相同
    幻读: 在一个事务当中, 多次读取相同条件读数据,发现前后数据条数不一样 (另一个事务插入一条数据,后发生数据回滚)

    MVCC的实现原理

    MVCC的实现, 依赖隐式字段, undo.log日志, 版本链, 快照读和当前读, 读视图这个几个核心要素。
  4. 隐式字段:每一行数据记录会有额外两个固定字段 DB_TRX_ID ,表示当前事务号,事务号递增,用于判断事务执行顺序。 DB_ROLL_PTR 回滚指针,用于指向上一个版本的undo.log记录,存储与回滚段当中, DB_ROW_ID 隐含的自增ID,如果记录当中有主键或者有非空的唯一键,则不需要生成自增ID
  5. undo.log: 事务开始之前,会记录更新数据的反向操作记录,备份起来,用于事务回滚
  6. 版本链:多个事务操作同一条记录,会产生多个版本的undo.log,这些日志通过回滚指针的指向,形成一个链表,俗称版本链
  7. 快照读和当前读
    快照读:就是不加锁的读取,不阻塞
    当前读:锁定读,读取的记录是最新版本,同时需要现货去对应记录的锁
     SELECT * FROM student LOCK IN SHARE MODE;  # 共享锁
     SELECT * FROM student FOR UPDATE; # 排他锁
     INSERT INTO student values ...  # 排他锁
     DELETE FROM student WHERE ...  # 排他锁
     UPDATE student SET ...  # 排他锁
  8. 读视图,用于判断快数据照可见性的逻辑,每个sql语句都会产生一个ReadView,在ReadView当中有四个核心属性
  • create_trx_id 创建当前事务的id
  • m_ids 当前系统活跃的事务id, 这些活跃的事务,并没有提交
  • m_low_limit_id 当前活跃的事务当中最小的事务id
  • m_up_limit_id 当前系统事务id的最大值的下一个事务id,也就是即将到来的事务id
    可见性判断逻辑:
  1. 当前记录所在的事务号DB_TRX_ID,如果小于当前活跃事务最小的id,那说明是在事务开始前就已经提交了,这个版本是可见的
  2. 如果当前事务号大于还未即将到来的事务,说明是重新开启的事务,不用想,也知道是不可见的
  3. 如果当前事务号处在获取事务id的范围内,判断当前事务号是不是创建的当前事务,如果是,记录可见,如果不是,记录不可见。倘若当前事务不等于范围内的某个事务,则说明该事务已经提交了,所以当前事务也是可见的

综上基于ReadView可见性视图和undo.log日志, 得出undo.log日志保存了数据的历史快照信息,而且这些快照信息按照版本号依次串联,而ReadView的作用就是判断当前快照版本是否可读

不同隔离级别下的MVCC实现

  1. RC读一提交, 在一个事务当中,每一次查询都会产生新的ReadView, 这样就导致, 前后数据不一致,也就是产生了不可重复读的问题
  2. RR可重复读, 在一个事务开启后,只会在第一次产生ReadView,后续查询不会 在产生新的ReadView, 所以就不会出现不可重复读的情况

文章作者:
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 !
评论
  目录