InnoDB引擎——6.鎖篇

InnoDB引擎——6.鎖篇

行級鎖神話——行級鎖總會增加開銷

實際上,只有當實現本身會增加開銷時,行級鎖纔會增加開銷,InnoDB存儲引擎不需要鎖升級,因爲一個鎖和多個鎖的開銷是相同的。如何理解?

MyISAM是表鎖,數據庫中lock和latch都是鎖,
latch更輕量,latch又分爲mutex(互斥量)和rwlock(讀寫鎖),注意!沒有通常死鎖檢查機制,lock對象是事物,用來鎖定數據庫對象(表,頁,行),lock在提交和回滾後釋放,是有死鎖機智的。另外latch存在於每個數據結構的對象中,而lock存在於Lock Manager的哈希表中。

兩種標準的行級鎖:(1)共享鎖(S Lock),讀鎖 (2)排他鎖(X Lock),寫鎖

意向鎖(IX)就是將鎖定對象分爲多個層次,意味着事物更希望在更細粒度上進行加鎖。意向鎖爲表級別的鎖:
意向共享鎖(IS Lock):事物想獲得一張表某幾行的共享鎖
意向排他鎖(IX lock):事物想獲得一張表某幾行的排他鎖

意向鎖不會阻塞除全表掃描以外的任何請求,因爲InnoDB支持的是行級別的鎖。

監控當前事物分析鎖問題的三張表:INNODB_TRX,INNODB_LOCKS,INNODB_LOCK_WAITS
(待更新)

一致性非鎖定讀:是指利用多版本控制來讀取當前執行時間數據庫中行的數據(並不是在每個事物隔離級別都採用非鎖定的一致性讀),在事物隔離級別爲READ COMMITTED(1)和REPEATABLE READ(2)下使用非鎖定一致性讀,但是在(1)下,讀到的是最新的一份快照數據,在(2)下,讀到的是事物開始的版本。
對於READ COMMITTED的事物隔離級別而言,違反了隔離性

一致性鎖定讀:即使對SELECT操作要求更高,有兩種方式(1)SELECT …FOR UPDATE 表示對讀取的行加一個X鎖(2)SELECT…LOCK IN SHARE MODE 補充:這兩個必須在一個事物中(因爲上述的都是在隔離級別裏探討的),務必加上BEGIN,START TRANSACTION或者SET AUTOCOMMIT=0

自增長與鎖:自增長AUTO-INC Locking是一種特殊的表鎖機制,爲了提高性能,在完成自增長的SQL語句後就釋放了,新的機制利用innodb_autoinc_lock_mode來控制自增長模式,默認值爲1.(有0,1,2:最開始的0是爲了兼容的),在InnoDB存儲引擎中,自增長的列必須是索引,同時必須是索引的第一列,不然會報錯。

外鍵和鎖:外鍵主要用於引用完整性的約束檢查

鎖的算法:
行鎖的3種算法:
(1)Record Lock:單個行記錄上的鎖
(2)Gap Lock:間隙鎖,鎖定一個範圍,不包括記錄本身(但是會產生Phantom Problem(幻像問題) ),關閉gap lock 就是隔離級別設爲READ COMMITTED
(3)Next-Key Lock :Gap Lock+Record Lock鎖定一個範圍,並且鎖定記錄本身。

當查詢的索引有唯一性時,InnoDB存儲引擎會對Next-key Lock進行優化,將其降級爲Record Lock,只鎖住索引本身,而不是範圍,來提高併發性。如果不唯一(即輔助索引),還會對下一個鍵值加上gap lock

對於唯一鍵值的鎖定,Next-Key Lock降級爲Record Lock僅存在於查詢所有的唯一索隱列。若唯一索引由多個列組成,而查詢僅是查找多個唯一索引列中的其中一個,那麼查詢其實是range類型的查詢,而不是point類型查詢,故InnoDB存儲引擎依然使用Next-Key Lock進行鎖定

解決Phantom Problem(幻像問題) :在同一事物下,連續執行兩次同樣的SQL語句可能導致不同的結果,第二次的SQL語句可能會返回之前不存在的行。

鎖問題:
(1)髒讀:在不同事物下,當前事物可以讀到另外事物未提交的數據,簡單來說就是可以讀到髒數據(不常發生),在一些特殊情景需要READ COMMITTED,比如replication環境中的slave節點,並且在該slave上的查詢並不需要特別精確的返回值。

(2)不可重複讀:一個事物內多次讀取同一個數據集合。在這個事物還沒有結束時,另外一個事物也訪問了該同一數據集合,並做了一些DML操作,所以兩次讀到數據不一樣。髒讀是讀到未提交的數據,而不可重複讀讀到的是已經提交的數據。一般來說,不可重複讀的問題是可以接受的。InnoDB存儲引擎的默認事物隔離級別是READ REPEATABLE,採用Next-Key Lock(左開右閉)算法,避免了不可重複讀的現象。

(3)丟失更新:是另一個鎖導致的問題,簡單來說就是一個事物的更新操作會被另一個事物的更新操作所覆蓋,從而導致數據的不一致。要避免丟失更新發生,需要讓事物在這種情況下的操作變成串行化,不是並行操作。

阻塞:阻塞並不是一件壞事,其實是爲了確保事物可以併發且可以正常運行。

死鎖:
(1)死鎖最簡單的方式解決方法是超時,一個事物回滾,一個事物繼續運行,根據FIFO順序選擇回滾對象,但超時的事物所佔權重比較大,就不太合適。

**死鎖檢測機制:**wati-for graph(等待圖)——要求數據庫保存以下兩種信息,(1)鎖的信息鏈表(2)事物的等待鏈表

鎖升級:Microsoft SQL Server數據庫中會有鎖升級,粒度降低,認爲鎖是一種稀有資源,但是InnoDB認爲不存在鎖升級問題,站在事物的角度認爲一個書屋鎖住了頁中的一個記錄還是多個,其開銷都是一致的。(採用位圖的方式)

小結:需要學會通過一些命令和數據字典來查看事物鎖住了哪些資源,不然永遠不知道發生了什麼,可能只是認爲MySQL數據庫有時會阻塞而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章