暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL 高频面试题解析 第05期:MVCC 怎么实现的

悦专栏 2020-11-09
9878
作者简介
马听,多年 DBA 实战经验,对 MySQL、 Redis、ClickHouse 等数据库有一定了解,专栏《一线数据库工程师带你深入理解 MySQL》、《Redis 运维实战》作者。

在有关 MySQL 的面试中,是不是 MVCC 经常会被问到?这节内容就来聊聊这个。

1 从一个实验讲起

在说 MVCC(Multi-Version Concurrency Control,多版本并发控制)原理之前,先一起看看一个例子。
创建一张测试表并写入测试数据:
进行实验:
    create database likecolumn;
    use likecolumn;
    CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `a` int(11) NOT NULL,
    `b` int(11) NOT NULL,
    PRIMARY KEY (`id`),
    KEY `idx_c` (`a`)
    ) ENGINE=InnoDB CHARSET=utf8mb4;
    insert into t1(a,b) values (1,1),(2,2);

    序号session1session2
    1
    set session transaction_isolation='READCOMMITTED';/* 设置会话隔离级别为 RC*/
    set session transaction_isolation='READCOMMITTED';/* 设置会话隔离级别为 RC*/
    2
    select * from t1;

    3
    begin;

    4
    update t1 set b=666 where a=1;

    5

    begin;
    6

    select * from t1;
    7
    commit;

    8

    select * from t1;
    9

    commit;
    这里解释一下上面的实验过程,在 session1 开启一个事务更新了 a=1 这行记录,但还没提交的情况下,在 session2 中,满足 a=1 这条记录,b 的值还是原始值 1,而不是 session1 更新之后的 666,那么在数据库层面,这是怎么实现的呢?
    其实 InnoDB 就是通过 MVCC 和 UNDO LOG 来实现的。

    2 什么是 MVCC

    MVCC, 即多版本并发控制。MVCC 的实现,是通过保存数据在某个时间点的快照来实现的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。
    也就是上面实验第 6 步中,为什么 session2 查询的结果还是 session1 修改之前的记录。

    3 MVCC 的实现原理

    对于 InnoDB ,聚簇索引记录中包含 3 个隐藏的列:
    • ROW ID:隐藏的自增 ID,如果表没有主键,InnoDB 会自动按 ROW ID 产生一个聚集索引树。
    • 事务 ID:记录最后一次修改该记录的事务 ID。
    • 回滚指针:指向这条记录的上一个版本。
    我们拿上面的例子,对应解释下 MVCC 的实现原理,如下图:
    如图,首先 insert 语句向表 t1 中插入了一条数据,a 字段为 1,b 字段为 1, ROW ID 也为 1 ,事务 ID 假设为 1,回滚指针假设为 null。当执行 update t1 set b=666 where a=1 时,大致步骤如下:
    • 数据库会先对满足 a=1 的行加排他锁;
    • 然后将原记录复制到 undo 表空间中;
    • 修改 b 字段的值为 666,修改事务 ID 为 2;
    • 并通过隐藏的回滚指针指向 undo log 中的历史记录;
    • 事务提交,释放前面对满足 a=1 的行所加的排他锁。
    在前面实验的第 6 步中,session2 查询的结果是 session1 修改之前的记录,这个记录就是来自 undolog 中。
    因此可以总结出 MVCC 实现的原理大致是:
    InnoDB 每一行数据都有一个隐藏的回滚指针,用于指向该行修改前的最后一个历史版本,这个历史版本存放在 undo log 中。如果要执行更新操作,会将原记录放入 undo log 中,并通过隐藏的回滚指针指向 undo log 中的原记录。其它事务此时需要查询时,就是查询 undo log 中这行数据的最后一个历史版本。
    MVCC 最大的好处是读不加锁,读写不冲突,极大地增加了 MySQL 的并发性。通过 MVCC,保证了事务 ACID 中的 I(隔离性)特性。

    本文已收录进 专栏《MySQL 高频面试题解析》

    相关文章:
    1. 一条 update 语句的生命历程
    2. 当前读和快照读的区别
    3. InnoDB 怎么做表空间迁移
    4. RR 隔离级别下真的不会产生幻读吗?
    5. MVCC 怎么实现的?
    6. 复制的演进历程
    7. 有哪些死锁场景?
    8. 物理备份和逻辑备份的区别

    最后修改时间:2020-11-12 18:51:05
    文章转载自悦专栏,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论

    文集目录
    暂无数据