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 指南。
我的应用程序中有这个奇怪的问题。它很少发生,一周一次或可能两次。所以基本上情况是这样的:
我的应用程序中有这个方法多次查询数据库,首先有 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 指南。