Sql-Server

執行順序刪除和未送出讀

  • November 18, 2019

我們正在使用動態 SQL 執行以下查詢,當我們執行並發實例時,這在少數情況下會出錯。錯誤是:

由於數據移動,無法使用 NOLOCK 繼續掃描…

這個問題說當一個程序讀取被另一個程序刪除的數據時會拋出這個錯誤。我們的過程是刪除和讀取相同的行,但是根據以下查詢一個接一個(在SELECT之後DELETE):

DELETE FROM Table1
WHERE colum1 = somevalue1
AND column2 = somevalue2

SELECT COUNT(*) 
FROM Table1 WITH (NOLOCK)
WHERE colum1 = somevalue1
AND column2 = somevalue2

我試圖了解上述查詢的執行。由於SELECT未送出,它是否在送出之前開始執行DELETE?這是否意味著刪除NOLOCK提示將停止錯誤?

由於SELECT未送出,它是否在送出之前開始執行DELETE

不,T-SQL 語句在 SQL Server 中總是按順序執行。關鍵是SELECT可以讀取其他並發執行的事務所做的未送出的更改。

這是否意味著刪除NOLOCK應該停止錯誤?

是的,但這只是因為只有在事務隔離級別READ UNCOMMITTED. 移動到不同的隔離級別可防止發生該特定錯誤。

附加資訊

發生錯誤 601 的原因有多種,但都有一個共同的主題:SQL Server 引擎正在跟踪某個指針鍊或其他指針鏈,當它遇到預期存在的結構已被另一個移動或刪除的情況時並發執行過程。

與 SQL Server 版本相比,可能發生錯誤 601 的情況逐漸減少,SQL Server 2012 最不可能返回此錯誤,但仍有可能。

我自己的觀點是,所有錯誤 601 事件都是錯誤 - 對於“錯誤”的合適值。READ UNCOMMITTED這種行為當然是​​不可取的,並且遠遠超出了 SQL 標準對隔離級別下可能遇到的現象的描述。

雖然 SQL 標準確實沒有很好地定義不同隔離級別的詳細行為,它所說的導致人們普遍認為,唯一的後果READ UNCOMMITTED一個事務可能會看到已被另一個事務更改的數據。在其他事務送出之前的事務。因此,使用READ UNCOMMITTED隔離級別通常是合理的,因為幾乎所有事務都非常快速地送出(並且很少回滾),因此讀取“臟”數據只是時間差異。

不幸的是,READ UNCOMMITTED在 SQL Server 中的實現遠遠超出了簡單的髒讀。SQL Server 中的READ UNCOMMITTED事務可以返回重複數據、大型數據類型的部分讀取、完全跳過數據記錄,或者只是因為 601 錯誤而失敗。

甚至. _ _ 這導致一些人得出結論,唯一可接受的隔離級別是那些至少提供語句級別一致性的隔離級別,即隔離或。READ COMMITTED REPEATABLE READ``row-versioning READ COMMITTED``SNAPSHOT``SERIALIZABLE

其中,row-versioning READ COMMITTED通常是最容易過渡到的。有關行版本控制隔離級別的詳細資訊,請參閱此聯機叢書主題及其子樹。

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