Sql-Server
數據鎖定問題
我正在學習鎖定基礎知識,但我對它的工作原理有些懷疑。我正在使用以下查詢來檢查事務鎖:
SELECT request_session_id AS spid , DB_NAME(resource_database_id) AS dbname , CASE WHEN resource_type = 'OBJECT' THEN OBJECT_NAME(resource_associated_entity_id) WHEN resource_associated_entity_id = 0 THEN 'n/a' ELSE OBJECT_NAME(p.object_id) END AS entity_name , index_id , resource_type AS resource , resource_description AS description , request_mode AS mode , request_status AS status FROM sys.dm_tran_locks t LEFT JOIN sys.partitions p ON p.partition_id = t.resource_associated_entity_id WHERE resource_database_id = DB_ID() AND resource_type <> 'DATABASE' ;
在這裡,我正在打開事務並執行一些基本的選擇查詢:
USE AdventureWorks ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ ; BEGIN TRAN SELECT * FROM Production.Product WHERE Name LIKE 'Racing Socks%' ;
如您所見,聚集和非聚集索引上存在鍵鎖
現在我正在嘗試創建另一個手工製作的桌子
CREATE TABLE [IsolationTest2Test] ( col1 INT PRIMARY KEY , col2 VARCHAR(20) ) ; GO INSERT INTO IsolationTest VALUES ( 10, 'The first row' ) ; INSERT INTO IsolationTest VALUES ( 20, 'The second row' ) ; INSERT INTO IsolationTest VALUES ( 30, 'The third row' ) ; INSERT INTO IsolationTest VALUES ( 40, 'The fourth row' ) ; INSERT INTO IsolationTest VALUES ( 50, 'The fifth row' ) ; GO
所以現在存在創建主鍵的聚集索引,並且我在 column2 上添加了非聚集索引
畢竟我正在執行以下查詢:
USE [IsolationDB] ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ ; BEGIN TRAN SELECT * FROM [dbo].[IsolationTest2Test] WHERE col2 = 'The third row' ;
然後我檢查鎖定並看到以下內容:
問題是為什麼在第二個查詢中聚集索引沒有鍵鎖?(選擇從
$$ IsolationTest2Test $$) 第一條語句的查詢計劃:
第二次查詢的查詢計劃:
現在我可以理解從表中選擇所有列的第一個查詢在非聚集索引鍵值上獲取 S 鎖,並且它在具有葉級數據的聚集索引鍵上獲取 S 鎖。
為什麼第二個查詢不使用聚集索引鍵 col 1 來執行鍵查找?為什麼它只使用非聚集索引查找?col1 的價值在哪裡?
問題是為什麼在第二個查詢中聚集索引上沒有鍵鎖?
因為該表中唯一的其他列是聚集索引鍵。並且非聚集索引始終包含聚集索引鍵列。
因此,您在 col2 上的非聚集索引是 SELECT * 查詢的覆蓋索引。