執行順序刪除和未送出讀
我們正在使用動態 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
通常是最容易過渡到的。有關行版本控制隔離級別的詳細資訊,請參閱此聯機叢書主題及其子樹。