Microsoft SQL Server 2008 Internals: Transactions and Concurrency
- 3/11/2009
Lock Compatibility
Two locks are compatible if one lock can be granted while another lock on the same resource is held by a different process. If a lock requested for a resource is not compatible with a lock currently being held, the requesting connection must wait for the lock. For example, if a shared page lock exists on a page, another process requesting a shared page lock for the same page is granted the lock because the two lock types are compatible. But a process that requests an exclusive lock for the same page is not granted the lock because an exclusive lock is not compatible with the shared lock already held. Table 10-2 summarizes the compatibility of locks in SQL Server 2008. Along the top are all the lock modes that a process might already hold. Along the left edge are the lock modes that another process might request.
Table 10-2. SQL Server lock compatibility matrix
NL |
SCH-S |
SCH-M |
S |
U |
X |
IS |
IU |
IX |
SIU |
SIX |
UIX |
BU |
RS-S |
RS-U |
RI-N |
RI-S |
RI-U |
RI-X |
RX-S |
RX-U |
RX-X |
|
NL |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
SCH-S |
N |
N |
C |
N |
N |
N |
N |
N |
N |
N |
N |
N |
N |
I |
I |
I |
I |
I |
I |
I |
I |
I |
SCH-M |
N |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
S |
N |
N |
C |
N |
N |
C |
N |
N |
C |
N |
C |
C |
C |
N |
N |
N |
N |
N |
C |
N |
N |
C |
U |
N |
N |
C |
N |
C |
C |
N |
C |
C |
C |
C |
C |
C |
N |
C |
N |
N |
C |
C |
N |
C |
C |
X |
N |
N |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
N |
C |
C |
C |
C |
C |
C |
IS |
N |
N |
C |
N |
N |
C |
N |
N |
N |
N |
N |
N |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
IU |
N |
N |
C |
N |
C |
C |
N |
N |
N |
N |
N |
C |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
IX |
N |
N |
C |
C |
C |
C |
N |
N |
N |
C |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
SIU |
N |
N |
C |
N |
C |
C |
N |
N |
C |
N |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
SIX |
N |
N |
C |
C |
C |
C |
N |
N |
C |
C |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
UIX |
N |
N |
C |
C |
C |
C |
N |
C |
C |
C |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
I |
I |
BU |
N |
N |
C |
C |
C |
C |
C |
C |
C |
C |
C |
C |
N |
I |
I |
I |
I |
I |
I |
I |
I |
I |
RS-S |
N |
I |
I |
N |
N |
C |
I |
I |
I |
I |
I |
I |
I |
N |
N |
C |
C |
C |
C |
C |
C |
C |
RI-U |
N |
I |
I |
N |
C |
C |
I |
I |
I |
I |
I |
I |
I |
N |
C |
C |
C |
C |
C |
C |
C |
C |
RI-N |
N |
I |
I |
N |
N |
N |
I |
I |
I |
I |
I |
I |
I |
C |
C |
N |
N |
N |
N |
C |
C |
C |
RI-S |
N |
I |
I |
N |
N |
C |
I |
I |
I |
I |
I |
I |
I |
C |
C |
N |
N |
N |
C |
C |
C |
C |
RI-U |
N |
I |
I |
N |
C |
C |
I |
I |
I |
I |
I |
I |
I |
C |
C |
N |
N |
C |
C |
C |
C |
C |
RI-X |
N |
I |
I |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
C |
C |
N |
C |
C |
C |
C |
C |
C |
RX-S |
N |
I |
I |
N |
N |
C |
I |
I |
I |
I |
I |
I |
I |
C |
C |
C |
C |
C |
C |
C |
C |
C |
RX-U |
N |
I |
I |
N |
C |
C |
I |
I |
I |
I |
I |
I |
I |
C |
C |
C |
C |
C |
C |
C |
C |
C |
RX-X |
N |
I |
I |
C |
C |
C |
I |
I |
I |
I |
I |
I |
I |
C |
C |
C |
C |
C |
C |
C |
C |
C |
At the point where the held lock and requested lock meet, there can be three possible values. N indicates that there is no conflict, C indicates that there will be a conflict and the requesting process will have to wait, and I indicates an invalid combination that could never occur. All the I values in the chart involve range locks, which can be applied only to KEY resources, so any type of lock that can never be applied to KEY resources indicates an invalid comparison.
Lock compatibility comes into play between locks on different resources, such as table locks and page locks. A table and a page obviously represent an implicit hierarchy because a table is made up of multiple pages. If an exclusive page lock is held on one page of a table, another process cannot get even a shared table lock for that table. This hierarchy is protected using intent locks. A process acquiring an exclusive page lock, update page lock, or intent exclusive page lock first acquires an intent exclusive lock on the table. This intent exclusive table lock prevents another process from acquiring the shared table lock on that table. (Remember that intent exclusive locks and shared locks on the same resource are not compatible.)
Similarly, a process acquiring a shared row lock must first acquire an intent shared lock for the table, which prevents another process from acquiring an exclusive table lock. Or if the exclusive table lock already exists, the intent shared lock is not granted and the shared page lock has to wait until the exclusive table lock is released. Without intent locks, process A can lock a page in a table with an exclusive page lock and process B can place an exclusive table lock on the same table and hence think that it has a right to modify the entire table, including the page that process A has exclusively locked.
Even if two locks are compatible, the requester of the second lock might still have to wait if an incompatible lock is waiting. For example, suppose that process A holds a shared page lock. Process B requests an exclusive page lock and must wait because the shared page lock and the exclusive page lock are not compatible. Process C requests a shared page lock that is compatible with the shared page already granted to process A. However, the shared page lock cannot be granted immediately. Process C must wait for its shared page lock because process B is ahead of it in the lock queue with a request (exclusive page) that is not compatible.
By examining the compatibility of locks not only with processes granted locks, but also processes waiting, SQL Server prevents lock starvation, which can result when requests for shared locks keep overlapping so that the request for the exclusive lock can never be granted.