Sql-Server

如果並發讀取/更新不影響相同的行,2 個表可以相互鎖定嗎?頁面鎖定關閉

  • July 26, 2017

如果頁面鎖關閉並且行不相關,那麼 2 個表是否會導致死鎖。例如

查詢 1 執行幾秒鐘

Select * from Orders where CustomerID = 1 and DateOrdered between @D1 and @D2

查詢 2 開始執行並在查詢 1 完成之前結束,但使用不同的 customerID

Update Orders set Quantity = Quantity + 10 where OrderID = 20 and CustomerID = 2

(這些只是證明一點的例子)

現在有一個 PK_Orders,它是 OrderID 上的一個聚集索引。還有一個單獨的索引 (ix_Order_Customer),它是一個非聚集索引,包含 CustomerID 作為要索引的欄位之一。該索引啟用了頁面鎖。

我不明白的是 SQL(使用 traceID 1222)如何在 SQL Server 日誌記錄中向我展示 PK_Orders 在執行的查詢甚至不影響已更新的相同 OrderID 時導致死鎖。

從日誌文件查看器中提取:

keylock hobtid=720229632 dbid=5 objectname=myDB.dbo.Orders
indexname=PK_Orders id=lock1b0b23c0 mode=X associatedObjectId=720229632

pagelock fileid=1 pageid=195848 dbid=5 objectname=myDB.dbo.Orders id=lock24442a40
mode=S associatedObjectId=720229274

有人可以幫忙解釋一下這是怎麼可能的嗎,如果這裡有相交的行,死鎖是否應該啟動?我複制了 2 個查詢並同時執行它們,但我無法重新創建錯誤,並且在 SQL Server Management Studio 中不會發生此錯誤 - 更新通過。

SQL Event Log Viewer 中的錯誤特別指出 PK_Orders 是這裡的原因。

通常在以下情況下會發生死鎖:

  1. 查詢 1 嘗試進行更新 - 但在更新之前需要進行選擇。所以首先它應用 READ 鎖(S - 共享鎖)。假設它設法鎖定了幾個頁面。
  2. 查詢 2 嘗試在其中一些頁面上進行選擇並設置 READ 鎖(S - 共享鎖)。
  3. 查詢 1 現在嘗試進行更新 - 因此它嘗試將 READ 鎖更改為 WRITE 鎖(即 S(共享)更改為 X(排他)鎖)。它設法在某些頁面上執行此操作,但由於某些頁面已被查詢 2 鎖定,因此無法在所有頁面上執行此操作。
  4. 查詢 2 依次嘗試獲取更多頁面 - 但它們現在有一個 X 鎖(WRITE 鎖)。

最後,兩個查詢都在等待對方,因此 SQL Server 決定用 DEADLOCK 異常終止一個查詢。

順便說一句 - 問題不是這裡的主鍵索引。

引用自:https://dba.stackexchange.com/questions/33753