下列資料表和索引是用來作為索引鍵範圍鎖定範例要遵循的基礎。
範圍掃描查詢
為了確保範圍掃描查詢是可序列化,相同的查詢每次在相同交易內執行時都必須傳回相同的結果。其他的交易絕不能把新的資料列插入範圍掃描查詢內;否則這些動作將會變成幽靈插入。例如,以下的查詢使用上述的資料表與索引:
SELECT name
FROM mytable
WHERE name BETWEEN 'A' AND 'C';
放置索引鍵範圍鎖定的索引項對應到名稱介於資料值 Adam 與 Dale 之間的資料列範圍,讓前次查詢中限定的新資料列無法新增或刪除。雖然此範圍內的第一個名稱是 Adam,但位於此索引項的 RangeS-S 模式的索引鍵範圍鎖定會確保以字母 A 開頭的新名稱無法新增至 Adam 前面,例如 Abigail。同樣的,位於 Dale 的索引項的 RangeS-S 索引鍵範圍鎖定,則確保以字母 C 開頭的新名稱皆無法新增至 Carlos 後面,例如 Clive。
附註: |
|---|
|
持有的 RangeS-S 鎖定的數量為 n+1,其中 n 為符合查詢的資料列數量。
|
單一擷取不存在的資料
如果交易內的查詢嘗試選取不存在的資料列,則在同一筆交易內稍後的某一點所提交的查詢必須傳回相同的結果。其他的任何交易皆不得插入這個不存在的資料列。例如,給定以下的查詢:
SELECT name
FROM mytable
WHERE name = 'Bill';
將索引鍵範圍鎖定放在與名稱範圍從 Ben 到 Bing 對應的索引項,因為要把名稱 Bill 插入這兩個相鄰的索引項之間。將 RangeS-S 模式的索引鍵範圍鎖定放在索引項 Bing 之上。這可預防其他交易將值 (例如 Bill) 插入到索引項 Ben 和 Bing 之間。
刪除動作
在交易內刪除某個值時,交易進行刪除動作期間不需鎖定該值所處之範圍。鎖定欲刪除的索引鍵值直到交易結束,即足以維持可序列化能力。例如,給定以下的 DELETE 陳述式:
DELETE mytable
WHERE name = 'Bob';
將獨占 (X) 鎖定放在與名稱 Bob 對應的索引項。其他交易可在被刪除的值 Bob 前後插入或刪除值。但是,嘗試讀取、插入或是刪除 Bob 這個值的任何交易,在進行刪除動作的交易尚未認可或回復之前都會被封鎖。
可以使用三種基本鎖定模式來執行範圍刪除:資料列、分頁或資料表鎖定。資料列、分頁或資料表的鎖定策略是由查詢最佳化工具來決定,或者亦可由使用者透過最佳化提示 (如 ROWLOCK、PAGLOCK 或 TABLOCK) 來指定。使用 PAGLOCK 或 TABLOCK 時,如果所有資料列都會從此分頁刪除,Database Engine 會立即重新配置索引頁。相反的,若是使用 ROWLOCK,所有已刪除的資料列則僅標示為已刪除;稍後再使用背景工作將這些資料列從索引頁中移除。
插入動作
在交易內插入某個值時,交易進行插入動作期間不需鎖定該值所處之範圍。鎖定欲插入的索引鍵值直到交易結束,即足以維持可序列化能力。例如,給定以下的 INSERT 陳述式:
INSERT mytable VALUES ('Dan');
將 RangeI-N 模式的索引鍵範圍鎖定放在與名稱 David 對應的索引項來測試範圍。如果授與鎖定,便插入 Dan 並將獨占 (X) 鎖定放在 Dan 這個值。RangeI-N 模式的索引鍵範圍鎖定只有在測試範圍時才需要,且在交易進行插入動作期間不需持有。其他的交易皆可在插入值 Dan 的前面或後面插入或刪除值。但是,嘗試讀取、插入或是刪除 Dan 這個值的任何交易在進行插入動作的交易尚未認可或回復之前都會被鎖定。