Reputation: 23
I have a SQL statement that does an update, and then if the @@ROWCOUNT
is 0, it will insert. this is basically a MERGE
in SQL 2008. We are running into situations where two threads are failing on the update simultaneously. It will attempt to insert the same key twice in a table. We are using the Default Transaction isolation level, Read Committed. Will changing the level to repeatable reads fix this or do I have to go all the way to Serializable to make this work? Here is some code:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRAN;
UPDATE TableA
SET Duration = @duration
WHERE keyA = @ID
AND keyB = @IDB;
IF @@rowcount = 0
BEGIN
INSERT INTO TableA (keyA,keyB,Duration)
VALUES (@ID,@IDB,@duration);
END
COMMIT TRAN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;";
Upvotes: 2
Views: 1587
Reputation: 453287
You would need to go all the way up to SERIALIZABLE
.
Under REPEATABLE READ
if the row does not exist then both UPDATE
statements can run concurrently without blocking each other and proceed to do the insert. Under SERIALIZABLE
the range where the row would have been is blocked.
But you should also consider leaving the isolation level at default read committed
and putting a unique constraint on keyA,keyB
so any attempts to insert a dupe fail with an error.
Upvotes: 4