This question is related with Occasionally Getting SqlException: Timeout expired. Actually, I am using IF EXISTS... UPDATE .. ELSE .. INSERT
heavily in my app.
The problem with IF EXISTS ... UPDATE ...
(and IF NOT EXISTS ... INSERT ...
) is that under concurrency multiple threads (transactions) will execute the IF EXISTS
part and all reach the same conclusion (eg. it does not exists) and try to act accordingly. Result is that all threads attempt to INSERT resulting in a key violation. Depending on the code this can result in constraint violation errors, deadlocks, timeouts or worse (lost updates).
You need to ensure that the check IF EXISTS
and the action are atomic. On pre SQL Server 2008 the solution involved using a transaction and lock hints and was very very error prone (easy to get wrong). Post SQL Server 2008 you can use MERGE
, which will ensure proper atomicity as is a single statement and the engine understand what you're trying to do.