Home > OS >  Different lock behaviour when using `IN`
Different lock behaviour when using `IN`

Time:08-04

I am having difficulty understanding the lock behaviour difference in the following examples, which cause me to have to resolve a deadlock.

I use (updlock,holdlock) for the common scenario of "select first, update/delete later". It might be relevant that in this specific case what is going to happen "later" is delete.

First, let me set up a case where everything works fine. As a "control panel query", let's create a very simple table, add some rows, and also prepare a lock selection query based on ashman786's enter image description here

It just has a single "Clustered Index Delete" operator with an equality seek predicate on id to tell it the row to delete.

The locks taken out in this case are an IX lock on the table, an IX lock on the page containing the row, and finally an X lock on the key of the row to be deleted. No U locks are taken at all.

When using the temp table the execution plan looks as follows.

enter image description here

It reads each row from color in turn and acquires a U lock on it. If the semi join operator finds that there was a match for that row in the temp table the U lock is converted to an X lock and the row is deleted. Otherwise the U lock is released.

If the execution plan was driven by the temp table instead then it could avoid reading and locking unneeded rows in color.

One way of doing this would be to write the query as

DELETE color
FROM   color WITH (forceseek)
WHERE  id IN (SELECT #t.id
              FROM   #t) 

enter image description here

The execution plan now reads the one row in #t - checks whether it exists in color (taking a U lock on just that row) and then deletes it.

As there is no constraint on #t ensuring that id is unique it removes duplicates first rather than potentially attempting to delete the same row multiple times.

  • Related