MySQL死锁分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL死锁分析相关的知识,希望对你有一定的参考价值。
熟悉或者了解数据库的朋友都知道锁的概念,这里不做过多的解析!锁的种类有很多,不同数据库的锁管理方式也不同。这里主要谈下mysql innodb引擎下的死锁。
死锁通俗的来讲就是2个事务相互请求对方持有的锁,这样就会造成2个事务相互等待对方释放的锁资源,于是这就是死锁。
事务A | 事务B |
begin; | |
select * from t where a = 1 for update; | begin; |
select * from t where a = 2 for update; | |
select * from t where a = 2 for update; | |
select * from t where a = 1 for update; #ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
首先INNODB引擎不会回滚大多数的异常,但死锁除外。再发现死锁后,Innodb会立即回滚其中一个事务(这里回滚依据,会设计到权重问题)。例子中事务B被回滚!这是最常见的一种死锁例子。
MySQL还有另外一种死锁情况:当前事务持有待插入记录的下一个记录的X锁(排他锁),但此时等待的队列中存在一个S锁的请求,则可能会发生死锁。首先创建一个测试用的表,并插入数据:
create table test( a int primary key) engine=innodb;
insert into test values (1),(2),(4),(5);
时间 | 事务A | 事务B |
1 | begin; | |
2 | begin; | |
3 | select * from test where a = 4 for update; | |
4 | select * from test where a<=4 lock in share mode; #等待 | |
5 | insert into test values (3) ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction | |
6 | #事务获得锁,正常运行 |
事务A中已经对记录4持有了X锁,但会话A插入记录3的时候会导致死锁发生。这个问题产生是由于事务B中请求记录4的S锁而发生等待,但之前请求锁对于主键记录1、2都已经成功,若再时间5能插入记录,那么事务B在获取记录4持有的S锁后,还需要向后获得记录3的记录,这显得不合理。于是INNODB引擎在这里主动选择死锁。
本文出自 “Jeff on the way” 博客,请务必保留此出处http://nrain.blog.51cto.com/11930278/1895270
以上是关于MySQL死锁分析的主要内容,如果未能解决你的问题,请参考以下文章