MySQL 的鎖機制是實現并發控制的核心,不同層級的鎖適用于不同場景,以下是對其鎖類型的系統分類及詳細說明:
一、按鎖粒度劃分
1. 全局鎖(Global Lock)
-
用途:鎖定整個數據庫實例,用于全庫備份。
-
命令:
FLUSH TABLES WITH READ LOCK; -- 加全局讀鎖 UNLOCK TABLES; -- 釋放鎖
-
影響:阻塞所有寫操作及DDL操作,僅允許讀操作。
2. 表級鎖(Table-Level Lock)
-
表鎖(Table Lock):
-
MyISAM引擎使用,分為:
- 表共享讀鎖(S鎖):允許其他會話讀,阻塞寫。
- 表獨占寫鎖(X鎖):阻塞其他會話的讀寫。
-
命令:
LOCK TABLES table_name READ; -- 加讀鎖 LOCK TABLES table_name WRITE; -- 加寫鎖 UNLOCK TABLES; -- 釋放鎖
-
-
元數據鎖(Metadata Lock, MDL):
- 自動加鎖:訪問表時自動加MDL讀鎖,修改結構時加MDL寫鎖。
- 問題:長事務可能導致DDL阻塞(如ALTER TABLE等待)。
-
意向鎖(Intention Locks):
- 作用:快速判斷表內是否有行級鎖沖突,減少鎖檢查開銷。
- 類型:
- 意向共享鎖(IS):表明事務意圖對某些行加S鎖。
- 意向排他鎖(IX):表明事務意圖對某些行加X鎖。
3. 行級鎖(Row-Level Lock)
- InnoDB引擎支持,鎖定索引記錄,類型包括:
- 記錄鎖(Record Lock):鎖定索引中的某一行。
- 間隙鎖(Gap Lock):鎖定索引記錄之間的間隙,防止幻讀。
- 臨鍵鎖(Next-Key Lock):記錄鎖 + 間隙鎖,鎖定左開右閉區間。
- 插入意向鎖(Insert Intention Lock):插入前對間隙加鎖,允許不同插入位置的并發。
- 自增鎖(AUTO-INC Lock):
- 用途:確保自增列(AUTO_INCREMENT)值的唯一性。
- 優化:MySQL 8.0引入輕量級鎖(互斥量),減少性能影響。
二、按鎖模式劃分
1. 共享鎖(Shared Lock, S鎖)
-
行為:允許其他事務加S鎖,阻塞X鎖。
-
使用場景:
SELECT ... LOCK IN SHARE MODE; -- 顯式加S鎖
2. 排他鎖(Exclusive Lock, X鎖)
-
行為:阻塞其他事務的S鎖和X鎖。
-
使用場景:
SELECT ... FOR UPDATE; -- 顯式加X鎖
三、按鎖策略劃分
1. 悲觀鎖(Pessimistic Locking)
- 假設:認為并發沖突頻繁,提前加鎖。
- 實現:通過
SELECT ... FOR UPDATE
顯式加鎖。
2. 樂觀鎖(Optimistic Locking)
-
假設:認為沖突較少,通過版本號或時間戳控制。
-
實現:
UPDATE table SET column = new_value, version = version + 1 WHERE id = 1 AND version = old_version;
四、鎖的兼容性與沖突
已存在的鎖 | IS鎖(新請求) | IX鎖(新請求) | S鎖(新請求) | X鎖(新請求) |
---|---|---|---|---|
IS鎖 | ? | ? | ? | ? |
IX鎖 | ? | ? | ? | ? |
S鎖 | ? | ? | ? | ? |
X鎖 | ? | ? | ? | ? |
五、不同隔離級別的鎖策略
隔離級別 | 鎖機制 |
---|---|
READ UNCOMMITTED | 不加鎖(通過快照讀),可能臟讀。 |
READ COMMITTED | 行級鎖(記錄鎖),無間隙鎖,允許幻讀。 |
REPEATABLE READ | 臨鍵鎖(Next-Key Lock)防止幻讀,默認隔離級別。 |
SERIALIZABLE | 所有讀操作隱式加共享鎖,完全串行化。 |
六、鎖的監控與診斷
1. 查看鎖信息
SHOW ENGINE INNODB STATUS; -- 查看Inno引擎狀態(含鎖信息)
SELECT * FROM information_schema.INNODB_LOCKS; -- 當前持有的鎖
SELECT * FROM information_schema.INNODB_LOCK_WAITS; -- 鎖等待關系
2. 常見問題
- 死鎖:事務相互等待鎖釋放,InnoDB自動檢測并回滾代價較小的事務。
- 鎖等待超時:由參數
innodb_lock_wait_timeout
控制(默認50秒)。
七、示例場景
場景1:防止超賣(臨鍵鎖)
-- 事務1:扣減庫存
BEGIN;
SELECT stock FROM products WHERE id = 1 FOR UPDATE; -- 加X鎖
UPDATE products SET stock = stock - 1 WHERE id = 1;
COMMIT;
- 作用:臨鍵鎖防止其他事務插入新記錄,確保庫存準確。
場景2:批量插入(間隙鎖)
-- 事務1:查詢范圍數據
BEGIN;
SELECT * FROM orders WHERE amount > 100 FOR UPDATE; -- 對間隙加鎖
- 作用:阻止其他事務在
amount > 100
范圍內插入新數據。
總結
MySQL通過多粒度鎖(全局鎖、表鎖、行鎖)和多種鎖模式(S/X鎖、意向鎖)實現高效的并發控制。合理選擇事務隔離級別和鎖策略(如臨鍵鎖防幻讀、樂觀鎖降級沖突)是優化性能的關鍵。監控工具和診斷命令可幫助快速定位鎖爭用問題。