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

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

  •  
  •   bestrenxs ·
    xsren · 2017-10-09 14:57:10 +08:00 · 4924 次点击
    这是一个创建于 2633 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    求大神指点。

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

    下面的 sql 语句都不符合 SQL 规范
    - select .... lock in share mode
    - select .... for update
    - lock tables
    bestrenxs
        9
    bestrenxs  
    OP
       2017-10-24 12:41:51 +08:00
    @sunkuku 好的 谢谢你
    picone
        10
    picone  
       2017-11-06 17:15:29 +08:00
    MySQL 事务默认隔离级别是 RR,会有幻读产生, 假如一个 SELECT 查询了用户的资金, 觉得够钱就 UPDATE 它。那么问题来了,如果在事务提交前另外一个 client 也 SELECT 了用户的资金,发现也够钱,也去 UPDATE 它,可能就变成负数了。
    解决方法又俩:
    1. 不太推荐而又简单的:串行化事务,也就是一个个查询去执行,不会有并发问题。
    2. 使用锁,锁定要查询的那个用户,如#8 所说的。
    但如果是做比较大的系统要注意一下死锁问题,假如有另外一个操作锁定另外一个数据,然后等待用户表的锁释放,而用户表的释放又等待刚才锁的释放, 大家互相等待,hhh。解决方法又是让他仅有一个线程获取到锁,不要同时获取到这两种锁。
    ofblyt
        11
    ofblyt  
       2017-12-26 15:53:52 +08:00
    @picone 我觉得你说的不对吧,幻读是针对 insert 来讲的,这两个 update 应该是属于可重复读级别的吧,理解有误请指正
    picone
        12
    picone  
       2017-12-26 16:04:43 +08:00
    @ofblyt #11 RR 全称 repeatable read, 可重复读。 所以这样解释有问题吗
    ofblyt
        13
    ofblyt  
       2017-12-26 16:13:53 +08:00
    @picone 但是你描述的是两个 update 的事务,应该和幻读没有关系吧,只有 insert 操作才会涉及到幻读
    picone
        14
    picone  
       2017-12-26 16:19:25 +08:00
    @ofblyt #13
    幻读是指 在事物执行过程中,相同的两个查询语句得到的记录集不同。无论 insert 或者 update 都可能发生
    https://en.wikipedia.org/wiki/Isolation_(database_systems)
    ofblyt
        15
    ofblyt  
       2017-12-26 16:24:13 +08:00
    @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  
       2017-12-26 17:50:54 +08:00
    @ofblyt #15 嗯,你是对的, 他还有一个前提,需要 range-locks。感谢斧正
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1095 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:17 · PVG 03:17 · LAX 11:17 · JFK 14:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.