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

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