Sql-Server

由於分配順序掃描或由於無鎖和頁面拆分,失去行和重複行是症狀嗎?

  • February 21, 2022

NOLOCK 導致分配順序掃描而不是索引順序掃描。

NOLOCK 不會阻止寫入,因為它不會在表上使用共享鎖。

在 NOLOCK 的掃描過程中,由於沒有共享鎖,並且在掃描目前到達的點之前發生了寫入(插入/更新),因此這種情況會導致失去記錄。

同樣,在寫入(插入/更新)期間,當讀取一行後發生頁面拆分,並且該行現在是下一頁的一部分(由於頁面拆分),那麼這種情況將導致重複記錄。

我一直在閱讀似乎表明缺少/重複行問題是由於分配順序掃描的文章。

  1. 如我上面的範例所示,失去/重複記錄問題是由於沒有鎖定和頁面拆分造成的。正確的?是否也可能是由於分配順序掃描引起的?
  2. 如果分配有序掃描確實會導致失去行/重複,那麼我想問一下 - 假設引擎使用了索引順序掃描(我知道引擎不會這樣做,但只是為了這個問題而假設)而不是分配順序掃描,那麼它將如何解決失去/重複行的問題?

NOLOCK 導致分配順序掃描而不是索引順序掃描。

這是不正確的。使用未送出讀意味著儲存引擎可以在分配順序掃描和索引順序掃描之間進行選擇。它可以在執行時選擇任一策略而無需重新編譯執行計劃。

NOLOCK 不會阻止寫入,因為它不會在表上使用共享鎖。

在讀取未送出時讀取數據意味著共享鎖不在行、頁或表粒度上。由於沒有使用這些鎖,它們不會阻塞並發事務更改數據所需的獨占鎖。

在 NOLOCK 的掃描過程中,由於沒有共享鎖,並且在掃描目前到達的點之前發生了寫入(插入/更新),因此這種情況會導致失去記錄。

**這不是特定於未送出的讀取。**使用鎖定讀取已送出或可重複讀取讀取數據也可能會失去已送出的數據。

鎖定已送出的讀取通常會在讀取下一行之前釋放一行上的共享鎖:

讀已送出

可重複讀取將共享鎖維護到事務結束,但只有到目前為止實際遇到的數據才會被鎖定。如果更改索引鍵值,則目前掃描位置前面的行可以移動到掃描點後面:

可重複閱讀

克雷格·弗里德曼 (Craig Freedman) 文章中的先前圖片內聯連結

上述問題特定於索引順序掃描


同樣,在寫入(插入/更新)期間,當讀取一行後發生頁面拆分,並且該行現在是下一頁的一部分(由於頁面拆分),那麼這種情況將導致重複記錄。

索引順序掃描不關心頁面拆分。頁面在拆分之前和之後都以邏輯鍵順序連結。索引順序掃描將遇到拆分頁面上的行,以及由拆分產生的新頁面。如果您按關鍵順序關注頁面,則無法避免這種情況。

  1. 如我上面的範例所示,失去/重複記錄問題是由於沒有鎖定和頁面拆分造成的。正確的?是否也可能是由於分配順序掃描引起的?

不,這些是由於在進行索引順序掃描時行按索引順序移動而多次失去或遇到行的範例。

由於頁面拆分而多次失去或遇到行是僅在使用分配順序掃描時才會發生的問題。按分配順序掃描時,頁面拆分會將一些行移動到新頁面。分配順序掃描可能會或可能不會遇到該新頁面。如果已經遇到拆分的頁面,我們會再次看到一些行。如果尚未遇到拆分頁面,如果新頁面落後於分配順序掃描位置,我們可能會錯過一些行。

如果引擎有可接受的保證,即在掃描期間數據不會更改,則分配順序掃描只有在不使用未送出讀取的情況下才有可能。因此,由於對更改數據的分配順序掃描而失去已送出的行或多次遇到它們,因此特定於使用未送出的讀取隔離。

  1. 如果分配有序掃描確實會導致失去行/重複,那麼我想問一下 - 假設引擎使用了索引順序掃描(我知道引擎不會這樣做,但只是為了這個問題而假設)而不是分配順序掃描,那麼它將如何解決失去/重複行的問題?

如前所述,使用索引順序掃描可避免由於頁面拆分而導致的失去/重複行。同樣如上所述,由於索引鍵更改,仍然可能發生失去或重複的行。

再次注意:使用 read uncommitted 並不能保證您獲得分配順序掃描。

進一步閱讀:

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