我在我的应用程序中遇到了一个奇怪的问题。它很少发生,可能每周一次或两次。基本上情况是这样的:
我在我的应用程序中有一个方法,它会多次查询数据库,首先有4个选择,其中一个使用关键字UPDLOCK
,然后跟随另一个表(不是应用UPDLOCK
的表)的插入和之前应用UPDLOCK
的表的更新。
所有这些查询都在一个事务中完成(位于.NET的一侧),最后进行COMMIT
操作。
现在,问题在于transaction.Commit()
抛出异常,消息为:
超时已过期。在操作完成之前超时时间已过或服务器未响应。
(我猜测是因为SqlConnection
超时了)。
所以我将整个过程包装在一个try-catch
块中,如果出现异常,则尝试回滚事务,因此当发生这种情况时,代码执行转到catch
块,并调用transaction.RollBack()
,它也会抛出异常,消息为:
此SqlTransaction已完成。它不再可用。
(我猜测当COMMIT
超时时,事务实际上已经COMMIT
了),因此在这种情况下,应用程序的某些部分会出现问题。一些本来不存在的问题(因为ROLLBACK
)实际上存在,并导致一些意外问题,这些问题随后需要手动修复。
除了增加SqlConnection
的超时时间之外,我找不到任何可能指向问题所在的东西。如果有人以前遇到过这个问题,请分享一下经验,提前感谢。 (DB服务器的CPU利用率从未超过45-50%,在大多数情况下它处于3-15%的空闲状态)
这是第一个Sql 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