Skip to content
Advertisement

SQL Multiple queries at the same time creating deadlock (UPDLOCK)

So I have a problem with my database giving me a deadlock.

System.Data.SqlClient.SqlException : Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

I have a project that starts to run and then splits into x amounts of instances that run parallel (usually between 4 and 8). Each of these instances run the setup queries which a small part of looks like this:

This code however fails giving me errors about trying to insert duplicate keys – I have investigated this and believe it to be that since these do not lock the database in anyway while executing the code that one actually adds in the record while the other already has checked it doesn’t exist and then also tries to add it. So I rewrote these queries using UPDLOCK to sort out that problem. The new queries look like this:

This however made them still sometimes still fail on having tried to insert duplicate keys while mostly failing on this:

System.Data.SqlClient.SqlException : Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim

So I rewrote them once more (this I believe isn’t how they are supposed to look but this was me experimenting around). Notice the UPDLOCK on the main statement:

This worked just fine but was locking the database for too long making usually one of the multiple instances fail on a SQL timeout saying the database didn’t respond while the others passed. (no more duplicate key issues).

I would also like to add if I run these statements singly or only a single instance of the C# code I can run them as often as I want and they will always create the row if it doesn’t exist otherwise do nothing as expected. They only start erroring when they are run basically at the same time by my C# code.

My guess is that I am using the UPDLOCK slightly wrong but I have tried everything in my knowledge. Any help would be appreciated.

Advertisement

Answer

Your code doesn’t really make sense as it stands, and I wonder if that may be exacerbating the locking issue.

Each of your statements goes

which is nonsensical. We don’t care in the select part as to what exists already, only in the not exists part. So it should just be

Also, as mentioned by others, you need to make it SERIALIZABLE (alternative syntax is HOLDLOCK). @DavidBrowne is somewhat unclear about this. The point is that it both takes out a range lock to prevent inserts, and that it holds that lock until the end of the transaction. It could use a table lock to satisfy that, it just needs to hold it until the end.

So what we need is as follows:


If you are still getting deadlocking after doing this, I suggest you share your deadlock graph, along with the full table and index definitions.

There are many other issues that can cause deadlocks, and a definitive answer can only be given after seeing the graph

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement