背景说明:

公司内部一套自建分布式交易服务平台,在POC稳定性压力测试的时候出现了数据库死锁。(InnoDB引擎)由于保密性,假设是app_test表死锁了。

现象:

发生异常:Deadlock found when trying to get lock; try restarting transaction

分析思路:

1、回忆和查找相关资料,InnoDB死锁导致的原因。

第一:涉及多表访问,两个事务相互占有对方需要的锁。假设有A表(含有初始化记录1)和B表(含有初始化记录2)。进行如下操作会发生死锁。(先设置set autocommit=0; 不自动提交事务)

事务1: updateA表记录1,where条件带主键索引。         事务2: updateB表记录2 ,where条件带主键索引

事务1:updateB表记录2 ,where条件带主键索引            事务2: updateA表记录1,where条件带主键索引 (Deadlock)

第二:单表单记录访问,两个事务相互占有对方需要的锁。假设有A表(含有初始化记录1) 进行如下操作会发生死锁  (先设置set autocommit=0; 不自动提交事务)

事务1: select A表记录1 lock in share mode where条件带主键索引。 事务2:select A表记录1 lock in share mode where条件带主键索引。

事务2: updateA表记录1 where条件带主键索引                                   事务2: updateA表记录1 where条件带主键索引  (Deadlock)

2、查看根据死锁的sql语句找到代码逻辑。下面代码逻辑就仅仅以操作数据库的形式体现。(毕竟数据库经过这么多人的验证,先怀疑是否程序操作数据库有问题。)

begin;

select liusmc ,huancdx ,buchang ,liuszdz ,liuszxz ,dangqzh  from app_test where liusbm = 'chkseq' AND xitongbs = '110' AND farendma = '985' for update;   

UPDATE app_test SET liusmc = 'chkseq', huancdx = 10000, buchang = 1, liuszdz = 99999999, liuszxz = 0, dangqzh = 3380100 WHERE liusbm = 'chkseq' AND xitongbs = '110' AND farendma = '985' ;

commit;

3、根据代码逻辑分析,sql采用的是 for update 添加的排他锁,而且是单表操作,还检查了表的索引情况(此表无索引,此处很关键),于是潜意识里面 排除了,第一和第二个导致死锁的原因。此处又陷入死胡同。能想到的两个原因都排除了。

4、于是想使用show engine innodb status 命令来查询Deadlock的具体信息究竟是那两个事务锁住了什么资源,导致了死锁。但是奈何没有数据库权限。又不好意思直接问甲方的管理员要。所以还是先自己梳理思路,查询相关资料。

5、后来决定模拟下代码逻辑操作数据库的场景。毕竟就一个事务select for update了一个表然后再update,两个事务执行这个的先后顺序,以及查询的是否相同记录也是容易模拟。于是模拟了以下场景。

场景模拟:

1、两个事务,事务1 先select for update 记录1  ,事务2 select for update 记录1  ;事务1 update记录1 (此场景不会死锁)

2、两个事务,事务1 先select for update 记录1  ,事务2 select for update 记录2  ;事务1 update记录1 (居然死锁发生了,不是说InnoDB引擎 在表无索引的情况下是锁表的么?知识范围有缺陷还是深度不够?此时的我真的在心中万马奔腾啊)

思绪良久,翻阅了好多资料,实在想不通了,于是厚着脸皮也不怕影响POC成绩的情况下,请教了甲方老的DBA协助查看下。DBA叫我复现以下,我说明了现象以及原因。然后也复现了。

DBA的回复是:

事务1 持有锁   事务2需要事务1持有的锁,事务1 的update操作需要获取锁,所以出现了回路,发生死锁。外带了一句主要问题where条件多列检测索引。解决方法就是添加索引。由于DBA领导一句话,要是这个原因清楚了,此话题就到此结束。所以没敢多问,环境维护人员漏加索引了(此表本来有主键索引的)。

对于DBA的这个解释,”还是没有懂,事务1持有锁,事务2需要事务1持有的锁。事务1 update操作需要获取这个锁,所以出现了回路,发生了死锁。”  事务2只是在等待这个事务1 占有的锁而已,为何事务1的update操作需要获取锁会被事务2 占有。难道在等待也是算占有的? 如果等待也算是占有的话,那么场景1模拟的也应该会是死锁。所以明显不是。

DBA查看的日志信息的时候给了一个截图很关键,app_test 的索引 gen_clust_index 被锁住了。我觉得原因出在这个隐藏主键上面。InnoDB在表无唯一索引和主键的情况下,会自动创聚焦索引。

select * from information_schema.INNODB_LOCKS;
select * from information_schema.INNODB_LOCK_WAITS;

当两个事务进程 select for update where条件 使用同一个主键的时候,INNODB_LOCKS 会有两个事务进行的锁定信息,INNODB_LOCK_WAITS也会有一条记录,这个问题,以后待补充查证吧。

MySQL数据库死锁分析的更多相关文章

  1. Mysql数据库死锁分析相关概念

    参考博客: mysql死锁问题分析(https://www.cnblogs.com/LBSer/p/5183300.html) mysql insert锁机制(http://yeshaoting.cn ...

  2. mysql数据库死锁的产生原因及解决办法

    这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下   数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...

  3. MySQL 数据库死锁

    数据库死锁 死锁的解决办法(1) 执行下面SQL,先查看哪些表被锁住了: select b.owner,b.object_name,a.session_id,a.locked_mode from v$ ...

  4. Mysql查询语句使用select.. for update导致的数据库死锁分析

    近期有一个业务需求,多台机器需要同时从Mysql一个表里查询数据并做后续业务逻辑,为了防止多台机器同时拿到一样的数据,每台机器需要在获取时锁住获取数据的数据段,保证多台机器不拿到相同的数据. 我们My ...

  5. 记一次线上MySQL数据库死锁问题

            最近线上项目报了一个MySQL死锁(DealLock)错误,虽说对业务上是没有什么影响的,由于自己对数据库锁这块了解不是很多,之前也没怎么的在线上碰到过.这次刚好遇到了,便在此记录一下 ...

  6. 关于在项目中遇到MySQL数据库死锁的问题

    在MySQL中, 当一个事务去更新某条数据, 还没有提交的时候, 第二个事务去更新该数据, 则会出现等待获取锁超时异常: >> Lock wait timeout exceeded; tr ...

  7. mysql数据库死锁的解决方案

    1. 查询锁表信息    show OPEN TABLES where In_use > 0;2. 查看当前数据库锁表的情况    SELECT * FROM information_schem ...

  8. Mybatis-update - 数据库死锁 - 获取数据库连接池等待

    最近学习测试mybatis,单个增删改查都没问题,最后使用mvn test的时候发现了几个问题: update失败,原因是数据库死锁 select等待,原因是connection连接池被用光了,需要等 ...

  9. <转>一个最不可思议的MySQL死锁分析

    1 死锁问题背景 1 1.1 一个不可思议的死锁 1 1.1.1 初步分析 3 1.2 如何阅读死锁日志 3 2 死锁原因深入剖析 4 2.1 Delete操作的加锁逻辑 4 2.2 死锁预防策略 5 ...

随机推荐

  1. 在iOS 4中创建一个LDGradientView样式的渐变视图

    本教程将演示如何在 Swift 4 中创建一个多功能的.@IBDesignable 样式的渐变视图类.你可以将 CAGradientView 放到 storyboard 中,并在设计时预览,或者以编程 ...

  2. char 和 byte 区别

    byte 是字节数据类型 ,是有符号型的,占1 个字节:大小范围为-128-127 . char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 ):大小范围 是0-65535 :char ...

  3. Angular 富文本编辑之路的探索

    作者:杨振兴Worktile 前端工程师,PingCode Wiki 产品技术负责人 PingCode Wiki 提供结构化知识库来记载信息和知识,便于团队沉淀经验.共享资源,欢迎大家注册试用 本文主 ...

  4. CorelDRAW中如何精确移动对象

    图形的变换操作包括改变图形的位置.大小.比例,旋转图形.镜像图形和倾斜图形,是在绘图编辑时经常使用的操作.使用"选择工具"选择对象之后,在对象上按下鼠标左键并拖动,即可任意移动对象 ...

  5. ELK---- Elasticsearch 使用ik中文分词器增加拓展热词

    进入到我们ik分词器安装目录下的config目录 cd /usr/local/myapp/elasticsearch-6.4.3/plugins/ik/configvi IKAnalyzer.cfg. ...

  6. WebsitePanel密码解密

    WebsitePanel是一套Windows系统中的虚拟主机管理系统,可以同时管理多台服务器. 通过反编译该系统的dll发现该系统的密码加密方式可逆. 解密流程 1,获取密钥 密钥保存在  Enter ...

  7. 解决-Chrome插件安装时程序包无效:"CRX_HEADER_INVALID"

    最近安装新的谷歌插件出现 :程序包无效:"CRX_HEADER_INVALID" 原因如下: 在地址栏输入chrome://settings/help 如果,你的 Chrome 浏 ...

  8. 简单好用的TCP/UDP高并发性能测试工具

    工具下载地址: 链接:https://pan.baidu.com/s/1fJ6Kz-mfFu_RANrgKqYiyA 提取码:0pyf 最近测试智能设备的远程的性能,思路主要是通过UDP对IP和端口发 ...

  9. LeetCode 041 First Missing Positive

    题目要求:First Missing Positive Given an unsorted integer array, find the first missing positive integer ...

  10. git的使用以及git和码云的连接

    什么是git? ​ Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.可以保存许多的历史版本,并且可以多人同时进行开发. 分布式版本控制系统 ​ 每个人拥有该项目 ...