SQL Server deadlocks between select/update or multiple selects

后端 未结 5 1501
一生所求
一生所求 2020-12-23 19:57

All of the documentation on SQL Server deadlocks talks about the scenario in which operation 1 locks resource A then attempts to access resource B and operation 2 locks reso

相关标签:
5条回答
  • 2020-12-23 20:36

    My guess is that the select-statement aquires a read-lock, when you come with the update-statement, then it needs to upgrade to a write-lock.

    Upgrading to a write-lock requires that all other read-locks are removed (Their select-transactions completes). But if another process already have the brilliant idea to upgrade to a write-lock, then you suddenly have two processes waiting for each other to release the read-lock, so they can get the write-lock.

    If using select-for-update (UPDLOCK) then it will aquire a write-lock from the beginning and then you don't have the deadlock issue.

    0 讨论(0)
  • 2020-12-23 20:42

    Read up properly on transactions and isolation levels: for a somewhat dense but fairly thorough and technology neutral work, see Principles of Transaction Processing. It rocked my world (and gave me quite a few headaches!).

    I'm not sure what you're having trouble with, or what isolation level you are using. But consider this: for all the database engine knows, if you do reads in one transaction, how can it tell whether or not you are going to do a write later on? High isolation levels require locking whenever a read is done, possibly on the entire table to protect against phantom reads, since the data may affect a write later on.

    Would you want the database to wait arbitrarily long for an exclusive lock on your data? Take a look at your isolation levels throughout, and whether you are unnecessarily running a series of reads as an isolated transaction. It's not always easy to determine how filthy reads you can tolerate, though...

    0 讨论(0)
  • 2020-12-23 20:50

    Locks between single queries can happen as they lock single rows, not the entire table:

    The update query gets an update lock on a few rows in a table, and the select query gets a read lock on some other rows in the table. The update query then tries to get an update lock on the rows that are read locked, and the select query tries to get a read lock on the rows that are update locked.

    It can get even more complicated with escalading locks, i.e. the database decides that there are too many single rows locked by a transaction so that it should be escalated into locking a section of the table or the entire table. This means that the lock may affect rows that aren't directly involved in the query.

    0 讨论(0)
  • 2020-12-23 20:54

    I'm surprised no one has mentioned the WITH (UPDLOCK) locking hint. It's very useful if you have deadlocks involving e.g. two select-insert pairs running in parallel.

    In SQL Server, if you issue the selects with WITH (UPDLOCK), the second select will wait until the first select is finished. Otherwise they get shared locks, and when they simultaneously try to upgrade to exclusive locks, they deadlock.

    0 讨论(0)
  • 2020-12-23 20:55

    This can happen because a select takes a lock out on two different indexes, meanwhile an update takes a lock out on the same indexes in the opposite order. The select needs two indexes because the first index doesn't cover all of the columns it needs to access; the update needs two indexes because if you update an index's key column you need to take a lock on it.

    http://blogs.msdn.com/bartd/archive/2006/09/25/770928.aspx has a fantastic explanation. Suggested fixes include adding an index that covers all of the columns the select needs, switching to snapshot isolation, or explicitly forcing the select to grab an update lock that it wouldn't normally need.

    0 讨论(0)
提交回复
热议问题