zoukankan      html  css  js  c++  java
  • mysql并发insert deadlock分析以及解决,无delete/update/for update

    关于并发insert操作发生deadlock这个情况,一直有很多争议,而且网上的帖子所有的例证和模拟其实不一定反映了真实的情况,例如:
    https://www.percona.com/blog/2012/03/27/innodbs-gap-locks/
    http://www.cnblogs.com/LBSer/p/5183300.html 
    http://www.cnblogs.com/bamboos/p/3532150.html 
    不少的类似例子应该来说其实不少有猜测和为了重现而重现的目的。
    事实上开两个窗口,不做delete/update/select for update,仅select/insert是100%可以重现死锁场景的,也可以不出现。
    start transaction A窗口select from X where x=1,不存在则insert X表记录1。假设x存在索引。
    start transaction B窗口select from X where x=2,不存在则insert X表记录2。
    这取决于当前使用的事务隔离级别,不同的事务隔离级别下有不同的行为。

    A 会话
    USE memdb;
    SHOW VARIABLES LIKE '%autocommit%';
    SET tx_isolation='SERIALIZABLE';
    SHOW VARIABLES LIKE '%tx%';
    START TRANSACTION;
    SELECT * FROM `abcdefg` WHERE def=19 AND ghi=19 AND jkl=19;
    -- 暂停,等B窗口前半部分执行了在执行下一部分
    INSERT INTO `abcdefg`(abc,def,ghi,jkl,mnp) VALUES('19',19,19,19,1);
    COMMIT;

     USE memdb;
    SHOW VARIABLES LIKE '%autocommit%';
    SET tx_isolation='SERIALIZABLE';
    SHOW VARIABLES LIKE '%tx%';
    START TRANSACTION;
    SELECT * FROM `abcdefg` WHERE def=18 AND ghi=18 AND jkl=18;
    -- 暂停,等A窗口前半部分执行了在执行下一部分
    INSERT INTO `abcdefg`(abc,def,ghi,jkl,mnp) VALUES('18',18,18,18,1);
    COMMIT;
     
    原因在mysql的行锁实现主要分为记录锁、Gap锁、Next-key锁等。
     这三种锁定的范围不同,并且行锁不代表实现时锁定了所有已存在的符合where中明确说明的条件的行,还有可能包括隐式、不存在的记录。

     因为 SERIALIZABLE使用的是GAP锁,所以,insert时>=当前索引的所有记录都被加上了S锁,故此问题发生 。

    这也是我们遇到的,非常纯粹的只有insert操作的死锁的例子,对于使用oracle、sql server的开发人员来说时,遇到时有时候相当的不理解。

    具体见各类锁的区别http://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html。

  • 相关阅读:
    阿里云服务器,http免费转https详细教程
    springboot系列总结(二)---springboot的常用注解
    springboot系列总结(一)---初识springboot
    java 查询当天0点0分0秒
    mysql各个版本驱动jar包下载 mysql/mysql-connector-java/5.1.22
    泰坦尼克 学习
    切片
    忽略warning 警告
    迭代 递归 循环 遍历
    标准化 归一化
  • 原文地址:https://www.cnblogs.com/zhjh256/p/5757867.html
Copyright © 2011-2022 走看看