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的特殊