Sql 服务器事务提交超时

Sql Server Transaction Commit times out

我的应用程序中有这个奇怪的问题。它很少发生,一周一次或可能两次。所以基本上情况是这样的:

我的应用程序中有这个方法多次查询数据库,首先有 4 个选择,其中一个使用关键字 UPDLOCK 然后插入到另一个 table(不是一个UPDLOCK 应用到的)和 table 上的更新,之前是 UPDLOCK-ed。

所有这些查询都在一个事务中完成(在 .NET 的一侧),最后它得到 COMMIT-ed。

现在,问题是 transaction.Commit() 抛出异常消息

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding

(我猜 SqlConnection 超时了)。

所以我将整个过程包裹在一个 try-catch 块中,如果发生异常,我会尝试回滚事务,所以当发生这种情况时,代码执行转到 catch 块和 transaction.RollBack() 被调用,它还会抛出消息

的异常

This SqlTransaction has completed. it is no longer usable

(正如我猜测的那样,当 COMMIT 超时时,交易实际上得到了 COMMIT-ed),所以在这之后应用程序的某些部分就会混乱。被认为不存在的东西(因为ROLLBACK)实际上存在并导致一些意想不到的问题,然后手动修复(此时)。

我找不到任何可以指出问题所在的信息,而不是增加 SqlConnection 的超时时间。如果有人以前处理过这个问题,你能分享一下经验吗,在此先感谢。 (数据库服务器 CPU 利用率永远不会超过 45-50%,大多数情况下它闲置在 3-15%)

这里是第一个SqlSelect --首先Select

    SELECT TOP 1
            t.Id ,
            t.OId ,
            t.Amount ,
    t.DUserId,
            t.StartDate ,
            t.ExtDesc,
    t.StatusId
    FROM    dbo.[Transaction] t
            JOIN dbo.Wallet cw ON t.CId = cw.Id
            JOIN dbo.Wallet dw ON t.DId = dw.Id
    WHERE   ExtKey = @ExtKey 
            AND ( cw.vId = @vId 
                  OR dw.VId = @vId 
                )

--Second Selct which executes twice with differenc params


    SELECT  u.Id ,
            UserName ,
            PinCode ,
            CurrencyId ,
            StatusId ,
            PersonalNumber ,
            gu.DefaultVendorServiceId ,
            CountryId,
    u.FirstName,
    u.LastName
    FROM    dbo.[User] u
            LEFT JOIN dbo.GamblerUser gu ON gu.UserId = u.Id
    WHERE   u.Id = @UserId


--Last select with (updlock)


SELECT w.Id, AccountNo, FundTypeId, VendorServiceId, Balance, UserId, vs.IsLocalAccount

FROM Wallet w (UPDLOCK)
JOIN VendorService vs on w.VId = vs.Id
WHERE 
    w.UserId  = @UserId
AND w.FundTypeId = @FundTypeId 
AND w.VendorServiceId  = @VendorServiceId


-- Insert


    INSERT  INTO [dbo].[Transaction]
            ( StartDate ,
              OTypeId ,
              StatusId ,
              Amount ,
              ExtDesc,
              DUserId 
            )
    VALUES                  ( @StartDate ,
              @OTypeId ,
              @StatusId ,
              @Amount ,
              @ExtDesc,
              @DUserId 
            )

    SET @Id = ( SELECT  @@IDENTITY
              )


-- Update on updlocked table    


UPDATE dbo.Wallet SET

    Balance = ISNULL(@Balance, Balance)

WHERE Id = @Id

(我假设这不是 Hekaton,它在提交时做了不同的事情。)

提交通常需要很短的时间。必须对日志进行一次物理写入,并且在 Mirroring/AG 的情况下必须进行网络往返。其中一件事可能会阻碍此处的提交。

我个人遇到过重载镜像连接的问题。

提交超时不能单独更改(我认为这是一个缺陷)。正在使用连接超时。

调查我上面提到的根本原因。作为解决方法,增加提交超时。

在提交失败的情况下,您不能假设事务是否实际提交。 (这就是二将问题。它通常无法解决。)您必须设计某种检查以查看数据库是否包含预期的写入。这在 Azure 上更为常见。查看 Azure 指南。