通过死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。
这里其实大家都可以想到一个解决方式,就是超时回滚:将任何的等待都转化为回滚,并且事务重新开始。的确这是一个解决办法,但是在生产环境中,这可能导致性能的下降,所带来的问题可能比死锁问题更严重,而且很难被发现并且浪费资源。
InnoDB存储引擎中,参数innodb_lock_wait_timeout用来设置超时时间。若其仅通过超时后对事务进行回滚或者通过FIFIO的顺序选择回滚对象,若超时的事务所占的权重比较大,比如事务操作更新了很多行,占用了较多的undo log,这时采用FIFO的方式,就显得不合适了,因为回滚这个事务的时间相对于另一个事务所占用的时间可能会很多。
wait-for graph
所以,出了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。InnoDB就采用这种方式。
wait-for graph会在数据库中保留两种信息:
- 锁的信息链表
- 事务等待链表
通过上述链表可以构造出一张图,而在这个图中若存在回路,就代表存在死锁,因此资源上互相发生等待。
如图:事务t2对row1占用x锁,t1对row2占用s锁,t1等待t2释放z锁,t4等待t1释放s锁,t2等待t1,t2释放锁,t3等待t1,t2,t2释放锁,故锁关系可构成如下图:
如上图,t1,t2之间存在回路,则代表存在死锁
参考--《Mysql技术内幕-InnoDB存储引擎》