I have two statements (an update against every row in one table (call it table A) and a delete on another table that looks up rows in table A) that I know are causing occasional deadlocks. It seems that there is an X lock and a U lock on the same primary key index of table A.
I have been trying, and failing, to replicate the deadlock in SQL Server Management Studio. Should I be able to?
Separately, the delete statement is very inefficient and I think I can fix the issue by creating a covering index that means that the primary key index mentioned above is no longer included in the actual execution plan of the delete statement. Given that ultimately the same rows are required by both statements will this guarantee no deadlocks or simply reduce the chance of it happening by giving SQL Server a different path to the data?
I finally managed to get a deadlock graph as shown below:
If I am reading this correctly, the process node on the right has an exclusive lock on PK_LoanFacility and is requesting another one (maybe this is because there are two updates in the statement associated with this process node. The first sets a field to NULL for all rows and the second then updates a subset with values pulled from another database). The process node on the left has an update lock on PK_LoanFacility and is requesting a shared lock. The statement on the left is deleting a single row from a child table and is finding the parent id via a WHERE clause. i.e. DELETE FROM table where ForeignID = (SELECT ID FROM ParentTable WHERE x = y). I am unsure as to why this would require an update lock on PK_LoanFacility (the PK of the parent table). I am guessing that whenever you delete a row from a table, all the foreign keys are inspected and updates to the primary key indexes of all parent tables are made..?
As previously mentioned, I am fairly sure that I can eliminate the need for the requested shared lock by adding some proper indexes, but I am still interested to understand what is happening.