ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql5.7 为什么刚要死锁立刻就会报错而无需等待超时?

2019-09-09 19:06:13  阅读:297  来源: 互联网

标签:事务 mysql5.7 死锁 报错 mysql innodb 超时 where id


问题起因

自己做了个人造死锁的小实验:

Session1

Session2

Begin;

 

Select * from t where id=1 lock in share mode;

 

 

Begin;

 

Select * from t where id=1 lock in share mode;

 

Delete from t where id=1;//waiting

Delete from t where id=1;

//立刻报错:Deadlock found when trying to get lock; try restarting transaction

 

 

按我对mysql的理解,死锁出现之后应该慢慢等他超时然后回滚,结果这里刚敲了执行立刻错就报出来了,显然不是用的超时;那我盲猜mysql会保存每个session持有的资源,每次运行新的sql语句会把所有session以持有的资源扫描一遍看看有没有可能造成死锁。但是emmm,这个策略感觉效率会很低。

于是很好奇mysql用了什么检测机制。

答案结论

5.7版本开始,innodb_deadlock_detect开关变量被引入且默认开启。(可以用show variables like '%innodb_deadlock_detect%';查看)

于是mysql有了两种途径检测死锁:原来的等待超时和新增的死锁检测。

死锁检测的原理是构建一个以事务为顶点、锁为边的有向图,判断有向图是否存在环,存在即有死锁,所以如果同时存在大量事务,那么检测或许会非常非常慢。因此mysql对此进行了上限控制。如果运行的时候报错

TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH, WE WILL ROLL BACK FOLLOWING TRANSACTION

那就表示目前正在等待的事务数量已达到200上限。超过200个事务的等待列表被视为死锁,并且尝试检查等待列表的事务被回滚。如果锁定线程必须查看等待列表中事务拥有的超过1,000,000个锁,也可能发生相同的错误。(详见MySQL5.7文档

 

搜寻答案过程中找到的其他有趣point

innodb执行事务的完全回滚时,事务设置的所有锁都会被释放。但是,如果错误导致仅回滚一条sql语句,则该语句设置的一些锁可能会被保留。发生这种情况是因为innodb以这样一种格式存储行锁:它在以后无法知道哪个锁是由哪个语句设置的。

  1.  

 

 

 

标签:事务,mysql5.7,死锁,报错,mysql,innodb,超时,where,id
来源: https://blog.csdn.net/q2878948/article/details/100671076

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有