mysql update用not in太慢了_MySQL 加锁和死锁解析
目錄
產生死鎖的必要條件
常規鎖模式
鎖的屬性
鎖組合(屬性+模式)
鎖沖突矩陣
鎖是加在那里的?
操作與加鎖的對照關系
那些操作會加GAP鎖?
如何去掉GAP鎖?
Insert
Delete
Update
GAP鎖
什么時候加next-key lock?
Insert Intention Lock
總結
產生死鎖的必要條件
多個并發事務(2個或者以上)
每個事物都持有了鎖(或者是已經在等待鎖)
每個事務都需要再繼續持有鎖(為了完成事務邏輯,還必須更新更多的行)
事物之間產生加鎖的循環等待,形成死鎖
常規鎖模式
LOCK_S(讀鎖,共享鎖)
LOCK_X(寫鎖,排它鎖)
鎖的屬性
LOCK _REC_NOT_GAP(鎖記錄)
LOCK_GAP(鎖記錄前的GAP)
LOCK_ORDINARY(同時鎖記錄+記錄前的GAP,Next key鎖)
LOCK_INSERT_INTETION(插入意向鎖)
鎖組合(屬性+模式)
可以任意組合鎖沖突矩陣
鎖是加在哪里的?
根據主鍵查找-鎖加在主鍵上
如 begin;select * from tt_copy where id=4 for update;加鎖情況
根據普通索引查找-鎖加在普通索引和主鍵上
如 begin;select * from tt_copy force index(idx_a) where a=4 for update;加鎖情況
index PRIMARY of table test.tt_copy trx id 1101590 lock_mode X locks rec but not gap操作與加鎖的對照關系以下沒特殊說明都為RC隔離級別Insert
無Unique key,插入后 :
無論RC或RR隔離級別都是對主鍵加 LOCK_X+LOCK_REC_NOT_GAP
有Unique key
插入前,插入的位置有GAP鎖:LOCK_INSERT_INTETION
插入后,新數據插入:LOCK_X+LOCK_REC_NOT_GAP
Delete
滿足刪除條件的所有記錄:LOCK_X+LOCK_REC_NOT_GAPUpdate
**Update操作分解 **
Step ?1:
定位到 下一條滿足查詢條件的記錄(查詢過程,類似于Select/Delete)
Step ?2:
刪除當前定位到的記錄(標記為刪除狀態)
Step ?3:
拼裝更新后項,根據更新后項定位到 新的插入位置
Step ?4:
在新的插入位置,判斷是否存在 Unique ?沖突( 存在Unique ?Key 時)
Step ?5:
插入更新后項(不存在Unique沖突時)
Step ?6:
重復Step ?1 到Step ?5 的操作,直至掃描完整個查詢范圍
Update操作分析
Step ?1,Step ?2:
Delete
Step ?3,Step ?4,Step ?5:
Insert
Update
無Unique key:
查詢范圍中的所有記錄,LOCK_X ?+ ?LOCK_REC_NOT_GAP
有Unique key:
查找滿足條件的記錄:
查詢范圍內的所有記錄, LOCK_X ?+ ?LOCK_REC_NOT_GAP
更新后項存在唯一性沖突:
沖突項上的加鎖,LOCK_S ?+ ?LOCK_ORDINARY
更新后項不存在唯一性沖突:
更新位置后項加鎖,LOCK_S ?+ ?LOCK_GAP (省略)
實際更新操作:
可看做插入了一條新紀錄,LOCK_X ?+ ?LOCK_REC_NOT_GAP
GAP鎖那些操作會加GAP鎖?
Read ?Committed (RC) ) :
Unique ?Key 唯一約束檢查;
Purge操作;
Repeatable ?Read (RC ):
RC的基礎上,所有需要加鎖的索引范圍掃描和索引查找(Update/Delete…)
還有一種會加GAP鎖:
RR隔離級別下,對有唯一索引的表執行insert on ?duplicate update操作,除了會對新插入的記錄加x not gap外,還會對相鄰記錄加x gap
如何去掉GAP鎖?
change the transaction isolation level to READ COMMITTED or enable the innodb_locks_unsafe_for_binlog system variable (which is now deprecated)什么時候加next-key lock?
By default, InnoDB operates in REPEATABLE READ transaction isolation level. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rowsInsert Intention Lock
An insert intention lock is a type of gap lock set by INSERT operations prior to(在...之前) row insertion.總結
? ?原則之一
要分析一個死鎖,必須深入業務,了解整個事務的邏輯(閉門無法造車)
? ?原則之二`
GAP鎖很復雜,為了減少GAP鎖,減少GAP導致的死鎖,盡量選擇Read ?Committed隔離級別(RC + ?row ?based ?binlog,基本上能夠解決所有問題,無需使用Repeatable ?Read)
適當的 減少Unique 索引,能夠減少GAP鎖導致的死鎖(根據業務情況而定)
? ?原則之三
在MySQL 中,以不同索引的過濾條件, 來操作相同的記錄(Update/Delete ),很容易產生死
鎖。
? ?原則之四
RC隔離級別下,如果死鎖中出現Next ?Key(Gap鎖),說明表中一定存在unique索引
多語句事務產生的死鎖,確保每條語句操作記錄的順序性,能夠極大減少死鎖
作者:jiaxin
出處:cnblogs.com/YangJiaXin/
總結
以上是生活随笔為你收集整理的mysql update用not in太慢了_MySQL 加锁和死锁解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c hello world_世界上最难的
- 下一篇: 小甲鱼python课后作业十七_小甲鱼P