SQL Server Lock 入門:S/X 與 Intent



比喻
先把「資料庫」換成你熟悉的場景「圖書館」,後面就很好理解了。
把一張資料表想成一排書櫃,資料列像一本本書:
- 讀取(SELECT):像在書櫃前「翻閱內容」
- 修改(UPDATE/DELETE):像拿筆「在書上改字」
- 新增(INSERT):像把「新書放上架」
為了避免你正在讀的內容被別人改掉(或你正在改的內容被別人讀到一半),SQL Server 會用各種 Lock 來維持一致性。
S / X
先記住這兩個:S = 讀、X = 寫。其他鎖大多是為了讓「讀寫協調」更順、更不容易互卡。
S Lock(Shared)
當你在 讀資料 時,SQL Server 可能會在讀到的資料上加 S Lock。
- 你拿到 S Lock 時:別人也可以拿 S Lock(一起讀)
- 但別人不能拿 X Lock:因為 X Lock 代表要改,會影響你正在看的內容
你可以把 S Lock 想成「閱讀席位」:同一本書,大家可以一起看,但不能有人同時拿筆改內容。
X Lock(Exclusive)
當你要 改資料(UPDATE/DELETE) 時,SQL Server 需要確保同一筆資料不會被其他人同時讀或改,所以會使用 X Lock(或先用其他鎖再升級成 X Lock)。
- 你拿到 X Lock 時:別人不能拿 S 也不能拿 X(不能讀、不能改)
你可以把 X Lock 想成「施工封鎖」:正在改裝的書櫃區域,其他人先不要進來。
Intent(IS/IX/IU)
理解 Intent 之前,先抓住一個重點:SQL Server 的鎖不只鎖「書本(列/頁)」,也會在「書櫃入口(表/索引)」做管理。
到這裡你可能會想:如果我只是改其中幾本書,為什麼要理整排書櫃?
這就是 Intent Lock(意圖鎖) 的用途:它像是貼在「書櫃入口」的告示牌,告訴大家:
「我等一下會在這個書櫃裡面的某幾本書上鎖,你們先別做會衝突的事。」
Intent Lock 通常會出現在較高層級(例如資料表或索引層級),而真正的 S/X 鎖會在較低層級(例如資料列、資料頁)上。
你可以把它想成:上層先貼告示牌,下層才真的鎖到那幾本書。
IS(Intent Shared)
常見情境:查詢讀取某些列時,可能在表/索引上有 IS,同時在列/頁上拿 S。
IX(Intent Exclusive)
常見情境:更新或刪除某些列時,可能在表/索引上有 IX,同時在列/頁上拿 X(或準備升級成 X)。
IU(Intent Update)
這個比較常出現在「先找出要改哪幾筆,再改」的過程中(例如某些 UPDATE 的執行路徑),它的概念是:
- 先用較溫和的方式保留改寫的權利
- 避免太多人同時走到最後一步才搶 X Lock
U Lock
Intent 解决的是「我等一下要在裡面動手」;而 U Lock 則常用在「我正在挑目標、準備動手」這一步。
U Lock(更新鎖) 可以把它想成「我正在挑這本書要不要改,先讓我卡位」。
典型情境是:系統需要先讀到某列(像讀),但下一步可能會把它改掉(像寫)。
- 若一開始就用 S Lock 讀,兩個交易都可以拿到 S,接著都想升級成 X,可能互卡造成 死結(deadlock)
- 用 U Lock 的做法是:同一筆資料通常只允許一個人拿 U,等確定要改時再轉成 X,降低互卡機率
你不需要記住所有相容性矩陣,只要記住一句話:
- U Lock 是「準備要改」的鎖,常用來降低死結機率
Schema(Sch-S/Sch-M)
前面講的是「內容」的鎖,接著補一個很多人第一次遇到會困惑的:表結構也會被鎖。
除了資料內容,還有「表結構」也需要保護:
- Sch-S(Schema Stability):像「我正在看這個書櫃的架構,請不要拆櫃」
- 常見:一般查詢在編譯/執行時會短暫需要
- Sch-M(Schema Modification):像「我要拆書櫃、換層板」
- 常見:
ALTER TABLE、建立/重建某些索引等需要變更結構的操作
- 常見:
直覺上:
- Sch-M 會擋住很多一般操作(因為拆櫃時大家都不能用)
鎖層級 / 升級
到這裡你已經知道有哪些鎖,最後再補「鎖在哪裡」與「為什麼有時候會突然卡很大」。
SQL Server 的鎖可能套用在不同層級(由細到粗):
- KEY / RID(列):鎖住單筆資料(最精準)
- PAGE(頁):鎖住一頁資料(多筆列)
- OBJECT(表):鎖住整張表(影響最大)
當一次要鎖的列很多時,SQL Server 可能會做 Lock Escalation(鎖升級),把一堆細鎖換成較粗的鎖(例如從很多列鎖升級成表鎖),用意通常是:
- 減少鎖的管理成本(鎖太多本身也有負擔)
但代價是:
- 衝突範圍變大(原本只影響幾筆,可能變成整張表被卡住)
快速對照
如果你只想先有一張小抄,可以看這張表就夠用。
| 鎖 | 用途(用一句話記) | 常見時機 |
|---|---|---|
| S | 讀:大家可一起看 | SELECT(視隔離等級而定) |
| X | 寫:我在改,其他人先不要碰 | UPDATE / DELETE / 受影響的 INSERT |
| IS | 告示:我會在裡面讀 | 讀到列/頁前,在表/索引層出現 |
| IX | 告示:我會在裡面改 | 改到列/頁前,在表/索引層出現 |
| IU | 告示:我可能要先讀再改 | 某些更新路徑中出現 |
| U | 準備改:先卡位,降低死結 | 找到目標列、準備升級 X 之前 |
| Sch-S | 我在用結構,別拆 | 多數查詢編譯/執行期間 |
| Sch-M | 我要改結構,大家先停 | ALTER TABLE 等 DDL |
記憶法
- S 是「讀」;X 是「寫」;Intent 是「我等一下要在裡面讀/寫」的告示牌。
- U 是「準備要改」的鎖,常用來降低死結;Sch-M 是「拆櫃級」操作,會擋住很多人。