MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
cc959798
V2EX  ›  MySQL

mysql mvcc 机制控制幻读问题

  •  
  •   cc959798 · Oct 24, 2018 · 4328 views
    This topic created in 2758 days ago, the information mentioned may be changed or developed.

    比如说 事务 A select * from tb1

    里面有三条数据

    然后开启一个事务 B

    select * from tb1 里面也是三条

    然后事务 A 插入一条并提交

    事务 B 里面看到的还是三条

    但是根据 mysql 版本控制,每行记录都有一个时间戳是事务的 id,新的事务 id 比老的事务 id 要大,事务 select 找到的行是创建时间比当前事务 id 要小的或者等于的行,但是上面的例子是事务 B 的 id 肯定比事务 A 要大,但是提交了依然看不到这是为什么?

    14 replies    2018-10-25 10:28:58 +08:00
    kuko126
        1
    kuko126  
       Oct 24, 2018   ❤️ 1
    看你事务隔离级别,RR 下 B 看不到 A 的插入是正常的
    lsongiu
        2
    lsongiu  
       Oct 24, 2018
    mysql 默认隔离级别是可重复读,这不就是可重复读吗
    cc959798
        3
    cc959798  
    OP
       Oct 24, 2018
    @kuko126 肯定是默认的
    cc959798
        4
    cc959798  
    OP
       Oct 24, 2018
    @lsongiu 问题是按照网上的原理说明,后开启的事务是可以查到自己开启后提交到事务的新插入的或者说变更的
    kuko126
        5
    kuko126  
       Oct 24, 2018
    @cc959798 mysql 的 RR 是解决了幻读问题的 所以看不到
    lsongiu
        6
    lsongiu  
       Oct 24, 2018
    @cc959798 那得等 A 事务提交之后才能查出来
    Codingless
        7
    Codingless  
       Oct 24, 2018
    可见性的判断不是通过比较行记录事务 ID 和当前事务 ID 的实现的,是通过比较行记录对应 MVCC 版本链上某个节点的事务 ID 和当前查询对应的 ReadView 中若干个值(具体的比较规则代码里很清楚)实现的,具体可以了解一下 MVCC 和 ReadView 实现相关的内容。
    zjsxwc
        8
    zjsxwc  
       Oct 24, 2018
    正常,Mysql 默认事务隔离级别 Repeatable Read 是会幻读的,想要不幻读需要开 Serializable 级别隔离
    cc959798
        9
    cc959798  
    OP
       Oct 24, 2018
    @lsongiu 事实是事务 A 提交了也查不出来,这个也是满足可重复读的特性
    lsongiu
        10
    lsongiu  
       Oct 24, 2018
    A ->开始 -> 修改 -> 提交
    b ->开始 ->第一次查询 ->第二次查询 。这时候查出出来的都是修改过的

    A ->开始 -> 修改 -> 提交
    b ->开始 ->第一次查询 ->第二次查询 。这时候查出出来的都是修改前的
    lsongiu
        11
    lsongiu  
       Oct 24, 2018
    。。。这万一还自动去空格啊。。白写了
    NNS71L068O2v70DB
        12
    NNS71L068O2v70DB  
       Oct 24, 2018
    我的理解,判断的不是事务 ID,而是系统版本号。每个行都有一个字段存系统版本号,版本号可能是时间戳,所以 a insert 操作的话,修改行版本号(时间戳)> b 的事务 id,所以对 b 不可见
    cc959798
        13
    cc959798  
    OP
       Oct 25, 2018
    @jojojo 但是怎么解释老的事务比如 A 能看到这个新的修改,A 的 id 是小于新产生的版本号的,感觉网上讲的都不清不楚,而且大部分都是复制粘贴
    cc959798
        14
    cc959798  
    OP
       Oct 25, 2018
    @lsongiu 对白写都是一样的。现在可以知道的是默认隔离级别下,两个事务开启,无论谁先谁后,只要新的事务再老的 commit 之前开启的话,两个事务里面无论怎么改,select 都是自己看到的,除非是加锁,就是直接读而不是快照读,关键不知道他是怎么实现的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5512 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 56ms · UTC 05:47 · PVG 13:47 · LAX 22:47 · JFK 01:47
    ♥ Do have faith in what you're doing.