Programming language used to interact with SQL Server databases
ROWLOCK is a request for row-level locks, not a guarantee. The behavior is constrained but not absolute.
- Does
WITH (ROWLOCK)force only row locks?
No. ROWLOCK specifies that row-level locks are to be taken where possible, but it does not guarantee that only row locks will be used for the entire operation. Locking is still subject to the normal locking hierarchy and engine decisions.
Relevant points from the documentation:
- Data modification statements (
UPDATE,INSERT,DELETE) typically request both shared and exclusive locks and can use row, page, or table locks depending on the access pattern and optimizer decisions. - Locking always follows the lock hierarchy (row → page → HoBT → table), and intent locks are used at higher levels to protect lower-level locks.
- Can SQL Server still acquire page locks with
ROWLOCK?
Yes. ROWLOCK is a hint that row-level locks are to be taken, but it does not explicitly forbid page locks. Page locks can still be taken in cases such as:
- Internal operations where page-level metadata or structures must be protected.
- Situations where the engine decides a different granularity is required to maintain consistency or protect internal structures.
To disallow page locks on an index, the documented mechanism is to set index/table options (not ROWLOCK), for example via CREATE INDEX / ALTER INDEX or CREATE TABLE / ALTER TABLE options that disallow page-level locks. The documentation explicitly states that locking granularity can be configured so that:
- If page-level locks are disallowed, the index is accessed by row-level and table-level locks.
- Can SQL Server escalate to table (OBJECT/TABLE) locks?
Yes. Lock escalation is still possible. The locking guide explicitly notes that:
- Lock granularity can be affected by
LOCK_ESCALATIONon the table. - When page and row locks are both disallowed, table-level locks are used.
Even when row-level locking is requested, the engine can escalate to table-level locks when the number of row/page locks becomes large or when required by LOCK_ESCALATION settings. ROWLOCK does not disable escalation.
- Can the engine ignore
ROWLOCKand choose higher granularity?
Yes. Table and query hints are honored “as possible,” but the engine can still choose different locking behavior when necessary. The documentation on customizing locking and row versioning makes clear that:
- Locking granularity is ultimately controlled by index/table options and the lock escalation mechanism.
- Page-level, row-level, or both can be disallowed per index; otherwise, the engine can choose among them.
The table-hints documentation states that hints like TABLOCKX, UPDLOCK, XLOCK control how locks are taken and held, but they do not override all internal decisions. For example, UPDLOCK is explicitly described as taking update locks at row or page level, and if combined with TABLOCK or if a table-level lock is taken for some other reason, an exclusive table lock is taken instead. This shows that hints can be superseded by higher-level locking when the engine deems it necessary.
- Differences in behavior with optimized locking (SQL Server 2019/2022/Azure SQL Database)
With optimized locking and RCSI enabled, the guidance is:
- Optimized locking focuses on reducing blocking by qualifying rows using row versions and acquiring locks only on qualifying rows (“lock after qualification”).
- Table and query hints such as
UPDLOCK,XLOCK, etc. are still honored but reduce the benefit of optimized locking because they force the engine to take and hold locks longer. - The documentation explicitly recommends avoiding locking hints where possible under optimized locking.
Key implications:
- Optimized locking changes when and how long locks are held, not the fundamental fact that lock escalation and higher-granularity locks can still occur.
- There is no statement that
ROWLOCKbecomes a strict guarantee under any version or under optimized locking.
Summary per question:
-
WITH (ROWLOCK)does not guarantee only row-level locks; it requests row locks where possible. - Page locks can still be acquired in some scenarios even with
ROWLOCK. - Row locks can still be escalated to table (OBJECT/TABLE) locks;
ROWLOCKdoes not disable escalation. - The engine may effectively override the preference when required by lock escalation, index/table options, or internal needs; hints are honored but not absolute.
- Across SQL Server 2019, 2022, and Azure SQL Database (with optimized locking), the core behavior remains: hints are honored but can reduce optimized locking benefits and do not prevent escalation or higher-granularity locks.
References: