learning_notes

学习笔记

View project on GitHub

当前读、快照读、MVCC

当前读

  • 当前读, 读取的是最新版本, 并且对读取的记录加锁, 阻塞其他事务同时改动相同记录,避免出现安全问题。
  • 操作:
    • select…lock in share mode (共享读锁)
    • select…for update
    • update , delete , insert
  • 实现方式:行锁+间隙锁
  • 加锁
    • 对主键或唯一索引,如果当前读时,where条件全部精确命中(=或者in),这种场景本身就不会出现幻读,所以只会加行记录锁。
    • 没有索引的列,当前读操作时,会加全表gap锁,生产环境要注意。
    • 非唯一索引列,如果where条件部分命中(>、<、like等)或者全未命中,则会加附近Gap间隙锁。例如,某表数据如下,非唯一索引2,6,9,9,11,15。如下语句要操作非唯一索引列9的数据,gap锁将会锁定的列是(6,11],该区间内无法插入数据。

快照读

  • 读取快照数据,也就是说当某个数据正在被修改的时候,也可以进行读取该数据,保证读写不冲突。
  • 实现方式: undolog和多版本并发控制(MVCC)

如何实现快照读

  • 快照”不是全量拷贝,而是利用了数据多版本的特性,也就是MVCC
  • MVCC的核心在于每个事务自己维护的一个事务ID数组
  • 只有“快照读”的sql语句,才会生成快照,比如不加锁的select语句;
  • 而“当前读”的sql语句,是不会生成快照的,比如update,select … for update, select .. lock in share mode等;
  • Read Committed隔离级别:每次select都生成一个快照读。
  • Read Repeatable隔离级别:开启事务后第一个select语句才是快照读的地方,而不是一开启事务就快照读。
  • 可见性的原则
    • 版本未提交,不可见;
    • 版本已提交,但是是在快照创建后提交的,不可见;
    • 版本已提交,而且是在快照创建前提交的,可见。