2015-01-16 67 views
0

我有一個存儲過程,它不會對數據庫的探測,以確定一些記錄應更新當併發檢查失敗

的很多每個記錄(訂單)具有TIMESTAMP稱爲[RowVersion]

我回滾事務存儲候選記錄ID和RowVersions在臨時表稱爲@Ids

DECLARE @Ids TABLE (id int, [RowVersion] Binary(8)) 

我獲得與以下

候選人的數
DECLARE @FoundCount int 
SELECT @FoundCount = COUNT(*) FROM @Ids 

由於記錄可當我從SELECT當我終於嘗試UPDATE,我需要一種方法來檢查併發性和ROLLBACK TRANSACTION如果檢查失敗

我有什麼樣的變化,到目前爲止

BEGIN TRANSACTION 

-- create new combinable order group 
INSERT INTO CombinableOrders DEFAULT VALUES 

-- update orders found into new group 
UPDATE Orders 
    SET Orders.CombinableOrder_Id = SCOPE_IDENTITY() 
    FROM Orders AS Orders 
    INNER JOIN @Ids AS Ids 
     ON Orders.Id = Ids.Id 
     AND Orders.[RowVersion] = Ids.[RowVersion] 

-- if the rows updated dosnt match the rows found, then there must be a concurrecy issue, roll back 
IF (@@ROWCOUNT != @FoundCount) 
BEGIN 
    ROLLBACK TRANSACTION 
    set @Updated = -1  
END 
ELSE 
    COMMIT 

從上面,我正在過濾UPDATE與存儲[RowVersion]這將跳過任何記錄已經被改變(希望)

但是我不太清楚,如果我正確地使用事務處理或樂觀併發關於TIMESTAMP我,或者有更好的方法來達到我的預期目標

回答

0

這很難理解你試圖實現什麼邏輯。

但是,如果您絕對必須在某個過程中執行多個非原子操作,並確保整個代碼塊在運行時不會再次執行(例如由其他用戶執行),請考慮使用sp_getapplock

鎖定應用程序資源。

你的程序可能類似於此:

CREATE PROCEDURE [dbo].[YourProcedure] 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    BEGIN TRANSACTION; 
    BEGIN TRY 

     DECLARE @VarLockResult int; 
     EXEC @VarLockResult = sp_getapplock 
      @Resource = 'UniqueStringFor_app_lock', 
      @LockMode = 'Exclusive', 
      @LockOwner = 'Transaction', 
      @LockTimeout = 60000, 
      @DbPrincipal = 'public'; 

     IF @VarLockResult >= 0 
     BEGIN 
      -- Acquired the lock 

      -- perform your complex processing 

      -- populate table with IDs 
      -- update other tables using IDs 
      -- ... 

     END; 

     COMMIT TRANSACTION; 
    END TRY 
    BEGIN CATCH 
     ROLLBACK TRANSACTION; 
    END CATCH; 

END 
+0

感謝我在SP –

+0

年底做一個更新之前你的答案但是實際上我試着去確定一些其他的查詢順序改變了我再次重讀您的問題。它在我看來你在做什麼是正確的。 MSDN ['rowversion'](https://msdn.microsoft.com/zh-cn/library/ms182776.aspx)文章有一個例子,他們在'UPDATE'語句中使用'OUTPUT'子句。他們記得在一個單獨的表變量中更新的行,然後用它來計算更新了多少行。你爲此使用'@@ ROWCOUNT'。我不知道哪種方法更好。如果您確實想要在處理過程中一起更新多個訂單,那麼您的解決方案應該可以正常工作。 –