將死鎖優先級設置為盡可能低的值,但我的腳本仍然不是死鎖情況下的受害者
我對生產有以下兩個疑問:
查詢 #1:根據“日期”列從核心表“Table1”中刪除舊曆史數據的腳本
有約 20 個表通過外鍵通過級聯規則指向“Table1”,因此當您從“Table1”中刪除時,數據也會從約 20 個其他表中刪除
腳本一次刪除 50 行數據,批處理間隔為 1 秒
當批處理只有 50 行時,腳本不會導致排他鎖升級為表級鎖;它只放置行/頁級別 (X) 鎖
查詢 #2:從“Table1”、“Table2”、“Table3”和其他一些表中提取數據的生產應用程序
這是一個重讀查詢,它在表上放置共享鎖。它不做任何插入/更新/刪除
問題:
有時,當
Query # 2
(Prod 應用程序)讀取數據時會發生死鎖,而我同時Query # 1
在 SSMS 中執行(腳本刪除舊數據)。Query # 2
始終是受害者,據我了解,這是因為它沒有對事務日誌進行任何更改,而Query # 1
確實為了解決這個問題,我添加
set deadlock_priority -10
了Query # 1
,希望它會使Query # 1
任何可能的死鎖成為受害者首先它似乎有效,
Query # 1
在死鎖情況下成為受害者,在刪除一些批次時拋出錯誤 1205。但是-最近我發現有時
Query # 2
仍然會成為受害者問題:
這怎麼可能
Query # 2
有時甚至在我已經成為受害者set deadlock_priority -10
之後Query # 1
?有沒有辦法解決它並確保
Query # 1
在 100% 的情況下成為受害者?更新:在下面添加圖表
您可以嘗試通過更改事務隔離級別來解決問題。專門開啟 Snapshot 隔離,設置 Read Committed Snapshot,讓讀寫不會互相干擾。您也可以只更新生產查詢以使用快照隔離而不更新預設數據庫隔離級別。
不過要小心並徹底測試它,因為它會在寫入行快照時增加 tempdb 上的流量。設置讀取送出快照也是整個數據庫的預設行為更改,需要回歸測試以驗證沒有意外的副作用。
Microsoft 此處提供了有關此選項的更好解釋:https ://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server