Reputation: 6272
I'm maintaining a stored procedure which will be executed whenever a user visits a web page.
-- 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
)
The stored procedure:
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
Can I throw exception using TRY CATCH THROW END CATCH
and still avoid deadlocks on TargetAccount
table ? I need to know when it fails to sync.
Is there a way to release table lock if the stored procedure failed to complete ?
Upvotes: 0
Views: 1091
Reputation: 63722
Table locks are transaction-scoped. If you only have the implicit transaction associated with the stored procedure, as soon as your stored procedure ends, so will the locks, regardless of any errors.
When dealing with locks like this, it is generally useful to use explicit transactions, so that you have more control over the lifetime of the locks, and make it more explicit in the code (so that there is no confusion when transactions are nested).
Upvotes: 2