死锁的概念死锁:死锁一般是事务之间互相等待资源,最后形成循环。对于死锁,数据库的处理方法:牺牲一个连接,保证另一个连接的成功执行。如果发生死锁,会返回ERROR:1213错误提示。大多数死锁可以由InnoDB存储引擎本身检测到,无需人工干预。注意:InnoDB存储引擎不会回滚大部分的错误异常,比如阻塞部分的例子,但是死锁是一个异常。发现死锁后,InnoDB存储引擎会立即回滚事务并返回1213错误。死锁示例eg1:死锁日志分析:从日志中我们可以看出事务1当前正在执行updateinfo_userssetmobile='18514656666'wheremobile='18514656620',这条语句是在申请表info_users的X锁indexIDX_MOBILE,所以提示lock_modeXwaiting第二部分:然后日志的后半部分显示了事务2当前的'locksheld'和'lockswaiting':从日志的HOLDSTHELOCKS(S)块我们可以看到即事务2持有索引IDX_MOBILE的X锁,是记录锁(RecordLock)。锁是由第2步中事务2执行的update语句申请的,从日志的WAITINGFORTHISLOCKTOBEGRANTED块中可以看出,事务2正在申请持有表的索引GEN_CLUST_INDEX的X锁info_area,通过deletefrominfo_areawhereid=1应用;陈述。eg2:eg3:死锁日志分析:***部分从日志中我们可以看出事务1当前正在执行DELETEfromuserswhereuid='bbb';,这条语句是在申请索引UID的X锁,所以提示lock_modeThesecondpartofXwaiting:然后日志的后半部分显示了事务2的当前'locksheld'和'waitinglocks':从日志的HOLDSTHELOCKS(S)块中,我们可以看到那事务2持有索引UID的X锁,它是一个记录锁(RecordLock)。锁是由步骤2中事务2执行的delete语句申请的。从日志的WAITINGFORTHISLOCKTOBEGRANTED块可以看出,事务2正在申请持有索引UID的S锁,该锁由insertINTOusersVALUES(2,'bbb');申请陈述。insert语句正常情况下会申请X锁,但是这里出现了S锁。这是因为uid字段是唯一索引,所以insert语句在插入前会进行重复键检查。为了让这个检查成功,需要申请一个S锁,防止其他事务修改uid字段。那么S锁为什么会失效呢?这是因为申请同一个字段的锁需要排队。在S锁之前有一个X锁没有申请成功,所以S锁必须等待,这样就形成了循环等待,就产生了死锁。通过阅读死锁日志,我们可以清楚的知道这两个事务形成了什么样的循环等待。进一步分析,我们可以逆向推断循环等待的原因,也就是死锁的原因。
