2009-09-30 129 views
0

我在SQL2005上遇到了一些TSQL代碼的奇怪問題。在同一記錄上同時更新

我們懷疑這件作品產生的問題是:

INSERT INTO SGVdProcessInfo 
    ([StartTs]) 
    VALUES 
    (GETDATE()) 

SELECT @IdProcessInfo = SCOPE_IDENTITY() 

UPDATE TOP(@quantity) 
    [SGVdTLogDetail] WITH (ROWLOCK) 
SET 
    [IdSGVdProcessInfo] = @IdProcessInfo 
WHERE 
    [IdSGVdProcessInfo] IS NULL 
    and IdTLogDetailStatus != 9 

@Quantity通常需要500

有上SGVdTLogDetail

一個非聚集索引超過IdSGVdProcessInfo和IdTLogDetailStatus

發生了什麼事是SGVdTLogDetail的一些記錄首先使用processinfo表的一個id更新,然後它們再次由另一個具有新的processinfo ID的進程更新。

如果ROWLOCK提示時提出這一問題,或許還有別的我不知道......

我的猜測是,當施加在第一選擇500行中的更新,另一個進程正在選擇下一個組,並記錄第一組尚未更新的記錄(由於行鎖)。這可能嗎?

任何幫助將不勝感激!

回答

1

是的,這聽起來不錯。您可以通過將整個操作放入可序列化的事務中來修復它(以損失的併發性爲代價)。這將保證所有行在事務生命週期都被鎖定,而不是僅在原子行級讀取和更新期間被鎖定。

0

我相信這是因爲SQL Server正在將行級鎖升級爲頁鎖。你會認爲你指定主鍵的UPDATE總是會導致一個行鎖,但是當SQL Server獲得一批這樣的批處理,並且其中一些碰巧在同一頁中時(取決於這種情況,這可能很有可能,例如更新文件夾中的所有文件,幾乎同時創建的文件),您將看到頁面鎖,並且會發生不好的事情。如果您沒有爲UPDATE或DELETE指定主鍵,那麼沒有理由認爲數據庫不會影響很多,所以它可能適合頁面鎖定,並且會發生不好的事情。

通過專門請求行級鎖,您可以避免這些問題,但是,在您的情況下,會有很多行受到影響,並且數據庫正在採取主動並升級爲頁鎖。

相關問題