SQL Server 2025 Added Lock Modes to Extended Events

A lock event in Extended Events is only useful if I can decode the map values. A numeric mode value of 5 is not a diagnosis. The map tells me that 5 means X. Then I can connect the event back to the lock evidence I already know how to read.[1]

A woman DBA marks one of two glowing new padlock symbols at the end of a large lock map spread across a table.

This post is part of the Undocumented Changes in SQL Server 2022 and 2025 series. The contents page lists every part in order.

This post follows the SQL Server 2025 LCK_M_SCH_A and LCK_M_SCH_C post. That post surfaced the new SCH_A and SCH_C names. Here I queried the Extended Events (XE) maps and the optimized locking events for lock after qualification (LAQ). XE is SQL Server’s event tracing system. LAQ is the optimized-locking feature that evaluates a row before taking the lock used to modify it.

The inventory files told me that the lock_mode map exists. They did not store the individual map values, so I queried sys.dm_xe_map_values directly on the 2019 and 2025 local instances. I did not query the 2022 instance. For 2022, I used only the inventory rows that were already captured in hv2022.tsv, so the 2022 comparison in this post covers XE event names and descriptions, not the map values.

The map change

I used this read-only map query on the 2019 and 2025 instances:

The 2019 lock_mode map ended with RX_U at key 20 and LAST_MODE at key 21. The 2025 map no longer shows LAST_MODE and ended this way:

The 2025 lock_owner_type map also added key 8, Node, and moved LastLockInfoOwner from key 8 to key 9. The lock_resource_type map did not change in this comparison. It still includes XACT at key 16.

The wait_types map lines up with the wait-type post. The 2025 map adds LCK_M_SCH_A, LCK_M_SCH_C, their low-priority variants, and their abort-blockers variants. It also includes LOCK_SAFEMODE, LOCK_UPDATE, POPULATE_LOCK_ORDINALS, PLOCK_DAEMON, and ORDLOCK_POPULATE_SYNC in the lock-text slice I queried.

The map shows that XE has names for these modes. It is not a definition of what SCH_A or SCH_C means. Microsoft documents Sch-S and Sch-M as schema stability and schema modification request modes in sys.dm_tran_locks, and the transaction locking guide discusses schema stability and schema modification locks.[2][3] I did not find SCH_A or SCH_C in the Microsoft documentation repositories when I searched the exact names, first whole-word and then case-insensitive.[4]

The definitions turned up elsewhere. A 2025 paper by the Azure SQL Database team defines SCH-A as Schema Access, a shared lock that conflicts only with Sch-M, and SCH-C as Schema Create, an exclusive lock that conflicts with every mode except SCH-A. Snapshot queries and query compilation take SCH-A, and schema changes take SCH-C, as part of a feature called MD-MVCC.[5] The LCK_M_SCH_A and LCK_M_SCH_C post has the full compatibility matrix.

The 2025 XE event changes

The existing lock events are still there in 2025: lock_acquired, lock_released, lock_escalation, lock_timeout, and locks_lock_waits. Their event descriptions matched between the 2022 inventory and the 2025 inventory.

The new lock-related rows were these four:

Event 2025 description
sqlserver.lock_after_qual_stmt_abort Fired when a statement is internally aborted and retried due to lock after qualification.
sqlserver.laq_feedback_stats Lock after qualification query-level feedback statistics.
sqlserver.lock_report_info Reports lock type info of a lock taken.
sqlserver.locking_stats2 Additional database-level locking statistics

Microsoft’s optimized locking article documents three related diagnostic additions. It says the lock_after_qual_stmt_abort event fires when a statement is internally reprocessed because of a conflict with another transaction. It says locking_stats fires for every database every several minutes and reports aggregate locking statistics. It says locking_stats2 fires for SQL Server and Azure SQL Managed Instance, and provides skip index locks and LAQ heuristics statistics.[6]

I used this query to inspect the XE metadata:

lock_acquired, lock_released, lock_escalation, and lock_timeout expose resource_type as lock_resource_type and mode as lock_mode. lock_after_qual_stmt_abort exposes database_id, logical_reads_before_retry, and query_plan_hash_binary. laq_feedback_stats exposes query-level totals for executions, conflicts, eligible logical reads, wasted logical reads, and executions with LAQ. locking_stats2 adds counters for optimized locking, skipped index locks, heap and index updates, and LAQ query-plan heuristics.

A scratch optimized-locking test

Microsoft says optimized locking is available in SQL Server 2025, is disabled by default, and can be enabled per database. It also says accelerated database recovery (ADR) must be enabled before optimized locking can be enabled. For LAQ, it says read committed snapshot isolation (RCSI) must be enabled.[7]

I used a scratch database named undoc_spinoff_locks. This script created the database if needed, enabled ADR, RCSI, and optimized locking, and created the test table:

The database accepted all three options. sys.databases returned 1 for is_accelerated_database_recovery_on, is_read_committed_snapshot_on, and is_optimized_locking_on.

I created a server-level event session named undoc_spinoff_locks, scoped to that database ID. I started it, ran two sessions that updated rows in dbo.lock_probe, queried the ring buffer, and then stopped the session. I did not drop the event session.

The two workload sessions were small. One held a transaction open on id = 1 for eight seconds. The other updated the group_id = 2 rows and then updated id = 1.

I used this only to check the instrumentation, not to measure workload behaviour. The captured lock_acquired and lock_released events used these lock modes:

The XACT resource is the relevant result here. Microsoft’s article says TID locking uses a single lock on the transaction ID to protect modified rows. It also says that with optimized locking, the only lock held until the end of the transaction is the X lock on the TID resource.[8] In this small test, XE showed XACT locks with S and X modes. The capture did not include SCH_A or SCH_C lock modes in this workload.

What I use from this

For SQL Server 2025, I want any XE map decoder that carries its own copy of lock_mode, lock_owner_type, or wait_types to use the 2025 values. The old lock-mode list that ends at LAST_MODE will mislabel key 21 and miss keys 22 and 23.

I also want the optimized-locking events on my diagnostic list. lock_after_qual_stmt_abort is the direct LAQ retry signal. locking_stats, locking_stats2, and laq_feedback_stats give aggregate counters that tell me whether optimized locking and LAQ are being used, skipped, or retried.

The same limitation applies here: A map value is not a definition. For SCH_A and SCH_C, the MD-MVCC paper supplies one, but it describes Azure SQL Database, not SQL Server 2025.

Have you captured SCH_A, SCH_C, or lock_after_qual_stmt_abort on a busy SQL Server 2025 instance? If you capture these events, let me know on Bluesky or LinkedIn. I may add the results to these notes.

References

  1. SQL Server Extended Events packages - Microsoft Learn. Shows sys.dm_xe_map_values use and gives a lock_mode example where value 5 maps to X. ↩
  2. sys.dm_tran_locks (Transact-SQL) - Microsoft Learn. Documents request_mode, Sch-S, Sch-M, and the XACT lock resource type. ↩
  3. Transaction Locking and Row Versioning Guide - Microsoft Learn. Documents schema stability and schema modification locks. ↩
  4. MicrosoftDocs/sql-docs, MicrosoftDocs/azure-docs, and MicrosoftDocs/fabric-docs - GitHub. The Markdown source for Microsoft SQL Server, Azure, and Fabric documentation, searched with whole-word and case-insensitive fixed-string searches on 2026-09-26. ↩
  5. MD-MVCC: Multi-version Concurrency Control for Schema Changes in Azure SQL Database - Antonopoulos et al., Proceedings of the VLDB Endowment, Vol. 18, No. 12, pages 4791-4803, 2025. Defines SCH-A (Schema Access) and SCH-C (Schema Create), gives their compatibility matrix, and says snapshot queries and query compilation take SCH-A while schema changes take SCH-C. ↩
  6. Optimized Locking - Microsoft Learn. Documents TID locking, LAQ, enablement requirements, and optimized-locking diagnostic events. ↩
  7. Optimized Locking - Microsoft Learn. Documents SQL Server 2025 optimized-locking availability, ADR requirements, and RCSI requirements for LAQ. ↩
  8. Optimized Locking - Microsoft Learn. Documents the TID-locking example and says the X lock on the TID resource is the only lock held until the end of the transaction when optimized locking is enabled. ↩