意向鎖(Intention Lock)
文章目錄
- 意向鎖(Intention Lock)
- 簡介
- 類型
- 原理
- 意向鎖加鎖流程
- 鎖兼容矩陣
- 使用場景
- 示例
- 總結
- 擴展:意向鎖和共享鎖排他鎖的加鎖流程
- 假設的場景和前提
- 已加鎖的情況
- 新的加鎖請求
- 加鎖流程
- 鎖的兼容性矩陣
- 示例代碼
- 總結
文章目錄
- 意向鎖(Intention Lock)
- 簡介
- 類型
- 原理
- 意向鎖加鎖流程
- 鎖兼容矩陣
- 使用場景
- 示例
- 總結
- 擴展:意向鎖和共享鎖排他鎖的加鎖流程
- 假設的場景和前提
- 已加鎖的情況
- 新的加鎖請求
- 加鎖流程
- 鎖的兼容性矩陣
- 示例代碼
- 總結
簡介
MySQL 中的意向鎖(Intention Lock)是一種表級鎖,用于幫助協調不同粒度的鎖(行級鎖和表級鎖)之間的沖突,優化并發事務的鎖管理。意向鎖并不會實際阻止行的讀寫操作,而是用來表明事務接下來要在某些行上加鎖,從而提高鎖沖突檢測的效率。
類型
MySQL 中主要有兩種類型的意向鎖:
- 意向共享鎖(Intention Shared Lock, IS):事務計劃在某些行上加共享鎖。
- 意向排他鎖(Intention Exclusive Lock, IX):事務計劃在某些行上加排他鎖。
原理
當一個事務請求獲取一個行級鎖或表級鎖時,MySQL會自動獲取相應的表的意向鎖。 這樣,其他事務請求獲取表鎖時,就可以先基于這個意向鎖來發現是否有人加過鎖,并根據該鎖的類型(意向共享鎖/意向排他鎖)來判斷自己是否可以獲取鎖。通過這種方式,當一個事務請求表級鎖時,InnoDB 可以快速確定是否有任何行級鎖沖突,而無需檢查表中每一行的鎖狀態。
注意:
- 意向鎖并不是直接鎖定資源,而是為了通知其他事務,以防止它們在資源上設置不兼容的鎖。
- 意向鎖并不是直接由用戶請求的,而是由 MySQL 管理的。
意向鎖加鎖流程
- 事務請求意向鎖:事務發出加意向鎖的請求(IS或IX)。
- 檢查兼容性:MySQL 檢查意向鎖是否與當前表上的其他意向鎖或表級鎖兼容。如果兼容,則加鎖成功。
- 后續加鎖操作:事務在行級別上加共享鎖或排他鎖時,只需檢查意向鎖而無需檢查整個表。
- 釋放鎖:事務提交或回滾后,釋放意向鎖。
鎖兼容矩陣
IS | IX | S | X | |
---|---|---|---|---|
IS | Yes | Yes | Yes | No |
IX | Yes | Yes | No | No |
S | Yes | No | Yes | No |
X | No | No | No | No |
- IS 和 IS 是兼容的,可以同時存在。
- IS 和 IX 是兼容的,可以同時存在。
- IX 和 IX 是兼容的,可以同時存在。
- S 和 IS 是兼容的,可以同時存在。
- S 和 IX 以及 X 鎖都是不兼容的。
使用場景
意向鎖在以下場景中非常有用:
- 高并發讀寫場景:在高并發讀寫操作中,意向鎖減少了鎖沖突檢測的開銷,提高了系統的并發性能。
- 行級鎖與表級鎖混合使用:當事務需要在行級別加鎖但可能會有其他事務請求表級鎖時,意向鎖有助于快速檢測沖突。
示例
假設有一個表 orders
,包含以下數據:
CREATE TABLE orders (id INT PRIMARY KEY,product_name VARCHAR(50),quantity INT
);
-
事務1:
START TRANSACTION; -- 請求在 orders 表上加意向排他鎖 SELECT * FROM orders WHERE id = 1 FOR UPDATE;
-
事務2:
START TRANSACTION; -- 請求在 orders 表上加意向共享鎖 SELECT * FROM orders WHERE id = 2 LOCK IN SHARE MODE;
-
事務3:
START TRANSACTION; -- 嘗試加表級共享鎖,會等待事務1和事務2釋放意向鎖 LOCK TABLES orders READ;
在以上示例中:
- 事務1在
orders
表上加了意向排他鎖(IX)和行級排他鎖(X)。 - 事務2在
orders
表上加了意向共享鎖(IS)和行級共享鎖(S)。 - 事務3嘗試加表級共享鎖(S),由于表上已有意向排他鎖(IX),因此會等待事務1釋放鎖。
總結
**意向鎖在 MySQL 中的作用是優化鎖管理,減少鎖沖突檢測的開銷,提升系統的并發性能。**它們在高并發讀寫場景和行級鎖與表級鎖混合使用場景中特別有用,通過表明事務的鎖意圖,使得鎖沖突檢測更加高效。
個人理解:
- 意向鎖本質還是共享鎖和排它鎖
- 根據 SQL 要添加共享鎖還是排它鎖,MySQL 自動添加意向共享鎖和意向排它鎖
- 意向鎖是表級鎖,且是 MySQL的自動添加的,人為不可控。
擴展:意向鎖和共享鎖排他鎖的加鎖流程
在 MySQL 中,如果一個事務已經對 table
表的 id=1
記錄添加了行級排他鎖(A),而此時另一個事務要對同一個表的 id=5
記錄添加行級排他鎖(B),加鎖流程將涉及意向鎖和排他鎖的處理。以下是詳細的加鎖流程:
假設的場景和前提
假設表結構如下:
CREATE TABLE table (id INT PRIMARY KEY,value VARCHAR(50)
);
已加鎖的情況
- 事務 A 已經對
id=1
的記錄添加了行級排他鎖(X 鎖)。
新的加鎖請求
- 事務 B 嘗試對
id=5
的記錄添加行級排他鎖(X 鎖)。
加鎖流程
- 事務 B 請求意向排他鎖(IX 鎖):
- 首先,事務 B 將在表
table
上嘗試加意向排他鎖(IX 鎖),以表明接下來會在某些行上加排他鎖。
- 首先,事務 B 將在表
- 檢查意向鎖的兼容性:
- 意向排他鎖(IX 鎖)與其他意向排他鎖(IX 鎖)和意向共享鎖(IS 鎖)都是兼容的,因此可以成功加鎖。
- 意向排他鎖(IX 鎖)與表級共享鎖(S 鎖)和表級排他鎖(X 鎖)不兼容,但此處沒有表級鎖沖突。
- 請求行級排他鎖(X 鎖):
- 事務 B 發出對
id=5
記錄加排他鎖(X 鎖)的請求。 - MySQL 檢查行級鎖的兼容性。由于
id=5
的記錄當前沒有被其他事務加鎖,排他鎖(X 鎖)可以成功加鎖。(如果此時事務 B 對id=1
添加行級鎖,那么事務 B 會被阻塞,直到事務 A 釋放了行級鎖)
- 事務 B 發出對
- 加鎖成功:
- 事務 B 成功對
id=5
的記錄加上排他鎖(X 鎖)。
- 事務 B 成功對
鎖的兼容性矩陣
為了更好地理解意向鎖和行級鎖的兼容性,以下是鎖的兼容性矩陣:
鎖類型 | IS | IX | S | X |
---|---|---|---|---|
IS | Yes | Yes | Yes | No |
IX | Yes | Yes | No | No |
S | Yes | No | Yes | No |
X | No | No | No | No |
示例代碼
以下是一個具體示例代碼來說明上述流程:
-
事務 A:
START TRANSACTION; -- 對 id=1 的記錄加排他鎖 SELECT * FROM table WHERE id = 1 FOR UPDATE; -- 行級排他鎖 X
-
事務 B:
START TRANSACTION; -- 對 id=5 的記錄加排他鎖 SELECT * FROM table WHERE id = 5 FOR UPDATE; -- 行級排他鎖 X
在這個示例中:
- 事務 A 對
id=1
的記錄加了排他鎖(X 鎖)。 - 事務 B 對
id=5
的記錄加了排他鎖(X 鎖)。
總結
- 意向排他鎖(IX 鎖):
- 事務 B 需要在表
table
上加意向排他鎖(IX 鎖)。由于 IX 鎖之間是兼容的,并且沒有表級別的鎖沖突,IX 鎖加鎖成功。
- 事務 B 需要在表
- 行級排他鎖(X 鎖):
- 事務 B 對
id=5
的記錄加行級排他鎖(X 鎖),由于id=5
沒有被其他事務鎖定,所以排他鎖加鎖成功。
- 事務 B 對
這整個過程確保了即使在高并發環境下,事務之間能夠協調操作,避免數據沖突和不一致。通過意向鎖和行級鎖的配合,MySQL 能夠有效地管理并發事務對數據庫的訪問和操作。