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

MySQL 并发 insert 导致的死锁如何解决

  •  
  •   quietin · 2016-06-18 20:23:42 +08:00 · 15326 次点击
    这是一个创建于 3115 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Innodb 下, 一个表中有一个主键索引和一个非主键索引的时候

    • 对这个表的并发 insert
    • 先 delete 某些纪录, 使用到非主键索引, 再 insert

    就会发生死锁的问题, 该如何解决呢 是不是因为 db 的并发过高了

    第 1 条附言  ·  2016-06-19 01:49:19 +08:00
    其实主要还是想问死锁的问题

    两个事务都进行先 delete 后 insert 的操作,

    最后死锁, 都是 lock_mode X insert intention waiting

    原因是都要争进行插入的排他锁(LOCK X), 其中一个事务有 LOCK S

    找了半天资料也没想明白, 这个 LOCK S 到底锁的啥, delete 不也是 LOCK X 吗

    还请指教
    19 条回复    2017-01-15 20:37:21 +08:00
    realpg
        1
    realpg  
       2016-06-18 20:25:47 +08:00
    没有数据量 没有并发量级 相当于啥也没说
    quietin
        2
    quietin  
    OP
       2016-06-18 22:50:16 +08:00
    @realpg 每天读取 10W, 写入 20W 次, 波动基本平稳, 高峰是平时 3 倍左右
    lecher
        3
    lecher  
       2016-06-19 00:33:25 +08:00
    这个量级并不算高,逻辑上面调一下,为什么要真实删除记录,伪删除足以满足业务需求了。
    chinajik
        4
    chinajik  
       2016-06-19 00:36:46 +08:00
    并发改队列,我曾经作死用多线程去写 mysql... 挂了...
    mathgl
        5
    mathgl  
       2016-06-19 01:42:21 +08:00
    @chinajik mysql 并发读写有问题?还是版本问题?
    wweir
        6
    wweir  
       2016-06-19 05:48:58 +08:00 via Android
    发生死锁必定是两个事务各持一把锁,并且两个事务(依赖的事务)正在等待对方的锁。
    所以描述清楚锁的图谱基本就能理清这事了
    wweir
        7
    wweir  
       2016-06-19 05:51:46 +08:00 via Android   ❤️ 1
    前段时间无聊读了点东西,偷懒的把 X 系列锁理解为写锁, S 系列锁理解为读锁。当然,这理解是不对的
    quietin
        8
    quietin  
    OP
       2016-06-19 10:16:16 +08:00
    @chinajik 需要数据库返回的结果...不能用队列吧?
    chaegumi
        9
    chaegumi  
       2016-06-19 10:43:04 +08:00
    我现在还是小项目做了一个统计是分表的, INSERT INTO 受不了,会产生重复 key 错误,用 INSERT DELAYED INTO 就解决了
    realpg
        10
    realpg  
       2016-06-19 10:43:50 +08:00
    这点数据量,感觉是你的事务逻辑有问题
    quietin
        11
    quietin  
    OP
       2016-06-19 12:00:34 +08:00
    @realpg 我都说了死锁了, 所以...能来点干货吗
    realpg
        12
    realpg  
       2016-06-19 12:02:01 +08:00
    @quietin
    个人能力有限,就会说空话,您另请高明吧……
    swolf119
        13
    swolf119  
       2016-06-19 14:42:08 +08:00
    delete 不是根据主键的吗
    非主键索引 delete 锁全表
    incompatible
        14
    incompatible  
       2016-06-20 01:10:12 +08:00
    把事务隔离级别设为 serialized
    或者做一个悲观锁,每个事务开始之前都去获取这个悲观锁,获得了锁再继续往下做事
    skyim
        15
    skyim  
       2016-06-20 14:17:13 +08:00
    @incompatible 如果这样的话,在高并发下面不是完啦
    incompatible
        16
    incompatible  
       2016-06-20 19:18:47 +08:00 via iPhone
    @skyim 楼主的场景本来就无法应对高并发,我只是帮他解决了死锁的问题。
    quietin
        17
    quietin  
    OP
       2016-06-20 21:33:56 +08:00
    @incompatible 请问写多读少的情况, 用什么方案代替直接写 MySQL 比较好
    hbprotoss
        18
    hbprotoss  
       2016-07-13 21:02:40 +08:00
    repeatable read 隔离级别下, insert 会加间隙锁
    ihuotui
        19
    ihuotui  
       2017-01-15 20:37:21 +08:00
    这就是为什么不用 delete 语句的原因,增加一个 delete 字段, 1 代表删除, 0 代表正常。
    删除语句,和插入都是要求 X 锁,假如主键非唯一,还需要加上 gap 锁。当碰上删除一个 key 时,并插入一个相同 key ,或者删除同样的 key ,就是死锁。
    参考
    http://hedengcheng.com/?p=771
    http://hedengcheng.com/?p=844#_Toc378337498
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2128 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:22 · PVG 09:22 · LAX 17:22 · JFK 20:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.