Library tutorials & articles

SQL Server Locks

Lock Contention Described

Databases that don't do just row-level locking often use a technique called lock escalation to achieve better performance. Unless its clear from the outset that a whole table will be modified, these databases start off using row locks, and they make plans to trade these locks in for rough-grained locks later if too many rows are modified.

Unfortunately, lock escalation introduces and amplifies a whole new problem: deadlock. If two users try to modify semantically-unrelated but physically-near data in two separate tables in reverse order, both users will start off with row locks, then try to upgrade them to page locks, and the situation will be that each user wants something the other user has, so they're stuck. This is deadlock.

For example:

  • UserA modifies some rows in TableA, causing a page lock affecting not just the rows UserA modified, but many others
  • UserB modifies some rows in TableB, causing a page lock affecting not just the rows UserA modified, but many others
  • UserA wants to modify some rows that UserB has locked (but not modified) in TableB
  • UserB wants to modify - or maybe just access - some rows that UserA has locked (but not modified) in TableA.

Something's gotta give. To deal with this problem, the database occasionally looks for deadlocks, and kills off one of the transactions so the other can finish. It usually kills the one that's made the least modifications so that it minimizes the cost of rolling back changes. Databases that use only row-level locking almost never have this problem because two users rarely want to modify the exact same row, and even more rarely do they attain locks in the perfectly poor order needed to cause deadlock.

Also, databases like this use lock timeouts to prevent users from waiting too long for a lock. Query timeouts also factor in here. You can write code to retry queries that timeout, but this only automates database congestion. Any timeout that is often reached will only serve to worsen the user experience. Things simply should not take that long.

In practice and under high load, SQL Server's locking system - which is based on lock escalation - does not perform well. Why? Lock contention. Lock contention is the problems of deadlock and waiting for locks. In a system in which many users are modifying the database at once, and many more users are trying to access the database concurrently, the locks are flying, users spend a lot of time waiting to attain locks, deadlocks are frequent, and users are far from happy.

Granted, if you've only got a few occasional users you won't have much trouble with SQL Server's out-of-the-box behavior. You'll be hard pressed to see these problems with simple in-the-office tests or deployments involving just a few users. But throw a couple hundred concurrent users at your database and a constant stream of INSERTS and UPDATES with quite a few DELETEs sprinkled in, and you'll start reading Oracle literature and eyeing your war chest. However, I've got a solution for you that will only cost you a code review, a few minor tweaks, and a system test. You do have a system test procedure in place, right?

Comments

  1. 03 Jul 2009 at 19:44

    To get more information about Isolation levels in SQL Server including Locks and its impact on database in detail with examples, refer the below link: http://www.sqllion.com/2009/07/transaction-isolation-levels-in-sql-server/

  2. 15 Feb 2007 at 15:59

    I've implemented the [WITH (NOLOCK)] hint and it's been a reasonable success.  The only additional note of caution I would add is that we have one table that is occasionally updated (batch inserts).

    The problem is that the data is inserted and then the index is updated.  If the index is read after the data has been updated but before the index is updated then this can cause the following error:

    Number = -2147217900, Description = Could not continue scan with NOLOCK due to data movement., Source = Microsoft OLE DB Provider for SQL Server, SQLState = 42000, Native Error = 601.

  3. 23 Sep 2005 at 14:32

    Great.


    This little hint with those little word (nolock) saved my life - and the life of our application. (http://www.gpsoverip.de)


    Thank you VERY much ...

  4. 29 Sep 2004 at 06:22

    You say (with regard to locking): "For financial code and denormalized aggregates (those little counters of related data that you stash away and try desperately to keep accurate), you should play it safe and not use this technique. But I think you'll find that for better than 90% of your application, it would not be that big of a deal if a user (or even intermediate code) saw an uncommitted modification"


    What do you mean? If data is being interrogated, then the returned result set MUST be consistent (ACID).


    Seeing uncommitted code is a no-no, whether Financial, denormalized or whatever.

  5. 27 Oct 2003 at 06:46

    Please contribute your suggestion in relation with various issues related with log file management in SQL server. Such as
    1.    Methods to Shrinking the log file.
    2.    Recover the database form Log file
    3.    Recovery mode etc


  6. 01 Jan 1999 at 00:00

    This thread is for discussions of SQL Server Locks.

Leave a comment

Sign in or Join us (it's free).

Michael Balloni

Related podcasts

  • Stack Overflow: Podcast #28

    This is the twenty-eighth episode of the StackOverflow podcast, where Joel and Jeff discuss Windows Azure, SQL Server 2008 full text search, Bayesian filtering, porn detection, and project management — among other things. Jeff met the inestimable Joey DeVilla aka Accordion Guy...

We'd love to hear what you think! Submit ideas or give us feedback