Transaction ID (TID) locking
In the database engine, locking is a mechanism that prevents multiple transactions from
updating the same data simultaneously in order to guarantee the
ACID
properties of
transactions.
When a transaction needs to modify data, it requests a lock on the data. The lock is granted if
no other conflicting locks are held on the data, and the transaction can proceed with the
modification. If another conflicting lock is held on the data, the transaction must wait for the
lock to be released before it can proceed.
When multiple transactions attempt to access the same data concurrently, the database engine
must resolve potentially complex conflicts with concurrent reads and writes. Locking is one of
the mechanisms by which the engine can provide the semantics for the ANSI SQL transaction
isolation levels. Although locking in databases is essential, reduced concurrency, deadlocks,
complexity, and lock overhead can affect performance and scalability.
When
row versioning
based isolation levels are in use or when ADR is enabled, every row in the
database internally contains a transaction ID (TID). TID is persisted with the row. Every
transaction modifying a row stamps the row with its TID.
With TID locking, instead of taking the lock on the key of the row, a lock is taken on the TID of
the row. The modifying transaction holds an
lock on its TID. Other transactions acquire an
lock on the TID to wait until the first transaction completes. With TID locking, page and row
locks continue to be taken for modifications, but each page and row lock is released as soon as
each row is modified. The only lock held until the end of transaction is the single
lock on the
TID resource, replacing multiple page and row (key) locks.
Consider the following example that shows locks for the current session while a write
transaction is active:
X
S
X
/* Is optimized locking is enabled? */
SELECT
DATABASEPROPERTYEX(DB_NAME(),
'IsOptimizedLockingOn'
)
AS is_optimized_locking_enabled;
CREATE
TABLE t0 (
a int
PRIMARY
KEY
,
b int
NULL
);
INSERT
INTO t0
VALUES (1,10),(2,20),(3,30);
GO