如何正确处理存储过程中的死锁?

时间:2019-11-27 17:19:54

标签: c# sql sql-server performance-testing deadlock

我正在使用SQL Server Express 2014和Visual Studio 2017。

我有两个存储过程:首先,检查表A中的特定记录是否存在(如果不存在,则创建一个);第二,更新该特定记录的值。

问题是,当使用Jmeter且有多个用户正在处理此过程时,会出现死锁。如何处理死锁以防止数据库丢失数据,因为死锁XACT_STATE()等于-1之后,所以我无法将事务从CATCH块回滚到savepoint,也无法回滚所有事务,因为它将回滚第一个过程的效果。

我还检查了SQL Server Profiler,如果SQL Server尝试回滚到命名的savepoint,它将冻结事务,并且Visual Studio向我显示错误

  

System.InvalidOperationException:'此SqlTransaction已完成;它不再可用。

我的代码:

USE TESTDB
GO

ALTER PROCEDURE UPDATEVALUES
@ID int
@PARAMS nvarchar(128)

AS
BEGIN
    SET NOCOUNT ON;

    SELECT @InnerTranName = '_' + @PARAMS;
    SET @Success = 0;
    SET @RetryCount = 0;

    BEGIN TRANSACTION @InnerTranName;
    WHILE @RetryCount < 5 AND @Success = 0
    BEGIN
        BEGIN TRY
            IF @RetryCount = 0
                BEGIN
                    SAVE TRANSACTION @InnerTranName;
                END

            -- UPDATE PROCEDURE

            IF @@TRANCOUNT = 2
                SET @Success = 1
        END TRY
        BEGIN CATCH
            DECLARE @error int,
                    @message varchar(4000),
                    @xstate int;

            SELECT
                @error = ERROR_NUMBER(),
                @message = ERROR_MESSAGE(),
                @xstate = XACT_STATE();

            RAISERROR ('CounterValue_Update: %d: %s', 16, 1, @error, @message)

            IF @error = 1205
                BEGIN
                    SET @RetryCount = @RetryCount + 1
                    ROLLBACK TRANSACTION @InnerTranName
                END
        END CATCH
    END
    IF @Success = 0
        ROLLBACK;
    ELSE
        COMMIT;
END

0 个答案:

没有答案