I have an application connected to a SQL Server 2014 database that combines several rows into one. There are no other connections to this database while the application is running.
First, select a chunk of rows within a specific time span. This query uses a non-clustered seek (TIME column) merged with a clustered lookup.
select ...
from FOO
where TIME >= @from and TIME < @to and ...
Then, we process these rows in c# and write changes as a single update and multiple deletes, this happens many times per chunk. These also use non-clustered index seeks.
begin tran
update FOO set ...
where NON_CLUSTERED_ID = @id
delete FOO where NON_CLUSTERED_ID in (@id1, @id2, @id3, ...)
commit
I am getting deadlocks when running this with multiple parallel chunks. I tried using ROWLOCK
for the update
and delete
but that caused even more deadlocks than before for some reason, even though there are no overlaps between chunks.
Then I tried TABLOCKX, HOLDLOCK
on the update
, but that means I can't perform my select
in parallel so I'm losing the advantages of parallelism.
Any idea how I can avoid deadlocks but still process multiple parallel chunks?
Would it be safe to use NOLOCK
on my select
in this case, given there is no row overlap between chunks? Then TABLOCKX, HOLDLOCK
would only block the update
and delete
, correct?
Or should I just accept that deadlocks will happen and retry the query in my application?
UPDATE (additional information): All deadlocks so far have happened in the update
and delete
phase, none in the select
. I'll try to get some deadlock logs up if I can't get this solved today (the correct trace flags weren't enabled before).
UPDATE: These are the two arrangements of deadlocks that occur with ROWLOCK
, they both refer only to the delete
statement and the non-clustered index it uses. I'm not sure if these are the same as the deadlocks that occur without any table hints as I wasn't able to reproduce any of those.
Ask if there's anything else needed from the .xdl, I'm a bit weary of attaching the whole thing.
UPDLOCK
during your select? That way the lock is already there when you're updating/deleting which should keep you out of deadlocking. If possible share some of the deadlock logging details with us. – Mamboupdate
anddelete
phase, so changing theselect
lock is unlikely to affect this case. I don't have any deadlock logs unfortunately, I'll see if I can get the deadlock trace flags enabled for the next attempt. @Nick.McDermaid Can't use snapshot isolation unfortunately. – Thrasherupdate
/delete
is always the vicim (so far). – Thrasher