BEGIN tran
DECLARE @name NVARCHAR(50)
SELECT @name=name FROM dbo.investor WITH(UPDLOCK) WHERE id=1206
IF @name='sxf359'
BEGIN
UPDATE dbo.investor SET name='sxfabc' WHERE id=1206
END
PRINT @name
WAITFOR DELAY '0:00:20'
COMMIT TRAN
此事務在執行過程中,如果使用
SELECT * FROM dbo.investor WITH(NOLOCK) WHERE id=1206
讀取該條數據,感覺上name字段應該讀取到的是sxf359。我一直是這樣認為的,因為事務還沒提交,還沒更新為sxfabc。但事實是讀取到的是sxfabc。把事務未最終提交的數據讀取出來了。一些“臟數據”或未被提交的數據潛在的可能被讀取,這就是臟讀。我對臟讀的定義有了更清晰的認識。
若用SELECT * FROM dbo.investor WHERE id=1206 讀取數據,或者SELECT * FROM dbo.investor WITH(UPDLOCK) WHERE id=1206 讀取數據,這個時候都會處於等待狀態,直到事務執行完畢,才會執行這個兩個讀取操作
但,如果是下面的事務情況:
1
2
3
4
5
6
7
BEGIN tran
DECLARE @name NVARCHAR(50)
SELECT @name=name FROM dbo.investor WITH(UPDLOCK) WHERE id=1206
PRINT @name
WAITFOR DELAY '0:00:20'
COMMIT TRAN
下面的這兩條語句同時都能夠執行:
SELECT * FROM dbo.investor WITH(NOLOCK) WHERE id=1206
SELECT * FROM dbo.investor WHERE id=1206
但是,下面這條語句不能執行:
SELECT * FROM dbo.investor WITH(UPDLOCK) WHERE id=1206
這條語句只有在事務執行完畢才會執行。
updlock意思就是更新鎖
防范臟讀,保險的方法是使用 with(updlock) ,但通常像這種正常讀取SELECT * FROM dbo.investor WHERE id=1206 就可以了。因為若使用with(updlock)情形下,下步必然是要更新數據
————————————————