我维护的存储过程将在用户访问网页时执行。
-- Existing tables
CREATE TABLE SourceAccount
(
Id bigint NOT NULL,
Value varchar(50) NOT NULL,
UpdateTime datetime2 NULL
)
CREATE TABLE TargetAccount
(
Id bigint NOT NULL,
Value varchar(50) NOT NULL,
UpdateTime datetime2 NULL
)
CREATE TABLE UpdatedCustomers
(
CustomerID bigint NOT NULL,
SyncTime datetime2 NOT NULL
)
存储过程:
CREATE PROCEDURE TriggerAccountSync (
@CustId bigint,
@LastUpdate DATETIME2)
AS
BEGIN
--if customer is outdated
IF EXISTS(SELECT 1 FROM UpdatedCustomers
WHERE CustomerID = @CustId AND SyncTime < @LastUpdate)
BEGIN
BEGIN TRY
INSERT INTO TargetAccount(Id, Value)
SELECT Id, Value
FROM SourceAccount
LEFT OUTER JOIN TargetAccount WITH (UPDLOCK, HOLDLOCK) ON TargetAccount.Id = SourceAccount.Id
WHERE SourceAccount.UpdateTime IS NULL
DELETE FROM TargetAccount
FROM SourceAccount
INNER JOIN TargetAccount WITH (UPDLOCK) ON TargetAccount.Id = SourceAccount.Id
WHERE TargetAccount.UpdateTime < @TimeStamp
UPDATE UpdatedCustomers
SET SyncTime = @LastUpdate
WHERE CustomerID = @CustId
END TRY
BEGIN CATCH
--there are multiple simultaneous calls, it can fail with deadlock
--don't raise error
END CATCH
END
END
我可以使用TRY CATCH THROW END CATCH
抛出异常并仍然避免TargetAccount
表上的死锁吗?我需要知道它何时无法同步。
如果存储过程无法完成,是否有办法释放表锁?
答案 0 :(得分:2)
表锁是事务范围的。如果只有与存储过程关联的隐式事务,则只要存储过程结束,锁定也会一直存在,无论是否有任何错误。
在处理这样的锁时,使用显式事务通常很有用,这样您就可以更好地控制锁的生命周期,并使其在代码中更加明确(这样在事务处理时就不会产生混淆)嵌套的)。