Sql-Server

我可以在 DELETE 時避免使用 TABLOCKX 嗎?

  • December 6, 2019

目標

以零停機時間刪除三個表中的數十億條舊記錄(大約 600GB)。

方法和背景

我計劃一次刪除一批與 100 萬個 MyID 相關的記錄(即 MyID BETWEEN 1 AND 1000000)。在刪除執行時,其中兩個表會非常熱,但第三個表上的活動可以安全地掛起。在兩個熱表中,MyID 是集群鍵。在第三個冷表中,我在 MyID 上有一個非聚集索引。

除了 DELETE 操作之外,熱表中的其他活動將包括 INSERT,可能每秒幾個。MyID 是一個 IDENTITY,新插入的記錄不會在任何 DELETE 批次的範圍內。

如果它有助於了解潛在的性能,那麼在由 MyID 聚集的表上對這些行的樣本批次進行聚合的 SELECT 需要 < 1 秒,而在非聚集表上大約需要 2 秒。我沒有這個特定數據庫的產品副本可以播放,所以我不能說刪除需要多長時間,但是一旦我將它部署到 DEV 我會有一個更好的主意。

旁注:為了解決日誌大小,我將這些批次包裝在事務中,並將 TLog 備份頻率從 15 分鐘提高到 5 分鐘。我有 150GB 的可用日誌空間。

問題

我在 MS 文件中讀到:

預設情況下,DELETE 語句總是在它修改的表上獲取一個排他 (X) 鎖,並持有該鎖直到事務完成。

我對使用鎖定提示非常謹慎,但在這種情況下,我可以安全地使用一個來避免 TABLOCKX 嗎?除了鎖定提示之外還有其他方法可以避免 TABLOCKX 嗎?

刪除數十億條記錄舊記錄(約600GB)

在這種情況下,複製應該保留而不是刪除的行可能更方便。請注意,所有 600Gb 肯定會移動到您的日誌文件中。

預設情況下,DELETE 語句總是在它修改的表上獲取一個排他 (X) 鎖,並持有該鎖直到事務完成。

這是錯誤的。table lock除非指定了相應的提示,否則SQL Server 永遠不會啟動。

預設情況下,SQL Server 將獲取最細粒度的鎖,以獲得最大的並發性。在大多數情況下,這意味著 SQL Server 將獲取行(RID 或 KEY)鎖。SQL Server 可以對單個表中的數據獲取成百上千個單獨的鎖,而不會導致任何問題。但是,在某些情況下,如果 SQL Server 確定查詢將訪問聚集索引中的一系列行,則它可能會獲取頁鎖。畢竟,如果要訪問頁面上的每一行,管理單個頁面鎖比管理數十個或數百個行鎖更容易。在其他情況下,主要是當沒有可用的索引來幫助處理查詢時,SQL Server 可能會在處理查詢的開始時鎖定整個表。

PK在您對范圍進行過濾的情況下:MyID BETWEEN 1 AND 1000000它很可能會從page鎖開始。而這一切都取決於有多少記錄適合一個page。如果1000000使用粒度鎖定記錄page所需的時間少於鎖定,那麼5000使用page鎖就可以了,如果locks每個語句lock escalation會發生更多,並且您的表將被完全鎖定。

除了在超過實例範圍的門檻值時升級鎖之外**,當任何單個會話在單個語句中獲得超過 5,000 個鎖時,SQL Server 還將升級鎖。**在這種情況下,選擇哪個會話將升級其鎖沒有隨機性。它是獲取鎖的會話。

SQL Server 並發:K.Delaney 的鎖定、阻塞和行版本控制

所以只有通過測試和監控獲得的鎖,你才能找到最優的batch size並避免lock escalationbatch size如果您知道表中每頁的平均行數,則可以近似計算。PAGLOCK或者您可以通過使用甚至禁用表上的鎖升級來強制頁面鎖定:

ALTER TABLE MyTable SET ( LOCK_ESCALATION = DISABLE )

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