I am trying to find a solution that will resolve a recurring deadlock situation in SQL server. I have done some analysis on the deadlock graph generated by the profiler trace and have come up with this information:
The first process (spid 58) is running this query:
UPDATE cds.dbo.task_core
SET nstate = 1
WHERE nmboxid = 89 AND ndrawerid = 1
AND nobjectid IN (SELECT
nobjectid
FROM (SELECT
nobjectid, count(nobjectid) AS counting
FROM cds.dbo.task_core
GROUP BY nobjectid
) task_groups
WHERE task_groups.counting > 1
)
The second process (spid 86) is running this query:
INSERT INTO task_core (…) VALUES (…)
spid 58 is waiting for a Shared Page lock on CDS.dbo.task_core
(spid 86 holds a conflicting intent exclusive (IX) lock)
spid 86 is waiting for an Intent Exclusive (IX) page lock on CDS.dbo.task_core
(spid 58 holds a conflicting Update lock)
It’s good that you posted the statements and the resources. To fully understand the issue, the plans would be also of use. But I’m going to make an (educated) guess and diagnose the deadlock cause as a large scan occurring in the UPDATE’s subquery:
This query has to scan the entire task_core table. Always. You are hitting the deadlock at a page because the full table scan is optimized to use page locking, but you can just as well hit it a row level if you add the ROWLOCK hint.
To eliminate the deadlock, you must eliminate the conflict during the full table scan that occurs in the update. Rather than using dirty reads, you can try using row-level versioning, enable read committed snapshot isolation in the database, see Understanding Row Versioning-Based Isolation Levels.
But a much better solution would be not to scan in the first place. First, revisit the business logic requirement and your data model. Everytime you see an update that needs to look at an entire table to make a decision, that is a very very smelly code stink. If you truly find that the update cannot be rewritten in a more sensible way (I doubt), then you should consider using an indexed view. BIG_COUNT(*) expressions are allowed in indexed views and they would speed up the query significantly, in addition to eliminating the deadlock cause.