Skip to content

Commit 8938cc8

Browse files
20240222 acrolinx
1 parent f341c16 commit 8938cc8

1 file changed

Lines changed: 12 additions & 12 deletions

File tree

docs/relational-databases/performance/optimized-locking.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ When multiple transactions are allowed to access the same data concurrently, the
8080

8181
### Optimized locking and transaction ID (TID) locking
8282

83-
Every row in the Database Engine internally contains a transaction ID (TID) when row versioning is in use. This TID is persisted on disk. Every transaction modifying a row will stamp that row with its TID.
83+
Every row in the Database Engine internally contains a transaction ID (TID) when row versioning is in use. This TID is persisted on disk. Every transaction modifying a row stamps that row with its TID.
8484

85-
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 will hold an X lock on its TID. Other transactions will acquire an S lock on the TID to check if the first transaction is still active. With TID locking, page and row locks continue to be taken for updates, but each page and row lock is released as soon as each row is updated. The only lock held until end of transaction is the X lock on the TID resource, replacing page and row (key) locks as demonstrated in the next demo. (Other standard database and object locks are not affected by optimized locking.)
85+
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 X lock on its TID. Other transactions acquire an S lock on the TID to check if the first transaction is still active. With TID locking, page and row locks continue to be taken for updates, but each page and row lock is released as soon as each row is updated. The only lock held until end of transaction is the X lock on the TID resource, replacing page and row (key) locks as demonstrated in the next demo. (Other standard database and object locks are not affected by optimized locking.)
8686

8787
Optimized locking helps to reduce lock memory as very few locks are held for large transactions. In addition, optimized locking also avoids lock escalations. This allows other concurrent transactions to access the table.
8888

@@ -148,7 +148,7 @@ The behavior of blocking changes with optimized locking in the previous example.
148148

149149
However, with optimized locking, Session 2 will not be blocked as the latest committed version of row 1 contains a=1, which does not satisfy the predicate of Session 2.
150150

151-
If the predicate is satisfied, we wait for any active transaction on the row to finish. If we had to wait for the S TID lock, the row might have changed, and the latest committed version might have changed. In that case, instead of aborting the transaction due to an update conflict, the Database Engine will retry the predicate evaluation on the same row. If the predicate qualifies upon retry, the row will be updated.
151+
If the predicate is satisfied, we wait for any active transaction on the row to finish. If we had to wait for the S TID lock, the row might have changed, and the latest committed version might have changed. In that case, instead of aborting the transaction due to an update conflict, the Database Engine retries the predicate evaluation on the same row. If the predicate qualifies upon retry, the row will be updated.
152152

153153
Consider the following example when a predicate change is automatically retried:
154154

@@ -196,7 +196,7 @@ Without LAQ, transaction T2 will be blocked and wait for the transaction T1 to c
196196

197197
After both transactions commit, table `t1` will contain the following rows:
198198

199-
```
199+
```output
200200
a | b
201201
1 | 3
202202
```
@@ -207,7 +207,7 @@ With LAQ, transaction T2 will use the latest committed version of the row b (`b`
207207

208208
After both transactions commit, table `t1` will contain the following rows:
209209

210-
```
210+
```output
211211
a | b
212212
1 | 2
213213
```
@@ -221,9 +221,9 @@ To support monitoring and troubleshooting of blocking and deadlocking with optim
221221

222222
- Wait types for optimized locking
223223
- `XACT` wait types and resource descriptions in [sys.dm_os_wait_stats (Transact-SQL)](../system-dynamic-management-views/sys-dm-os-wait-stats-transact-sql.md#lck_m_s_xact):
224-
- `LCK_M_S_XACT_READ` - Occurs when a task is waiting for a shared lock on an XACT `wait_resource` type, with an intent to read.
225-
- `LCK_M_S_XACT_MODIFY` - Occurs when a task is waiting for a shared lock on an XACT `wait_resource` type, with an intent to modify.
226-
- `LCK_M_S_XACT` - Occurs when a task is waiting for a shared lock on an XACT `wait_resource` type, where the intent cannot be inferred. Rare.
224+
- `LCK_M_S_XACT_READ` - Occurs when a task is waiting for a shared lock on an `XACT` `wait_resource` type, with an intent to read.
225+
- `LCK_M_S_XACT_MODIFY` - Occurs when a task is waiting for a shared lock on an `XACT` `wait_resource` type, with an intent to modify.
226+
- `LCK_M_S_XACT` - Occurs when a task is waiting for a shared lock on an `XACT` `wait_resource` type, where the intent cannot be inferred. Rare.
227227
- Locking resources visibility
228228
- `XACT` locking resources. For more information, see `resource_description` in [sys.dm_tran_locks (Transact-SQL)](../system-dynamic-management-views/sys-dm-tran-locks-transact-sql.md).
229229
- Wait resource visibility
@@ -241,13 +241,13 @@ To maximize the benefits of optimized locking, it is recommended to enable [read
241241
ALTER DATABASE databasename SET READ_COMMITTED_SNAPSHOT ON;
242242
```
243243

244-
In [!INCLUDE [asdb](../../includes/ssazure-sqldb.md)], RCSI is enabled by default and read committed is the default isolation level. With RCSI enabled and when using read committed isolation level, readers don't block writers and writers don't block readers. Readers read a version of the row from the snapshot taken at the start of the query. With LAQ, writers will qualify rows per the predicate based on the latest committed version of the row without acquiring U locks. With LAQ, a query will wait only if the row qualifies and there is an active write transaction on that row. Qualifying based on the latest committed version and locking only the qualified rows reduces blocking and increases concurrency.
244+
In [!INCLUDE [asdb](../../includes/ssazure-sqldb.md)], RCSI is enabled by default and read committed is the default isolation level. With RCSI enabled and when using read committed isolation level, readers don't block writers, and writers don't block readers. Readers read a version of the row from the snapshot taken at the start of the query. With LAQ, writers will qualify rows per the predicate based on the latest committed version of the row without acquiring U locks. With LAQ, a query will wait only if the row qualifies and there is an active write transaction on that row. Qualifying based on the latest committed version and locking only the qualified rows reduces blocking and increases concurrency.
245245

246246
In addition to reduced blocking, the lock memory required will be reduced. This is because readers don't take any locks, and writers take only short duration locks, instead of locks that expire at the end of the transaction. When using stricter isolation levels like repeatable read or serializable, the Database Engine is forced to hold row and page locks until the end of the transaction, for both readers and writers, resulting in increased blocking and lock memory.
247247

248248
### Avoid locking hints
249249

250-
While [table and query hints](../../t-sql/queries/hints-transact-sql.md) are honored, they reduce the benefit of optimized locking. Lock hints like UPDLOCK, READCOMMITTEDLOCK, XLOCK, HOLDLOCK, etc., in your queries reduce the full benefits of optimized locking. Having such lock hints in the queries forces the Database Engine to take row/page locks and hold them until the end of the transaction, to honor the intent of the lock hints. Some applications have logic where lock hints are needed, for example when reading a row with select with UPDLOCK and then updating it later. We recommend using lock hints only where needed.
250+
While [table and query hints](../../t-sql/queries/hints-transact-sql.md) are honored, they reduce the benefit of optimized locking. Lock hints like `UPDLOCK`, `READCOMMITTEDLOCK`, `XLOCK`, `HOLDLOCK`, etc., in your queries reduce the full benefits of optimized locking. Having such lock hints in the queries forces the Database Engine to take row/page locks and hold them until the end of the transaction, to honor the intent of the lock hints. Some applications have logic where lock hints are needed, for example when reading a row with select with `UPDLOCK` and then updating it later. We recommend using lock hints only where needed.
251251

252252
With optimized locking, there are no restrictions on existing queries and queries do not need to be rewritten. Queries that are not using hints will benefit most from optimized locking.
253253

@@ -279,7 +279,7 @@ FROM t3 WITH (REPEATABLEREAD)
279279
INNER JOIN t4 ON t3.a = t4.a;
280280
```
281281

282-
In the previous query example, only table `t3` will use the repeatable read isolation level, and will hold locks until the end of the transaction. Other updates to `t3` can still benefit from optimized locking. The same applies to the HOLDLOCK hint.
282+
In the previous query example, only table `t3` will use the repeatable read isolation level, and will hold locks until the end of the transaction. Other updates to `t3` can still benefit from optimized locking. The same applies to the `HOLDLOCK` hint.
283283

284284
## Frequently asked questions (FAQ)
285285

@@ -311,7 +311,7 @@ If ADR is disabled, optimized locking is automatically disabled as well.
311311

312312
### What if I want to force queries to block despite optimized locking?
313313

314-
For customers using RCSI, to force blocking between two queries when optimized locking is enabled, use the READCOMMITTEDLOCK query hint.
314+
For customers using RCSI, to force blocking between two queries when optimized locking is enabled, use the `READCOMMITTEDLOCK` query hint.
315315

316316
## Related content
317317

0 commit comments

Comments
 (0)