LCK_M_SCH_A and LCK_M_SCH_C: New Lock Wait Types in SQL Server 2025
A new lock wait type in a monitoring dashboard is awkward. If it is a familiar LCK_M_* name, I can usually map it back to a lock mode and a blocking pattern. If it is a new SCH-prefixed name with no description, I have to slow down.

It follows the SQL Server 2025 configuration options post. It also belongs with the first post on SQL Server 2025. The method started in the first post in the whole series.
For SQL Server 2025, I compared SQL Server 2022 CU25 with SQL Server 2025 CU9. CU means cumulative update. The inventory also includes SQL Server 2025 RTM (release to manufacturing), and the lock wait types in this post were present in that RTM inventory too.
The nine new LCK_M wait types
The 2022 to 2025 diff has nine new wait types that match LCK_M_*:
| Wait type | Documentation result |
|---|---|
LCK_M_S_XACT |
described by Microsoft |
LCK_M_S_XACT_READ |
described by Microsoft |
LCK_M_S_XACT_MODIFY |
described by Microsoft |
LCK_M_SCH_A |
not found in the checked Microsoft sources |
LCK_M_SCH_A_LOW_PRIORITY |
not found in the checked Microsoft sources |
LCK_M_SCH_A_ABORT_BLOCKERS |
not found in the checked Microsoft sources |
LCK_M_SCH_C |
not found in the checked Microsoft sources |
LCK_M_SCH_C_LOW_PRIORITY |
not found in the checked Microsoft sources |
LCK_M_SCH_C_ABORT_BLOCKERS |
not found in the checked Microsoft sources |
The three LCK_M_S_XACT* wait types are documented as part of optimized locking. Microsoft says optimized locking uses transaction ID locking and lock after qualification. The sys.dm_os_wait_stats page describes the LCK_M_S_XACT* wait types for tasks waiting on an XACT transaction resource.[1][2]
The six LCK_M_SCH_A* and LCK_M_SCH_C* wait types were different. They were absent from the parsed sys.dm_os_wait_stats wait-type table. I also searched the SQL Server, Azure, and Fabric documentation repositories for each name. I used whole-word fixed-string searches, and I found no hits.[3]
I am not going to expand SCH_A or SCH_C. The names suggest schema lock modes, but I could not find a Microsoft source that defines those abbreviations.
The 2025 lock-mode map has two undocumented names
The Extended Events map for lock modes on the 2025 instance includes the usual lock modes. It also includes two names I had not seen on the Learn lock-mode pages: SCH_A and SCH_C. Extended Events (XE) is SQL Server’s event tracing system.
Here is the read-only query I ran on the local 2025 instance:
|
1 2 3 4 5 6 7 8 9 10 |
SELECT [name] , [map_key] , [map_value] FROM [sys].[dm_xe_map_values] WHERE [name] = N'lock_mode' ORDER BY [map_key]; |
The 2025 output ended with these rows:
|
1 2 3 4 5 6 7 |
map_key map_value ------- --------- 19 RX_S 20 RX_U 21 RX_X 22 SCH_A 23 SCH_C |
The map output is useful, but it is not a definition. It says that 2025 exposes SCH_A and SCH_C as lock-mode map values. It does not say what those modes do, which resources use them, or whether a workload can request them directly.
The documented lock-mode lists still stop at the modes I already knew. The sys.dm_tran_locks page defines Sch-S as schema stability and Sch-M as schema modification. It also documents request statuses named LOW_PRIORITY_WAIT, LOW_PRIORITY_CONVERT, and ABORT_BLOCKERS. Those names match the suffixes on the new wait-type variants.[4]
The transaction locking guide describes only two schema lock types: schema modification (Sch-M) and schema stability (Sch-S). It says Sch-M is used for data definition language (DDL) operations such as adding a column or dropping a table. It says Sch-S is used when SQL Server compiles and executes queries. I did not find SCH_A or SCH_C on that page.[5]
Related inventory rows
The 2025 diff has several lock-related XE additions. I used four of them in this post: sqlserver.lock_report_info, sqlserver.locking_stats2, sqlserver.lock_after_qual_stmt_abort, and sqlserver.laq_feedback_stats.
A read-only query against sys.dm_xe_object_columns showed the related columns. lock_report_info has columns named lockRequestMode and lockResourceType. locking_stats2 has columns for optimized locking, skipped lock requests, and lock after qualification (LAQ). lock_after_qual_stmt_abort records an internally aborted statement retry due to LAQ. laq_feedback_stats records query-level LAQ counters.
I also looked for supporting evidence that did not turn into a finding. The 2022 to 2025 diff has no new columns in sys.dm_tran_locks or sys.dm_os_waiting_tasks. I searched the changed 2025 system module definitions for SCH_A, SCH_C, Sch-A, and Sch-C, and found no hits. New and changed messages did not define SCH_A or SCH_C either.
What I could see in wait stats
I checked sys.dm_os_wait_stats on the local 2025 instance for all nine new LCK_M_* wait types:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
SELECT [wait_type] , [waiting_tasks_count] , [wait_time_ms] , [max_wait_time_ms] FROM [sys].[dm_os_wait_stats] WHERE [wait_type] IN ( N'LCK_M_SCH_A' , N'LCK_M_SCH_A_LOW_PRIORITY' , N'LCK_M_SCH_A_ABORT_BLOCKERS' , N'LCK_M_SCH_C' , N'LCK_M_SCH_C_LOW_PRIORITY' , N'LCK_M_SCH_C_ABORT_BLOCKERS' , N'LCK_M_S_XACT' , N'LCK_M_S_XACT_READ' , N'LCK_M_S_XACT_MODIFY' ) ORDER BY [wait_type]; |
All nine rows existed, and every counter was zero on that idle test instance. I did not try to force one of these waits to appear. The safe test boundary for this post was read-only SELECT statements and locks from my own session. Creating, altering, or dropping an object to produce a schema-lock block was outside that boundary.
My working interpretation
The evidence supports this narrower reading.
SQL Server 2025 adds six undocumented schema-looking lock wait types: LCK_M_SCH_A, LCK_M_SCH_C, and low-priority and abort-blockers variants of each. The 2025 XE lock-mode map exposes SCH_A and SCH_C as lock modes. Microsoft documents Sch-S and Sch-M, but I could not find public documentation for SCH_A or SCH_C in the sources I checked.
The suffixes suggest that these waits can participate in the same low-priority and abort-blockers machinery that sys.dm_tran_locks documents for lock requests. The SCH_ prefix suggests a relationship to schema locks. Those are inferences from names and map values, not definitions from Microsoft.
If one of these wait types appears in your top waits, I start with the usual blocking evidence: current waits, current locks, blockers, lock request status, and the statement text. I would not treat the new name alone as enough to identify the operation behind it.
Next in this series: Columnstore transcoder wait types in SQL Server 2025.
Have you seen LCK_M_SCH_A or LCK_M_SCH_C on a busy SQL Server 2025 instance? Tell me on Bluesky or LinkedIn, and I will update the notes.
References
- Optimized Locking - Microsoft Learn. Describes SQL Server 2025 optimized locking, transaction ID locking, and lock after qualification. ↩
- sys.dm_os_wait_stats (Transact-SQL) - Microsoft Learn. Describes
LCK_M_S_XACT,LCK_M_S_XACT_READ, andLCK_M_S_XACT_MODIFY. ↩ - MicrosoftDocs/sql-docs, MicrosoftDocs/azure-docs, and MicrosoftDocs/fabric-docs - GitHub. The Markdown source of Microsoft Learn for SQL Server, Azure and Fabric, searched with whole-word, fixed-string
git grepon 2026-09-26. The search results are my own. ↩ - sys.dm_tran_locks (Transact-SQL) - Microsoft Learn. Defines documented lock request modes and request statuses. ↩
- Transaction Locking and Row Versioning Guide - Microsoft Learn. Describes documented schema stability and schema modification locks. ↩