Why do we need UPDATE Locks in SQL Server?

Today I want to talk about a specific question that I almost get every time when I teach about Locking & Blocking in SQL Server: Why does SQL Server need to have Update Locks? Before we go down to the details of why they are needed, I first want to give you a basic overview of when an Update (U) Lock is acquired, and how the lock itself behaves regarding its compatibility.

In general an Update Lock is used in SQL Server when performing an UPDATE statement. When you look at the underlying query plan, you can see that such a plan always consists of 3 parts:

  • Reading data
  • Calculating new values
  • Writing data

Update Query Plan

When SQL Server initially reads the data to be changed in the first part of the query plan, Update Locks are acquired on the individual records. And finally these Update Locks are converted to Exclusive (X) Locks when the data is changed in the third part of the query plan. The question that arrises with this approach is always the same: why does SQL Server acquire Update Locks instead of Shared (S) Locks in the first phase? When you normally read data through a SELECT statement, a Shared Lock is also good enough. Why is there now a different approach with UPDATE query plans? Let’s have a more detailed look at it.

Deadlock Avoidance

First of all UPDATE Locks are needed to avoid deadlock situations in UPDATE query plans. Let’s try to imagine what happens when multiple UPDATE query plans acquire Shared Locks in the first phase of the plan, and afterwards convert these Shared Locks to Exclusive Locks when the data is finally changed in the third phase of the query plan:

  • The 1st query can’t convert the Shared Lock to an Exclusive Lock, because the 2nd query has already acquired a Shared Lock.
  • The 2nd query can’t convert the Shared Lock to an Exclusive Lock, because the 1st query has already acquired a Shared Lock.

That approach would lead to a traditional deadlock situation in a relational database:
Update Deadlock
That’s one of the main reasons why implementers of relational database engines have introduced Update Locks to avoid that specific deadlock situation. An Update Lock is only compatible with a Shared Lock, but isn’t compatible with another Update or Exclusive Lock. Therefore a deadlock situation can be avoided, because 2 UPDATE query plans can’t run concurrently at the same time. The 2nd query will just wait until the Update Lock can be acquired in the 1st phase of the query plan. An unpublished study of System R also showed that this kind of deadlock was the most prominent one. System R was initially implemented without any Update Locks.

Improved Concurrency

Instead of acquiring an Update Lock during the 1st phase, it would be also a viable option to acquire an Exclusive Lock directly in that phase. This will also overcome the deadlock problem, because an Exclusive Lock is not compatible with another Exclusive Lock. But the problem with that approach is limited concurrency, because in the mean time no other SELECT query can read the data that is currently exclusively locked. Therefore there is also the need for the Update Lock, because this specific lock is compatible with the traditional Shared Lock. As a result this means that other SELECT queries can read data, as long as individual Update Locks are not yet converted to Exclusive Locks. As a side-effect this will improve the concurrency of our parallel running queries. 

In traditional relational literature an Update Lock is a so-called Asymmetric Lock. In the context of the Update Lock that means that the Update Lock is compatible with the Shared Lock, but not vice-versa: the Shared Lock is not compatible with the Update Lock. But SQL Server doesn’t implement the Update Lock as an asymmetric one. The Update Lock is a symmetric one, which means that Update and Shared Locks are compatible in both directions. This will also improve the overall concurrency of the system, because it doesn’t introduce blocking situations between both lock types.

Summary

In todays blog posting I gave you an overview of Update Locks in SQL Server, and why they are needed. As you have seen there is a really strong need for Update Locks in a relational database, because otherwise it would yield to deadlock situations and decreased concurrency. I hope that you now have a better understanding of Update Locks, and how they are used in SQL Server.

Thanks for reading!

-Klaus

12 thoughts on “Why do we need UPDATE Locks in SQL Server?”

  1. Thanks Klaus, you made it so clear and understandable, I can’t wait to read more of your articles and will definitely watch your training videos.

  2. Just did a quick test flipping between read_committed and snapshot and observed the following locking.

    Object – IX – (the table)
    Page – IX – In_Row_Data
    Key – X – I_Row_Data

    Shouldn’t the locking strategy change depending on the isolation level ?

    1. Hello Jude,

      Thanks for your comment.
      With the isolation level you only influence readers (SELECT statements) and their locks.
      You can’t influence writers (INSERT, UPDATE, DELETE statements). They always acquire locks as you have observed with your testing.

      Thanks

      -Klaus

  3. Excellent explanation! This was exactly the info I was looking for, and it was described very clearly.

  4. I love to work on Database.
    Reading database related articles almost after 2 years!
    Its so simple yet detailed info.
    Thanks

  5. Hi Klaus
    If I understand right, every update creates a exclusive lock on the releated data. This means if I launch a long during select that goes over all records and in this time a do a update this can be done because we cannot create a exclusive lock if there is a shared lock of the select. Is this right?
    Is there a way to avoid this behavior?
    Thanks for the great article

    1. Klaus Aschenbrenner

      Hello Christoph,

      When you run your SELECT statement in Read Committed, the Shared Lock is released after the row is processed. Therefore you should only have a short period of blocking.
      If you want to avoid the Shared Locks of SELECT statements, I highly recommend Read Committed Snapshot Isolation – Optimistic Concurrency.

      Thanks,

      -Klaus

  6. Hi, thanks a lot for your article. I’m a very beginner on this. Could you please put some statement examples of this? simple ones, for example is we do and update do we need to put the “with(rowlock)”?. Or maybe some link with more explanations.

    Thanks a lot for your time and the information shared.
    Leo

Leave a Reply to Sudhev Cancel Reply

Your email address will not be published. Required fields are marked *