• REPEATABLE READ如何确定数据行的版本?


    REPEATABLE READ如何确定数据行的版本?

    众所周知,在事务隔离级别REPEATABLE READ的情况下,我们读到的行数据版本是事务开始时候的版本,但是在具体实现上,这里有一个疑问,数据库到底使用的是begin开始时候的版本?还是begin开始后,我们第一次读相关行数据时候的版本呢?也就是什么时候决定本次事务能够读到的行的版本。先不要急着下结论,让我们以mysqld 8.0.20-debug为例子,看下MySQL究竟是怎么实现的。

    1 表

    表的schema为:

    create table t(
        a int PRIMARY KEY,
        b int
    );
    
    insert into t values(1,1),(2,2),(4,4),(5,5);
    

    2 第一个例子

    两个session的操作顺序如下:

    时间线 session A session B
    1 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    begin;
    2 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    begin;
    update t set b = b * 10 where a = 2;
    commit;
    3 select * from t where a = 2;

    在sessionA中,读到的结果如下所示:

    +---+------+
    | a | b    |
    +---+------+
    | 2 |   20 |
    +---+------+
    

    可以看到,似乎MySQL是在第一次读该行时决定本次事务应该使用哪个版本?但到底是不是这样呢?让我们把数据恢复到一开始的值,看第二个例子。

    3 第二个例子

    两个session的操作顺序如下:

    时间线 session A session B
    1 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    begin;
    select * from t where a = 4;//这里读取一个不相关的行
    2 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    begin;
    update t set b = b * 10 where a = 2;
    commit;
    3 select * from t where a = 2;

    在这个例子里面,不同的地方在表格中已经加黑,而在这个例子里面,sessionA中,读到的结果如下所示:

    +---+------+
    | a | b    |
    +---+------+
    | 2 |    2 |
    +---+------+
    

    而这一次,因为我们读到了一个不相关的值,却导致了a=2这一行读到的值发生了变化,那么结果其实很显而易见了。

    MySQL在决定REPEATABLE READ使用的行版本的时候,其实是在用户第一次读相关行的时候决定的,只不过,这个是以page为单位的,这也就是第二个例子里面,为啥读了a=4的值却导致了a=2的值发生了变化的原因。

    这是一个小小的区别,可以帮助我们更好的理解MySQL的运行机制。

  • 相关阅读:
    android so壳入口浅析
    PySide图形界面开发(一)
    对一个伪装成微信的加固病毒的分析
    ZjDroid工具介绍及脱壳详细示例
    用pyinstaller把python代码打包成exe可执行文件
    Android下so注入汇总
    利用drozer进行Android渗透测试
    OWASP移动安全漏洞Top 10
    python with原理
    腾讯云
  • 原文地址:https://www.cnblogs.com/seancheer/p/15186233.html
Copyright © 2020-2023  润新知