InnoDB鎖的基本概念
文章總共分為五個部分:
- InnoDB的鎖機制淺析(一)—基本概念/兼容矩陣
- InnoDB的鎖機制淺析(二)—探索InnoDB中的鎖(Record鎖/Gap鎖/Next-key鎖/插入意向鎖)
- InnoDB的鎖機制淺析(三)—幻讀
- InnoDB的鎖機制淺析(四)—不同SQL的加鎖狀況
- InnoDB的鎖機制淺析(五)—死鎖場景(Insert死鎖)
大而全版(五合一):InnoDB的鎖機制淺析(All in One)
1. 前言
本章的兼容矩陣是后面死鎖解決的基礎。
數據事務設計遵循ACID的原則:
原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。一個支持事務(Transaction)的數據庫,必須要具有這四種特性,否則在事務過程(Transaction processing)當中無法保證數據的正確性。
MySQL數據庫提供了四種默認的隔離級別,讀未提交(read-uncommitted)、讀已提交(或不可重復讀)(read-committed)、可重復讀(repeatable-read)、串行化(serializable)。
MySQL的默認隔離級別是RR。
2. 鎖基本概念
2.1 共享鎖和排它鎖
InnoDB實現了兩種標准行級鎖,一種是共享鎖(shared locks,S鎖),另一種是獨占鎖,或者叫排它鎖(exclusive locks,X鎖)。
S鎖允許當前持有該鎖的事務讀取行。
X鎖允許當前持有該鎖的事務更新或刪除行。
S鎖
如果事務T1持有了行r上的S鎖
,則其他事務可以同時持有行r的S鎖
,但是不能對行r加X鎖
。
X鎖
如果事務T1持有了行r上的X鎖
,則其他任何事務不能持有行r的X鎖
,必須等待T1在行r上的X鎖
釋放。
如果事務T1在行r上保持S鎖
,則另一個事務T2對行r的鎖的請求按如下方式處理:
- T2可以同時持有S鎖
- T2如果想在行r上獲取
X鎖
,必須等待其他事務對該行添加的S鎖
或X鎖
的釋放。
2.2 意向鎖-Intention Locks
InnoDB支持多種粒度的鎖,允許行級鎖和表級鎖的共存。例如LOCK TABLES ... WRITE
等語句可以在指定的表上加上獨占鎖。
InnoBD使用意向鎖來實現多個粒度級別的鎖定。意向鎖是表級鎖,表示table中的row所需要的鎖(S鎖或X鎖)的類型。
意向鎖分為意向共享鎖(IS鎖)和意向排它鎖(IX鎖)。
IS鎖表示當前事務意圖在表中的行上設置共享鎖,下面語句執行時會首先獲取IS鎖,因為這個操作在獲取S鎖:
SELECT ... LOCK IN SHARE MODE
IX鎖表示當前事務意圖在表中的行上設置排它鎖。下面語句執行時會首先獲取IX鎖,因為這個操作在獲取X鎖:
SELECT ... FOR UPDATE
事務要獲取某個表上的S鎖和X鎖之前,必須先分別獲取對應的IS鎖和IX鎖。
2.3 鎖的兼容性
鎖的兼容矩陣如下:
--- | 排它鎖(X) | 意向排它鎖(IX) | 共享鎖(S) | 意向共享鎖(IS) |
---|---|---|---|---|
排它鎖(X) | N | N | N | N |
意向排它鎖(IX) | N | OK | N | OK |
共享鎖(S) | N | N | OK | OK |
意向共享鎖(IS) | N | OK | OK | OK |
按照上面的兼容性,如果不同事務之間的鎖兼容,則當前加鎖事務可以持有鎖,如果有沖突則會等待其他事務的鎖釋放。
如果一個事務請求鎖時,請求的鎖與已經持有的鎖沖突而無法獲取時,互相等待就可能會產生死鎖。
意向鎖不會阻止除了全表鎖定請求之外的任何鎖請求。
意向鎖的主要目的是顯示事務正在鎖定某行或者正意圖鎖定某行。