1. 程式人生 > >mysql-innodb鎖型別詳細介紹

mysql-innodb鎖型別詳細介紹

資料庫鎖定機制就是為了保證資料的一致性,使得各種共享資源在被併發訪問時變得有序。

mysql支援三種級別的鎖定機制:表級鎖定(table-level),行級鎖定(row-level),頁級鎖定(page-level)。
1.表級鎖定(table-level)
表級鎖是mysql中鎖粒度最大的鎖定機制,一次會將整張表鎖定,不會出現死鎖問題


2.行級鎖定(row-level)
行級鎖是鎖粒度最小的鎖定機制。由於鎖粒度最小,所以鎖定資源發生的爭用也就最小,這樣提高了應用程式併發處理的能力同時提高了整個系統的效能,但是每次獲取鎖和釋放鎖都要做很多事情,帶來的消耗也就增加,也最容易發生死鎖。


3.頁級鎖定(page-level)
頁級鎖定的特點是鎖定顆粒度介於行級鎖定與表級鎖之間,所以獲取鎖定所需要的資源開銷,以及所能提供的併發處理能力也同樣


是介於上面二者之間。另外,頁級鎖定和行級鎖定一樣,會發生死鎖。

mysql這三種鎖的特性可以大致歸納如下: 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低;
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高;    
頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。

innodb儲存引擎與myisam最大的不同就是:innodb支援事務;採用行級鎖
可以通過檢查Innodb_row_lock變數來分析系統上行鎖的爭奪情況:

如果Innodb_row_lock_time_avg和Innodb_row_lock_current_waits兩個值偏高,則表示鎖爭用嚴重可以通過查詢information_schema庫中相關的表(INNODB_LOCKS)來檢視鎖情況。

innodb行級鎖的模式和加鎖方法
innodb實現了兩種模型的行鎖: 1.共享鎖(S):允許一個事務去讀一行,阻止其它事務獲得相同資料集的排他鎖 2.排他鎖(X):允許獲得排他鎖的事務更新資料,阻止其它事務取得相同資料集的共享鎖和排他鎖
innodb同時為了支援表鎖和行鎖的共存,實現多粒度的鎖定機制,還有兩種意向鎖(intention locks): 1.意向共享鎖(IS):事務打算給資料行加行共享鎖,事務在給一個數據行加鎖前必須獲得該表的IS鎖 2.意向排他鎖(IX):事務打算給資料行加行排他鎖,事務在給一個數據行加鎖前必須獲得該表的IX鎖 四種鎖的相容情況如圖:
如果一個事務請求的鎖模式與當前的鎖相容,InnoDB就將請求的鎖授予該事務;反之,如果兩者不相容,該事務就要等待鎖釋放。
意向鎖是InnoDB自動加的,不需使用者干預。對於UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及資料集加排他鎖(X);對於普通SELECT語句,InnoDB不會加任何鎖;事務可以通過以下語句顯示給記錄集加共享鎖或排他鎖。
共享鎖(S):SELECT  ... LOCK IN SHARE MODE
排他鎖(X):SELECT ... FOR UPDATE
innodb行鎖的實現方式 innodb行鎖是通過給索引上的索引項加鎖來實現的,如果沒有索引,innodb將通過隱藏的聚簇索引來對記錄加鎖。innodb的行鎖分為三種:Record lock、Gap lock、Next-Key Locks Record lock
單條索引記錄上加鎖,record lock鎖住的永遠是索引,而非記錄本身,即使該表上沒有任何索引,那麼innodb會在後臺建立一個

隱藏的聚集主鍵索引,那麼鎖住的就是這個隱藏的聚集主鍵索引。所以說當一條sql沒有走任何索引時,那麼將會在每一條聚集索引後面加X鎖,這個類似於表鎖 Gap lock
在索引記錄之間的間隙中加鎖,或者是在某一條索引記錄之前或者之後加鎖,並不包括該索引記錄本身。

Next-Key Locks 在預設情況下,mysql的事務隔離級別是可重複讀,並且innodb_locks_unsafe_for_binlog引數為0,這時預設採用next-key locks,所謂Next-Key Locks,就是Record lock和gap lock的結合,即除了鎖住記錄本身,還要再鎖住索引之間的間隙。

(-∞, 1],  (1, 10], (10, 20], (20, +∞)

下列SQL語句自帶的行鎖級別為:
insert——記錄鎖、update——防插入鎖、delete——防插入鎖
此外,若查詢的列包含唯一索引或主鍵,則行鎖將被自動降級到記錄鎖
(1)在不通過索引條件查詢時,innodb會鎖定表中的所有記錄
(2)mysql的行鎖是針對索引加的鎖,所以雖然是訪問不同行的記錄,如果使用相同的索引鍵,是會出現鎖衝突的
(3)當表有多個索引的時候,不同的事務可以使用不同的索引鎖定不同的行,不論是使用主鍵索引,唯一索引或普通索引,innodb都會使用行鎖來對資料加鎖
(4)即使在條件中使用了索引欄位,但是否使用索引來檢索資料是由mysql通過判斷不同計劃的代價來決定的,如果mysql認為全表掃描效率更高,它就不會使用索引,這種情況下innodb會對所有記錄加鎖。



譯者介紹:家華,從事mysqlDBA的工作,記錄自己對mysql的一些總結