0%

多版本并发控制

多版本并发控制.png

多版本并发控制

Multi-Version Concurrency Control, MVCC

地位

InnoDB存储引擎实现隔离级别的一种具体方式

  • 主要用来实现Read Committed和Repeatable Read
  • Read Uncommitted无需MVCC
  • 只靠MVCC无法实现Serializable

基本思想

脏读和不可重复读问题的根本原因

  • 未满足隔离性,事务可以读取到其它事务未提交的修改

相关概念

  • 系统版本号(SYS_ID)

    • 每开始一个新的事务,系统版本号就会自动递增
  • 事务版本号(TRX_ID)

    • 事务开始时的系统版本号
  • 版本快照

MVCC的要求

  • 修改操作(DELETE、INSERT、UPDATE)会为数据行新增一个版本快照
  • 写操作更新最新的版本快照
  • 读操作读旧版本快照
  • 只能读取已经提交的快照

Undo日志

结构

  • 多个版本的快照存储在Undo日志中
  • 日志通过回滚指针ROLL_PTR把一个数据行的快照连起来

栗子

undo日志.png

  • 操作

    1
    2
    3
    INSERT INTO t(id, x) VALUES(1, "a");
    UPDATE t SET x="b" WHERE id=1;
    UPDATE t SET x="c" WHERE id=1;
  • 过程

    Del字段标记删除操作

ReadView

Read View.png

内容

  • 当前系统未提交的事务列表(TRX_IDs )
  • TRX_ID_MIN、TRX_ID_MAX

读操作过程

  • TRX_ID < TRX_ID_MIN

    • 该数据行快照是在当前所有未提交事务之前进行更改的,因此可以使用
  • TRX_ID > TRX_ID_MIN

    • 表示该数据行快照是在事务启动之后被更改的,因此不可使用
  • TRX_ID_MIN <= TRX_ID <= TRX_ID_MAX

    • Read Committed

      • TRX_ID in TRX_IDs

        • 该数据行快照对应的事务还没提交,所以NO
      • TRX_ID not in TRX_IDs

        • 该数据行快照对应的事务已经提交,所以YES
    • Repeatable Read

      • No matter what, No

        为了避免不可重复读

快照读与当前读

快照读

  • MVCC的Select读的是快照中的数据,无需加锁

    也可以手动加锁:

    1
    2
    SELECT * FROM table WHERE ? lock in share mode;
    SELECT * FROM table WHERE ? for update;

当前读

  • INSERT、UPDATE、DELETE需要进行加锁

Phantom Read问题

MVCC不能解决Phantom Read问题:

MVCC只能解决快照读的幻读问题,不能解决当前读的幻读问题

行锁

  • Record Locks

    • 锁定一个记录上的索引 而不是记录本身
  • Gap locks

    • 锁定索引之间的间隙
  • Next-Key locks

    • 不仅锁定一个记录上的索引,也锁定索引之间的间隙

    • 概念

      • InnoDB存储引擎的一种锁实现
    • 作用

      • 使用MVCC+Next-Key Locks可以在Repeatable Read级别下解决幻读问题