› 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
bestrenxs
V2EX  ›  MySQL

不懂就问:请问 Mysql/Innodb 的 RR 模式下哪种情况下需要手动加锁啊?

  •  
  •   bestrenxs ·
    xsren · Oct 9, 2017 · 6039 views
    This topic created in 3274 days ago, the information mentioned may be changed or developed.

    最近有个项目需要并发情况下读写 mysql,看了下面这两篇文章,对 InnoDB 的隔离和加锁机制有了一定的理解。 https://tech.meituan.com/innodb-lock.html http://hedengcheng.com/?p=771

    个人理解,Mysql/Innodb 的 RR 模式,大多数情况下是不需要我们手动加锁的,但是某些情况下需要手动加锁的。

    我这样理解对吗?如果对的话,哪种情况需要手动加锁啊?

    求大神指点。

    16 replies  •  2017-12-26 17:50:54 +08:00
    bestrenxs
        1
    bestrenxs  
    OP
       Oct 9, 2017
    自己顶一下!
    tuzhenyu
        2
    tuzhenyu  
       Oct 9, 2017   ❤️ 1
    Innodb 的 RR 模式通过 MVCC 和间隙锁解决了脏读,不可重复读,幻读问题,不需要手动加锁吧(同小白--)
    bestrenxs
        3
    bestrenxs  
    OP
       Oct 9, 2017
    @tuzhenyu 我又看了一遍文章,好像是你说的这样的。。谢谢
    RubyJack
        4
    RubyJack  
       Oct 9, 2017
    @tuzhenyu 别误人子弟啊,RR 哪里解决幻读了
    bestrenxs
        5
    bestrenxs  
    OP
       Oct 9, 2017
    @RubyJack 看那两篇文章 InnoDB 是通过 GAP 锁解决了。。
    RubyJack
        6
    RubyJack  
       Oct 9, 2017   ❤️ 1
    @bestrenxs 你是对的,我没有看到前面的限定条件是 mysql
    bestrenxs
        7
    bestrenxs  
    OP
       Oct 10, 2017
    @RubyJack 感谢回复
    sunkuku
        8
    sunkuku  
       Oct 24, 2017
    @bestrenxs innodb 内部实现了锁。有行锁(非空唯一索引),nextkey 锁(读写锁),意向锁。
    如果你手动加锁,这种行为会导致他和事务相互影响。如果你在 innodb 中禁用了 AUTOCOMMIT,你可以手动释放锁。但是默认配置下,任何时候不要显式的获取锁。不管用什么引擎。

    下面的 sql 语句都不符合 SQL 规范
    - select .... lock in share mode
    - select .... for update
    - lock tables
    bestrenxs
        9
    bestrenxs  
    OP
       Oct 24, 2017
    @sunkuku 好的 谢谢你
    picone
        10
    picone  
       Nov 6, 2017
    MySQL 事务默认隔离级别是 RR,会有幻读产生, 假如一个 SELECT 查询了用户的资金, 觉得够钱就 UPDATE 它。那么问题来了,如果在事务提交前另外一个 client 也 SELECT 了用户的资金,发现也够钱,也去 UPDATE 它,可能就变成负数了。
    解决方法又俩:
    1. 不太推荐而又简单的:串行化事务,也就是一个个查询去执行,不会有并发问题。
    2. 使用锁,锁定要查询的那个用户,如#8 所说的。
    但如果是做比较大的系统要注意一下死锁问题,假如有另外一个操作锁定另外一个数据,然后等待用户表的锁释放,而用户表的释放又等待刚才锁的释放, 大家互相等待,hhh。解决方法又是让他仅有一个线程获取到锁,不要同时获取到这两种锁。
    ofblyt
        11
    ofblyt  
       Dec 26, 2017
    @picone 我觉得你说的不对吧,幻读是针对 insert 来讲的,这两个 update 应该是属于可重复读级别的吧,理解有误请指正
    picone
        12
    picone  
       Dec 26, 2017
    @ofblyt #11 RR 全称 repeatable read, 可重复读。 所以这样解释有问题吗
    ofblyt
        13
    ofblyt  
       Dec 26, 2017
    @picone 但是你描述的是两个 update 的事务,应该和幻读没有关系吧,只有 insert 操作才会涉及到幻读
    picone
        14
    picone  
       Dec 26, 2017
    @ofblyt #13
    幻读是指 在事物执行过程中,相同的两个查询语句得到的记录集不同。无论 insert 或者 update 都可能发生
    https://en.wikipedia.org/wiki/Isolation_(database_systems)
    ofblyt
        15
    ofblyt  
       Dec 26, 2017
    @picone A phantom read occurs when, in the course of a transaction, new rows are added by another transaction to the records being read,不知道你看没看你链接里面的内容……
    picone
        16
    picone  
       Dec 26, 2017
    @ofblyt #15 嗯,你是对的, 他还有一个前提,需要 range-locks。感谢斧正
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   912 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 22:51 · PVG 06:51 · LAX 15:51 · JFK 18:51
    ♥ Do have faith in what you're doing.