navicat是个碧池。session
情景:在一个事务里写上了有in 有for update的语句,被提醒可能发生死锁,因而去作一波死锁状况的测试来考虑对策测试
基本知识:当两个session都须要对方的资源而舍不得本身的资源的时候,就死锁了,因此理论上我这里可能死锁的状况是(省略了begin和commit语句,假设表为A,id为主键,index为有索引的键,normal为普通的字段):优化
Session1:select * from A where id in (2,3) for updateorm
Session2:select * from A where id in (1,2,3) for update索引
Session1:update A set normal='test' where id =1事务
DEADLOCKssl
意思就是会话一锁了2,3,会话二锁了1,遇到2,3的时候等待,会话一再想更新1,就懵逼了资源
————————————————————————————————————————————————————————it
然鹅,我就遇到了以下的不合理状况:io
1、事务级别为RR,使用终端mycli为会话一,navicat为会话二,上述语句能正常在mycli报错,但固然在两表互锁后,用会话一先更新id为2的数据,再更新id为1的数据竟然直接成功了,navicat也经过了阻塞出来了数据
2、理论上index字段也是行级锁,也会死锁,因而
Session1:select * from A where index in (2,3) for update
Session2:select * from A where index in (1,2,3) for update
Session1:update A set normal='test' where index=1
竟然顺利经过了,navicat中也在持续阻塞,两个事务都能正常手动提交
3、操做normal时是正常的表锁的状况,但explain的时候很懵逼
explain update A set normal='test'
发现type=index,key=PRIMARY,但rows是全表的条数
————————————————————————————————————————————————————————
解决过程,其实主要仍是几条查询语句切来切去来看状况,简单记录下语句
show processlist —— 查看当前的链接状态,主要看State字段
select * from information_schema.INNODB_TRX —— 查看当前事务和状态
show status like '%lock%' —— 查看当前锁状况
show OPEN TABLES where In_use > 0; —— 查看当前被锁的表
————————————————————————————————————————————————————————
结论:
一、马丹的,实际上是会话二,即navicat的事务抛出了死锁异常,而后navicat并无提醒出来。。。
二、使用in语句查询有索引的字段的时候并不必定是走的索引,优化器会根据状况选择更快的方法,这里explain一下即可知道index in (1,2) 当时的type=ALL,所以也是进行了表锁,在把数据加了不少是的type=range后,如愿发生了死锁
三、还真没查到。。。explain delete也是正常的type=ALL,多是update的特殊