V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
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
gotonull
V2EX  ›  MySQL

MySQL 可重复读隔离级别下是否解决了幻读问题

  •  
  •   gotonull · 2020-07-23 09:26:16 +08:00 · 3909 次点击
    这是一个创建于 504 天前的主题,其中的信息可能已经有所发展或是发生改变。

    MySQL 在默认的事务隔离级别下到底有没有解决幻读问题啊

    34 条回复    2020-07-24 10:20:16 +08:00
    iseki
        1
    iseki  
       2020-07-23 09:28:36 +08:00 via Android
    没有吧
    zarte
        2
    zarte  
       2020-07-23 09:29:41 +08:00
    只是事务解决不了并发
    iseki
        3
    iseki  
       2020-07-23 09:30:01 +08:00 via Android
    你看看 PostgreSQL…那个没有…有谓词锁🔒
    pingdongyi
        4
    pingdongyi  
       2020-07-23 09:30:25 +08:00 via Android
    看如何定义幻读
    iseki
        5
    iseki  
       2020-07-23 09:30:39 +08:00 via Android
    @iseki 但是 pg 默认级别好象是读提交
    nwg
        6
    nwg  
       2020-07-23 09:31:21 +08:00
    插入类型的幻读解决不了 比如:预定会议室问题
    更新类别的幻读解决了 多次查询是一个数据
    xuwei0056
        7
    xuwei0056  
       2020-07-23 09:32:42 +08:00
    解决了
    BBCCBB
        8
    BBCCBB  
       2020-07-23 09:32:45 +08:00   ❤️ 2
    解决了, 有 gap lock.
    bear2000
        10
    bear2000  
       2020-07-23 09:47:23 +08:00   ❤️ 1
    解决了。

    在非锁定读的情况下会读取一个快照数据,不会出现幻读。

    在锁定读的情况下会有间隙锁,也不会出现幻读。

    PS:推荐看一看《 MySQL 技术内幕 InnoDB 存储引擎》
    RedBeanIce
        11
    RedBeanIce  
       2020-07-23 09:55:35 +08:00
    mvcc,间隙锁(书上看的)
    huntcool001
        12
    huntcool001  
       2020-07-23 10:05:01 +08:00   ❤️ 3
    没有完全解决.
    StackoverFlow 上这个例子: https://stackoverflow.com/questions/5444915/how-to-produce-phantom-reads

    create table ab(a int primary key, b int);

    Tx1:
    begin;
    select * from ab; // empty set

    Tx2:
    begin;
    insert into ab values(1,1);
    commit;
    Tx1:
    select * from ab; // empty set, expected phantom read missing.
    update ab set b = 2 where a = 1; // 1 row affected.
    select * from ab; // 1 row. phantom read here!!!!
    lscexpress
        13
    lscexpress  
       2020-07-23 10:15:25 +08:00
    幻读影响你业务吗?
    hheedat
        14
    hheedat  
       2020-07-23 10:25:17 +08:00
    解决了 MVCC + gap lock
    maigebaoer
        15
    maigebaoer  
       2020-07-23 10:32:31 +08:00 via Android
    并没有
    jimmyismagic
        16
    jimmyismagic  
       2020-07-23 10:35:48 +08:00
    默认并没有解决幻读,因为只锁了行,对于批量处理,你可能在删了一批符合条件的数据后,又读到新的符合条件的数据
    liprais
        17
    liprais  
       2020-07-23 10:41:30 +08:00 via iPhone
    没有
    新增的不会看到
    update 的会有问题
    gadsavesme
        18
    gadsavesme  
       2020-07-23 10:46:29 +08:00
    快照读解决,当前读还是有问题
    pangleon
        19
    pangleon  
       2020-07-23 11:07:22 +08:00
    MYSQL 用间隙锁解决幻读问题,结果间隙锁又会引起别的 BUG,所以 RR 级别很多公司都不推荐使用。都是用 RC 了,毕竟人家 ORACLE 就是默认 RC 有谁去改了么?
    gotonull
        20
    gotonull  
    OP
       2020-07-23 11:11:58 +08:00
    @lscexpress 没有,只是面试的时候被问到了,我说没解决,面试官说解决了。所以来问问大神们。结果大家的回答还是各种说法都有,都给我整懵了!
    zy445566
        21
    zy445566  
       2020-07-23 11:17:36 +08:00
    @gotonull 确实解决了,就是楼上说间隙锁,使用的时候通过 select +for update 锁定控制范围
    mahone3297
        22
    mahone3297  
       2020-07-23 11:17:41 +08:00
    极客时间,Mysql 的课有讲,解决了。
    20 | 幻读是什么,幻读有什么问题?
    zgzhang
        23
    zgzhang  
       2020-07-23 11:29:59 +08:00   ❤️ 1
    在快照读读情况下,mysql 通过 mvcc 来避免幻读。
    在当前读读情况下,mysql 通过 next-key 来避免幻读。
    select * from t where a=1;属于快照读
    select * from t where a=1 lock in share mode;属于当前读

    不能把快照读和当前读得到的结果不一样这种情况认为是幻读,这是两种不同的使用。所以我认为 mysql 的 rr 级别是解决了幻读的。
    https://github.com/Yhzhtk/note/issues/42
    gotonull
        24
    gotonull  
    OP
       2020-07-23 11:34:20 +08:00
    @mahone3297 谢谢,这就去学习学习
    dxyhymn
        25
    dxyhymn  
       2020-07-23 13:46:29 +08:00
    解决了,推荐去看书,看完你就知道了,而且很透彻。
    JasonLaw
        26
    JasonLaw  
       2020-07-23 14:29:21 +08:00
    @huntcool001 #12 +1,并没有完全解决。

    https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html 中也描述了这个问题。在“The snapshot of the database state applies to SELECT statements within a transaction, not necessarily to DML statements.”这段里面。
    JasonLaw
        27
    JasonLaw  
       2020-07-23 14:35:34 +08:00
    其实我不太明白为什么这么多人都是在说 gap locking,文档里明明说的是 next-key locking 。

    https://dev.mysql.com/doc/refman/8.0/en/innodb-next-key-locking.html 中说了“To prevent phantoms, InnoDB uses an algorithm called next-key locking that combines index-row locking with gap locking.”,很明显,单纯的 gap locking 是不能阻止幻读的,index-row locking 加上 gap locking 才能够解决。
    JasonLaw
        28
    JasonLaw  
       2020-07-23 14:37:14 +08:00
    @pangleon #19 “间隙锁又会引起别的 BUG”,可以详细说明一下是什么 bug 吗?谢谢。
    pws22
        29
    pws22  
       2020-07-23 14:45:09 +08:00
    没有完全解决
    daimubai
        30
    daimubai  
       2020-07-23 22:30:09 +08:00 via iPhone
    确实使用的是 Next-lock-key 算法,它包含了 row lock 和 gap lock,默认情况下是解决了幻读的,不过不能完全避免吧,因为只会锁间隙,如果不在间隙添加也可以添加成功吧
    daimubai
        31
    daimubai  
       2020-07-23 22:31:21 +08:00 via iPhone
    MVCC 并没有解决幻读,而是解决了 RC 下的脏读和 RR 下的不可重复读
    wentaoliang
        32
    wentaoliang  
       2020-07-23 23:00:33 +08:00
    默认没有开启避免幻读,但是可以通过 for update 或者 share mode 来开启避免幻读。原理楼上以及说了
    freelancher
        33
    freelancher  
       2020-07-24 06:48:37 +08:00
    讲真。我看原理的时候就解决了。这个是在隔离特性里面。自己去看一下吧。
    leapV3
        34
    leapV3  
       2020-07-24 10:20:16 +08:00
    可重复读没有解决,需要加间隙锁
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3821 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 07:29 · PVG 15:29 · LAX 23:29 · JFK 02:29
    ♥ Do have faith in what you're doing.