LCK_M_SCH_M Wait Type in SQL Server

LCK_M_SCH_M is a wait to acquire a Schema Modification (SCH-M) lock. DDL needs this lock to change an object’s structure: ALTER TABLE, offline index rebuilds, partition switches, truncates, and drops all take SCH-M. It is the least compatible lock in the engine; it conflicts with every other lock, including the Schema Stability locks that every running query holds.

This wait means your DDL is stuck. Something is still using the object, and the schema change cannot start until every last reader and writer lets go.

Is It a Problem?

The wait itself hurts twice. First, the DDL is delayed. Second, and worse, while the SCH-M request queues, it blocks all new queries against the object from compiling, so a stuck ALTER TABLE quickly turns into an application-wide stall on that table. If LCK_M_SCH_M shows up in your top waits, deployments or maintenance are colliding with the workload.

Common Causes

  • Running DDL while the application is active, with long-running queries or open transactions still holding locks on the object.
  • Index maintenance jobs overlapping business hours, especially offline rebuilds.
  • Partition switch or TRUNCATE TABLE steps in ETL waiting for readers to clear.
  • An idle session with an uncommitted transaction that touched the table hours ago.

What To Do

  1. When DDL hangs, check sys.dm_os_waiting_tasks for the SCH-M waiter and follow blocking_session_id to the culprit. sys.dm_tran_locks shows what it still holds.
  2. Kill or complete the blocker if it is an abandoned transaction; DBCC OPENTRAN in the database points at the oldest one.
  3. Schedule DDL for quiet windows, and use ONLINE = ON operations where the edition allows, which need SCH-M only briefly at the start and end.
  4. On SQL Server 2014 and later, use WAIT_AT_LOW_PRIORITY with ABORT_AFTER_WAIT so index operations fail fast or kill blockers deliberately, instead of freezing the table for everyone.

How To See It

Rank it against everything else with Get-WaitStatistics. LCK_M_SCH_M is spiky rather than constant, so line the spikes up with your job schedule and deployment history.


Part of the SQL Server Wait Types Library.
Related deep dive: LCK_M_X, LCK_M_S, and LCK_M_U Wait Types.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *