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

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

悦专栏 2020-11-09
6654
作者简介
马听,多年 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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论

    文集目录
    暂无数据