InnoDB(6.3):锁——阻塞、死锁、锁升级

本文介绍了InnoDB存储引擎中的阻塞与死锁现象,详细解释了等待图(wait-for graph)检测机制及锁升级的概念。通过具体案例展示了如何通过调整参数来避免长时间的阻塞,并探讨了死锁发生的原因。

阻塞

阻塞情况是因为不同锁之间的兼容性关系,事务的执行可能要需要等待锁的释放才可以继续进行下去,那么在这个时间段就称为阻塞。

阻塞其实并不是一件坏事,因为阻塞是为了确保事务可以并发且正常地运行,保证数据的一致性

InnoDB使用innodb_lock_wait_timeout用来控制等待的时间(默认是50S),超过这个时间就不等待了,是要结束事务还是要回滚取决于innodb_rollback_on_timeout(默认为off),该用来设定是否在等待超时后,是否要对进行中的事务进行回滚操作。

SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
SHOW VARIABLES LIKE 'innodb_rollback_on_timeout';
//进行等待时间,设为60S
SET @@innodb_lock_wait_timeout=60;
SET @@innodb_rollback_on_timeout=on;

在这里插入图片描述
在这里插入图片描述
在默认情况下,InnoDB存储引擎不会回滚超时的异常(也就是innodb_rollback_on_timeout默认为off)。

死锁

死锁是指两个或两个以上的事务在执行过程中,因为争夺锁资源而造成一种互相等待的现象

解决死锁的方式

解决死锁的问题最简单粗暴额方法就是全部事务进行回滚,让事务重新开始,但这样会导致并发性能的下降,甚至任何一个事务都不能够进行。

解决死锁另一个方式就是一个超时,即当一个事务等待的时间超过设置的某一阈值,那么这个事务就要回滚,并释放自己的资源,然后另一个事务就可以拿到资源了,就可以继续进行下去。

虽然超时机制比较简单,根据FIFO原则(先进先出)选择回滚对象,即先进行的事务会优先进行回滚,但这种简单的选择方式会消耗更多的性能,比如要回滚的事务是业务量很大的,或者业务的权重占比比较大,或者已经更新了很多行,产生了比较多的undo页,那么选择这个事务去进行回滚就不太合适了,因为回滚这个事务的时间相对另一个事务所占用的时间可能会很多

因此,除了超时机制,InnoDB存储引擎采用的**等待图(wait-for graph)**的方式去进行死锁检测

等待图

wait-for graph需要数据库去保存下面的两种信息

  • 锁的信息链表
  • 事务等待链表

事务等待链表存储的是事务的等待顺序,即进入阻塞的链表。

锁的信息链表记录的是该行的各种锁之后要被占用的信息,相当于行程规划。

举个栗子
在这里插入图片描述
Transacting Wait Lists里面的事务指向row里面的锁,表示事务正在等待指向的锁以上的那些锁的释放

比如T1指向了row1的S锁,代表T1想要row1的S锁,但需要等T2将row1的X锁释放。

所以上面这幅图,总共有T1、T2、T3在等待锁

  • T1在等待T2释放row1的X锁
  • T2在等待T4释放row2的S锁,等待T1释放row2的S锁
  • T3在等待T2释放row2的X锁,等待T4释放row2的S锁,等待T1释放row2的S锁

那么生成的wait-for graph图如下所示
在这里插入图片描述
只要wait-for graph图中出现回路,就代表出现了死锁情况,很明显,上图中T1和T2就形成了回路,生成了一个死锁。

wait-for graph是一种较为主动的死锁检测机制,在每个事务请求锁并发生等待时都会判断是否存在回路,若存在则代表出现了死锁,一般来说,InnoDB会选择回滚undo量最小的事务

拓展:为何外键无索引会导致死锁发生

假设有A事务,往子表中增加数据会修改数据,那么它需要子表的行锁(X锁)或表锁(X锁,可能根据外键修改),父表的行锁(该行锁是在外键索引中的),因为外键没有索引,那么就会升级成表锁,那么就需要等待别的事务释放表锁,而表锁的释放比行锁麻烦,因为表锁是意向锁,表示对该表访问一些数据,或者修改一些数据,而不是像行锁,行锁只要对行数据操作完了就会释放。

锁升级

锁升级是指将当前锁的粒度升级,也就是变得更粗,比如从行锁升级成页锁,然后升级成表锁。

锁升级可以减少锁的开销,锁的粒度越低,那么锁就越多,对应的开销也就越大,所以升级锁在一定程度上提高了效率

锁升级虽然减少了开销,但会导致并发性能的降低。

一般来说,InnoDB都是行锁、间隙锁,只有在缺失索引的条件下才会升级成表锁,也就是意向锁。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值