并发检查失败时的回滚事务

时间:2015-01-16 00:12:27

标签: sql-server

我有一个存储过程,会对数据库进行大量探测,以确定是否应更新某些记录

每条记录(订单)都有TIMESTAMP名为[RowVersion]

我将候选记录ID和RowVersions存储在名为@Ids

的临时表中
DECLARE @Ids TABLE (id int, [RowVersion] Binary(8))

我通过以下

获得候选人的数量
DECLARE @FoundCount int
SELECT @FoundCount = COUNT(*) FROM @Ids

由于记录可能会从i 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的事务或乐观并发,或者是否有更好的方法来实现我的预期目标

2 个答案:

答案 0 :(得分:0)

当您选择数据时,请在显式事务内部尝试使用HOLDLOCK和UPDLOCK。它会破坏其他交易的并发性而不是你的交易。

http://msdn.microsoft.com/en-us/library/ms187373.aspx

答案 1 :(得分:0)

很难理解你想要实现的逻辑。

但是,如果您绝对必须在过程中执行多个非原子操作并确保整个代码块在运行时不会再次执行(例如,由其他用户执行),请考虑使用{{3} }。

  

锁定应用程序资源。

您的程序可能与此类似:

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