InnoDB鎖學習
Innodb實現標準行級鎖,有2種模式的鎖:
l S (shared locks) 共享鎖:允許擁有鎖的事務讀一行資料
l X (exclusive locks) 排他鎖:允許有用鎖的事務更新或刪除一行資料
如果一個事務T1在行r擁有一個S共享鎖,從不同的事務T2請求鎖定行r,處理如下:
l 事務T2能立即獲得行r的S共享鎖,因此,T1和T2都在行r上持有S共享鎖
l 事務T2不能獲得行r的X排它鎖
如果一個事務T1在行r持有x排它鎖,其他事務T2無法獲得任何型別的鎖。
InnoDB意向鎖
Innodb支援多粒度鎖定,這種鎖定允許事務在行級上的鎖和表級上的鎖同時存在。為了支援在不同粒度上進行加鎖操作,innodb支援一種額外的鎖方式,稱為意向鎖(intention locks)。
Innodb意向鎖為表級別的鎖,設計的主要目的主要是為了在下一個事務中揭示下一行將被請求的鎖型別。
InnoDB中有2中型別的意向鎖:
? Intention shared (IS): Transaction T intends to set S locks on individual rows in table t.
事務T想對錶t的某些行設定共享鎖
? Intention exclusive (IX): Transaction T intends to set X locks on those rows.
事務T想對錶t的某些行設定排它鎖
例如:SELECT ... LOCK IN SHARE MODE 設定了一個IS鎖
SELECT ... FOR UPDATE 設定一個IX鎖
意向鎖協議如下:
? 一個事務在可以獲得表t的某些行的S共享鎖,必須先獲取表t的IS意向共享鎖
? 一個事務在可以會的表t的某些行的X排它鎖,必須先獲取表t的IX意向排它鎖
Innodb鎖相容性矩陣
意向鎖不會堵塞除了全表操作(例:LOCK TABLES ...WRITE)以外的任何請求,其意向鎖的主要目的是顯示某些操作鎖定了某行,或者將要鎖定某行。
意向鎖的存在價值在於在定位到特定的行所持有的鎖之前,提供一種更粗粒度的鎖,可以大大節約引擎對於鎖的定位和處理的效能,因為在儲存引擎內部,鎖是由一塊獨立的資料結構維護的,鎖的數量直接決定了記憶體的消耗和併發效能。例如,事務A對錶t的某些行修改(DML通常會產生X鎖),需要對t加上意向排它鎖,在A事務完成之前,B事務來一個全表操作(alter table等),此時直接在表級別的意向排它鎖就能告訴B需要等待(因為t上有意向鎖),而不需要再去行級別判斷
意向鎖實際上可以理解為一種“暗示”未來需要什麼樣行級鎖:
IS表示未來可能需要在這個表的某些記錄上加共享鎖
IX表示未來可能需要在這個表的某些記錄上加排他鎖。
意向鎖是表級別的,IS和IX鎖之間相互並不衝突,但與表級S/X鎖衝突。
在對記錄加S鎖或者X鎖時,必須保證其在相同的表上有對應的意向鎖或者鎖強度更高的表級鎖
InnoDB記錄鎖、GAP鎖和Next-Key鎖
Innodb的行鎖的型別:
? Record lock: 鎖定一個索引記錄
? Gap lock: 鎖定一個範圍,不包含記錄本身
? Next-key lock: Gap lock+ Record lock,鎖定一個範圍,並且鎖定記錄本身
Record Locks總是鎖住索引記錄,即使表沒有定義索引,Innodb會建立一個隱試的聚集索引來鎖定。
Next-key Locks 預設Innodb使用RR的隔離級別。在這種情況下,InnoDB使用next-key鎖機制來查詢資料和索引掃描,防止幻象問題
Next-key locking結合了index-row鎖和Gap鎖。當搜尋和查詢索引操作時,InnoDB使用行鎖的方式,在相應的索引記錄上設定共享或者排他鎖。因此,行級別的鎖實際上是索引記錄鎖。而Next-Key鎖是索引記錄鎖加範圍鎖。如果一個會話在索引記錄R上加了一個共享或者排他鎖,其他會話不能立即插入一個新的索引記錄在索引記錄R之前的間隙中。
假設一個索引的值有10, 11, 13, 和20,那麼該索引可能被Next-Key Locking的區間為:
最後一個間隔範圍,Next-Key 實際上鎖定的範圍是僅僅是最大索引值後面的範圍。
當操作的索引是唯一的情況下,Innodb會對Next-key Locking進行最佳化,將其降級為Record Lock,只鎖住索引本身,而不是鎖定範圍。
如下:
Session A |
Session B |
Session A>drop table t; |
|
|
Session A>begin; |
#session A提交上面的事務 Session A>commit; |
|
上面的實驗中,表t有1,2,5三個值。在session A中對a=5進行鎖定讀X鎖定,但因為欄位a是主鍵(唯一索引),因此此時鎖定的僅是5這個索引記錄,而不是(2,5)]這個範圍,這樣在Session B中能順利的插入a=4(4在(2,5]之間)而不會阻塞。上述正式因為Next-Key Lock對唯一索引的記錄降級為record lock的原因,從而可以提高應用的併發性。
當查詢的列是非唯一的索引時,情況如下:
Session A |
Session B |
Session A>drop table t; |
|
注意:右邊的Session B看到15被堵塞,而20沒有被堵塞;所以,推測此處Gap Lock的範圍是【15,20)和(20,25)。這與官當上的http://dev.mysql.com/doc/refman/5.7/en/innodb-record-level-locks.html舉的例子的 可能的間隔範圍剛好閉開區間是反的 |
#18在[15,20)之間,被堵塞 |
Gap Locks 當使用唯一索引查詢唯一的行時,不需要Gap locks.
前面next-key的例子表明gap可能覆蓋一個單獨的索引值,多個索引值,或可能是空的。
例如:下面的語句只需要在id為100的行上使用一個index-record lock,而不會影響其他會話插入資料:
SELECT * FROM child WHERE id = 100 for update;
如果ID不是索引或者不是一個uniq index,該語句則使用Gap Locking.
插入意向Gap鎖(insert intention gap lock)在Insert操作之前被設定。這種鎖的目的是:當多個事務插入資料到相同的索引間隙,只要他們插入的索引間隙內的位置不同,則不需要相互等待。假如有索引值4和7,某個事務檢視在4和7的間隙間插入5和6,在插入的行會分配插入意向Gap鎖,但因為5和6的行並不衝突,所以不會堵塞對方。
注意:不同的事務在一個間隙(Gap)上可以持有互斥的鎖。例如:當事務B在某個Gap上擁有一個排他Gap鎖,事務A在相同的Gap上可以持有共享Gap鎖。此處允許鎖衝突共存的原因是:當從一個索引上purge一個記錄,其他事務對此記錄加的Gap鎖會被被合併。
Gap鎖在Innodb中是”完全禁止的”。這意味著它們只能防止其他事務在一個Gap中的插入操作。因此,排他Gap鎖和共享Gap鎖具有同樣的效果。
Disabling Gap Locking
Gap鎖可以被完全關閉 方法是設定事務隔離級別修改為RC,或者開啟innodb_locks_unsafe_for_binlog系統變數(此選項5.6和5.7已經被棄用)。關閉Gap的情況下,除了在外來鍵一致性檢查和逐漸衝突檢查的時候,gap鎖均不生效。
RC隔離級別和開啟innodb_locks_unsafe_for_binlog引數也會帶來其他影響,比如:在mysql分析where條件之後,未匹配行的記錄鎖就會被釋放(違反了2PL:原則)例如:在update中,innodb執行"半一致性"讀,這樣,最新的提交版本被告知mysql,然後由mysql決定行是否匹配執行Update操作的where條件。
參考連結:
http://dev.mysql.com/doc/refman/5.7/en/innodb-lock-modes.html
http://dev.mysql.com/doc/refman/5.7/en/innodb-record-level-locks.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-2083351/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- InnoDB學習(六)之資料庫鎖資料庫
- InnoDB多版本學習
- InnoDB學習(二)之ChangeBuffer
- innodb查詢鎖
- MySQL鎖:03.InnoDB行鎖MySql
- InnoDB學習(三)之BinLog
- InnoDB學習(一)之BufferPool
- Mysql innodb引擎(二)鎖MySql
- Innodb 鎖子系統
- mysql innodb的行鎖MySql
- InnoDB事務鎖之行鎖-聚集索引加鎖流程索引
- MySQL鎖:InnoDB行鎖需要避免的坑MySql
- MySQL 5.5 InnoDB表鎖行鎖測試MySql
- InnoDB學習(七)之索引結構索引
- InnoDB學習(八)之 聚簇索引索引
- MySQL入門學習之——innodb lockMySql
- InnoDB常用鎖總結(行鎖、間隙鎖、臨鍵鎖、表鎖)
- InnoDB 事務加鎖分析
- mysql innodb的行鎖(2)MySql
- mysql innodb的行鎖(3)MySql
- mysql innodb的行鎖(4)MySql
- InnoDB行鎖實現方式
- mysql事務和鎖InnoDBMySql
- mysql innodb間隙鎖示例MySql
- MySQL學習之行鎖MySql
- InnoDB事務鎖之行鎖相關結構
- InnoDB事務鎖之行鎖-insert加鎖-隱式鎖加鎖原理
- InnoDB事務鎖之行鎖-delete流程update階段加鎖delete
- MySQL:Innodb恢復的學習筆記MySql筆記
- innodb學習筆記(一) aio的使用筆記AI
- MySQL InnoDB 中的鎖機制MySql
- MySQL:Innodb 一個死鎖案例MySql
- MySQL 5.7 查詢InnoDB鎖表MySql
- 【MySQL】InnoDB鎖機制之一MySql
- 淺談Innodb的鎖實現
- Mysql研磨之InnoDB行鎖模式MySql模式
- MySQL InnoDB如何應付死鎖MySql
- 【MySQL】InnoDB鎖機制之二MySql