1. 程式人生 > >MySQL Innodb 中的鎖

MySQL Innodb 中的鎖

upd 種類型 共享鎖 隔離 AD 釋放 ble 完整性 ext

MySQL Innodb 中的鎖

鎖是用來解決並發沖突的必要手段,MySQL 中的並發主要是指多個線程同時對同一個數據庫進行操作,其中不同線程可能代表不同的事務,本質上也就是對共享資源的不同事務的同時訪問。

Innodb 支持行級鎖和意向鎖。行級鎖就是對行記錄進行加鎖,行級鎖也分為兩種類型,一種是共享鎖( S 鎖),一種是排他鎖( X 鎖)。意向鎖為表級別的鎖,也就是將鎖定的對象分為多個層次,意向鎖意味著事務希望在更細粒度上進行加鎖,一般來說,意向鎖是從上往下(數據庫->表->頁->記錄)進行加鎖,其中任何一個部分導致等待,那麽該操作都會需要等待粗粒度的鎖的完成。

讀的鎖定操作

一致性非鎖定讀

MySQL 的默認事務隔離級別是 Repeatable Read,在事務隔離為 Repeatable Read 和 Read Committed 級別下,默認的讀取方式即為一致性非鎖定讀。一致性非鎖定讀即為在訪問行記錄時,不需要等待該行上的 X 鎖釋放。Innodb 的一致性非鎖定讀是以多版本控制實現的,在多版本控制中,會保存修改之前數據的快照,作為恢復使用。

需要註意的是:在 Repeatable Read 和 Read Committed 的兩種級別下的一致性非鎖定讀也是不同的,Repeatable Read 隔離級別下,總是讀取事務開始時的行數據,而 Read Committed 模式下總是讀取該行版本上的最新快照。

一致性鎖定讀

默認情況下,在 Repeatable Read 和 Read Committed 隔離界別下,SELECT 語句對一行的讀取是使用一致性非鎖定讀的,用戶可以通過指定 SELECT 語句使用一致性鎖定讀,例如:

  1. SELECT ... FOR UPDATE
  2. SELECT ... LOCK IN SHARE MODE

這兩種方法可以分別給行記錄加上一個 X 鎖和 S 鎖。

外鍵和鎖

對於一個外鍵的更新和插入,首先需要查詢父表中的記錄,即主動對父表加一個 S 鎖,這裏必須使用一致性鎖定讀。如果不這麽做,當另外事務 A 對父表的行記錄進行了刪除操作,而事務 B 打算在子表中添加一行與父表具有外鍵關系的行,事務 B 會讀到存在該外鍵,從而添加(從快照中讀取),但是實際上當事務 A 提交後,父表中將不存在該主鍵,從而導致父子表中完整性被破壞。

行鎖的三種方法

Record Lock:單個行記錄上的鎖。

Gap Lock:間隙鎖,不包含記錄本身。

Next-Key Lock:鎖定一個範圍同時也鎖定記錄本身。

在查詢的列是唯一索引時,Next-Key Lock 會降級為 Record Lock,以提高並發效率。

在 Repeatable Read 和 Read Committed 情況下使用行鎖的方法不同,在 Repeatable Read 下,使用 Next-Key Lock,而在 Read Committed 情況下,使用 Record Lock。

MySQL Innodb 中的鎖