SQL Server Lock 入門:S/X 與 Intent

Limit
Limit
Gentle and strong, Limit shines.
Cover Image for 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 是「拆櫃級」操作,會擋住很多人。