• MVCC之RC、RR隔离级别下可见性的分析


    准备

    基础知识

    需要了解MVCC的原理与实现。

    点击链接查看:《Mysql 进阶》 · 语雀

    常用命令

    • 查看默认隔离级别show variables like 'transaction%';
    1. +----------------------------------+-----------------+
    2. | Variable_name | Value |
    3. +----------------------------------+-----------------+
    4. | transaction_alloc_block_size | 8192 |
    5. | transaction_allow_batching | OFF |
    6. | transaction_isolation | REPEATABLE-READ |
    7. | transaction_prealloc_size | 4096 |
    8. | transaction_read_only | OFF |
    9. | transaction_write_set_extraction | XXHASH64 |
    10. +----------------------------------+-----------------+
    • 修改隔离级别SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL level
    1. level: {
    2. REPEATABLE READ
    3. | READ COMMITTED
    4. | READ UNCOMMITTED
    5. | SERIALIZABLE
    6. }
    • 是否默认提交事务select @@autocommit
    1. +--------------+
    2. | @@autocommit |
    3. +--------------+
    4. | 1 |
    5. +--------------+
    • 设置为RCset session transaction isolation level read committed;
    • 开启一个事务start transaction; | begin;
    • 查看当前活动的事务SELECT * FROM information_schema.INNODB_TRX;

    RC隔离级别可见性分析

    1. CREATE TABLE IF NOT EXISTS `sanguo` (
    2. `id` int NOT NULL AUTO_INCREMENT,
    3. `name` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
    4. `age` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
    5. PRIMARY KEY (`id`)
    6. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
    7. INSERT INTO `sanguo` (`id`, `name`, `age`) VALUES (1, '刘备', '20');

    时间

    会话A(TRX_ID=5)

    会话B(TRX_ID=6)

    会话C(TRX_ID=7)

    T0

    设置隔离级别为RC:set session transaction isolation level read committed;

    T1

    开启事务: begin;

    T2

    更新为关羽:

    UPDATE `sanguo` SET `id`=1, `name`='关羽', `age`='20' WHERE `id`=1;

    T3

    更新为张飞:

    UPDATE `sanguo` SET `id`=1, `name`='张飞', `age`='20' WHERE `id`=1;

    T4

    更新为赵云:

    UPDATE `sanguo` SET `id`=1, `name`='赵云', `age`='20' WHERE `id`=1;

    T5

    更新为诸葛亮:

    UPDATE `sanguo` SET `id`=1, `name`='诸葛亮', `age`='20' WHERE `id`=1;

    T6

    查询记录:(刘备)

    select * from sanguo;

    T7

    提交事务:

    commit;

    T8

    查询记录:(张飞)

    select * from sanguo;

    T9

    提交事务:

    commit;

    T10

    查询记录:(诸葛亮)

    select * from sanguo;

    我们将目光定位到T6时刻,此时的Undo Log 的状态和ReadView的情况:

    根据可见性规则,T6时刻会话C查询的结果是刘备。

    可见性规则:

    • 如果TRX_ID小于m_low_llimit_id,则说明相对于当前事务来说,这个数据已提交,可以访问。
    • TRX_ID等于当前事务的ID(m_creator_trx_id),可以访问。
    • TRX_ID大于等于m_up_limit_id,说明这个数据版本是事务之后创建的,不可访问。
    • 如果TRX_ID在m_low_limit_id~m_up_limit_id之间,的话,就检查TRX_ID是否在m_ids里面,在的话不能访问。

    当来到T8时刻,在RC隔离级别下,每次Select都生成一条ReadView,所以此时的ReadView情况如下:

    所以,当会话C再次查询记录的时候,根据可见性规则,查询的结果将是张飞。

    同理,当T9时刻会话B提交事务之后,T10时刻会话C能查询记录结果为诸葛亮。

    RR 隔离级别下的可见性分析

    跟RC隔离级别不同的是,在第一次Select生成ReadView记录之后,后续就一直重用,不生成新的ReadView记录。

    所以,在上一个案例的基础上,我们聚焦T8时刻,此时,Undo Log和ReadView的情况如下:

    可以看到,RR隔离级别下,会话C继续沿用第一次生成的ReadView记录,所以,即使T7时刻会话A提交了事务,但还是能重复读取到刘备。

  • 相关阅读:
    .NET如何快速比较两个byte数组是否相等
    ping no reply
    UML模型和类的六大关系
    大数据在电力行业的应用案例100讲(十三)-可视化在线建模
    【ShardingSphere-proxy +PostgreSQL实现读写分离(静态策略)】
    9.2 校招 内推 面经
    【JS重点15】原型对象概述
    C语言---函数---总结
    米桃安全漏洞讲堂系列第4期:WebShell木马专题
    Spring——Spring核心基于注解方式的DI实现IoC的设计思想-搭建三层架构项目样例
  • 原文地址:https://blog.csdn.net/qq_38974073/article/details/127641405