Reputation: 2846
A part of my application updates a table as per business logic after opening a connection on transaction isolation level REPEATABLE READ. In a rare scenario, If this operation coincides with another part of the application which opens a different connection and tries to reset the same record to its default value. I get following error
Msg 1205, Level 13, State 45, Line 7
Transaction (Process ID 60) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
I think i am able to re-produce the issue using following example.
1.
create table Accounts
(
id int identity(1,1),
Name varchar(50),
Amount decimal
)
2.
insert into Accounts (Name,Amount) values ('ABC',5000)
insert into Accounts (Name,Amount) values ('WXY',4000)
insert into Accounts (Name,Amount) values ('XYZ',4500)
3.
Start a long transaction with isolation level as REPEATABLE READ
Set transaction isolation level REPEATABLE READ
begin tran
declare @var int
select @var=amount
from Accounts
where id=1
waitfor delay '0:0:10'
if @var > 4000
update accounts
set amount = amount -100;
Commit
4.
While Step.3 above is still being executed. Start another transaction on a different connection
Begin tran
update accounts
set Amount = 5000
where id = 1
commit tran
Transaction started in Step 3 would eventually complete but the one started in Step 4 would fail with following error message.
Msg 1205, Level 13, State 45, Line 7
Transaction (Process ID 60) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
What are my options to be able to eventually run transaction in step 4. The idea is to be able to reset the record to a default value and anything being performed on other transactions should be overridden in this case. I don't see any issue if both the transactions are not concurrent.
Upvotes: 5
Views: 3598
Reputation: 171178
The idea is to be able to reset the record to a default value
In what order do you want the updates applied? Do you want the "reset" to always come through? Then you need to perform the reset strictly after the update in step 3 has completed. Also, the reset update should use a higher lock mode to avoid the deadlock:
update accounts WITH (XLOCK)
set Amount = 5000
where id = 1
That way the reset will wait for the other transaction to finish first because the other tran has an S-lock.
Alternatively, habe step 3 acquire an U-lock or X-lock.
Upvotes: 4
Reputation: 922
You can set the deadlock priority of transaction in setp 4 to be higher For more details see http://technet.microsoft.com/en-us/library/ms186736.aspx
Upvotes: 0