0

我正在维护一个存储过程,每当用户访问网页时都会执行该存储过程。

-- 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吗?我需要知道它何时无法同步。

如果存储过程未能完成,有没有办法释放表锁?

4

1 回答 1

2

表锁是事务范围的。如果您只有与存储过程关联的隐式事务,那么一旦您的存储过程结束,锁也会结束,而不管任何错误。

在处理这样的锁时,通常使用显式事务很有用,这样您可以更好地控制锁的生命周期,并在代码中使其更加显式(这样在事务嵌套时不会混淆)。

于 2016-08-31T08:06:01.333 回答