Quick Answer
LCK_M_RS_U_LOW_PRIORITY occurs when a task waits for an Update lock with Low Priority on the current key and an Update Range lock between keys during low priority ALTER operations. This wait type only appears during ALTER TABLE or ALTER INDEX operations using the WAIT_AT_LOW_PRIORITY option, introduced in SQL Server 2014.
Root Cause Analysis
This wait type manifests exclusively during ALTER operations configured with WAIT_AT_LOW_PRIORITY, where SQL Server's lock manager attempts to acquire update locks with reduced priority to avoid blocking concurrent operations. The lock manager queues these requests behind existing lock holders, creating a controlled degradation scenario.
The lock manager differentiates between standard lock requests and low priority requests through internal priority queuing mechanisms. When WAIT_AT_LOW_PRIORITY is specified, the lock acquisition logic places these requests at the end of the lock queue, behind all existing and future normal priority requests. This prevents ALTER operations from blocking production workloads but can result in extended wait times.
SQL Server 2014 introduced this mechanism specifically to address the problem of schema modification operations blocking concurrent queries. The Range-Update (RS_U) lock component indicates the operation needs to lock both individual keys and ranges between keys, typical of index reorganization or partition operations where the engine must ensure no new rows are inserted between existing keys during the modification.
The low priority lock behavior remains consistent across SQL Server versions 2014 through 2022, though SQL Server 2016 added improvements to the priority queue management that reduced unnecessary context switches during extended waits. SQL Server 2019 enhanced the lock escalation detection within low priority operations to prevent deadlock scenarios when combined with partition switching operations.
AutoDBA checks Low priority lock timeouts, blocking session analysis, and index maintenance scheduling optimization across your entire SQL Server instance in 60 seconds. Download the free diagnostic script and see what else needs attention.
Diagnostic Queries
-- Check current low priority ALTER operations and their wait times
SELECT
r.session_id,
r.wait_type,
r.wait_time_ms,
r.wait_resource,
t.text AS query_text,
r.blocking_session_id,
DB_NAME(r.database_id) AS database_name
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.wait_type = 'LCK_M_RS_U_LOW_PRIORITY';
-- Identify blocking chains affecting low priority operations
WITH BlockingChain AS (
SELECT
session_id,
blocking_session_id,
wait_type,
wait_time_ms,
wait_resource,
0 AS level
FROM sys.dm_exec_requests
WHERE blocking_session_id <> 0
AND wait_type = 'LCK_M_RS_U_LOW_PRIORITY'
UNION ALL
SELECT
r.session_id,
r.blocking_session_id,
r.wait_type,
r.wait_time_ms,
r.wait_resource,
bc.level + 1
FROM sys.dm_exec_requests r
INNER JOIN BlockingChain bc ON r.session_id = bc.blocking_session_id
WHERE bc.level < 10
)
SELECT * FROM BlockingChain ORDER BY level, session_id;
-- Monitor lock waits and resource contention for low priority operations
SELECT
resource_type,
resource_database_id,
resource_associated_entity_id,
request_mode,
request_type,
request_status,
request_session_id,
resource_description
FROM sys.dm_tran_locks
WHERE request_session_id IN (
SELECT session_id
FROM sys.dm_exec_requests
WHERE wait_type = 'LCK_M_RS_U_LOW_PRIORITY'
);
-- Check for concurrent operations that might be blocking low priority ALTERs
SELECT
s.session_id,
s.login_name,
s.program_name,
r.command,
r.percent_complete,
t.text AS current_statement,
r.estimated_completion_time/1000/60 AS estimated_minutes_remaining
FROM sys.dm_exec_sessions s
INNER JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.database_id = (
SELECT database_id
FROM sys.dm_exec_requests
WHERE wait_type = 'LCK_M_RS_U_LOW_PRIORITY'
)
AND s.session_id <> @@SPID;
-- Historical analysis of low priority wait patterns
SELECT
DATEPART(hour, creation_time) AS hour_of_day,
COUNT(*) AS wait_occurrences,
AVG(CAST(wait_duration_ms AS bigint)) AS avg_wait_ms,
MAX(CAST(wait_duration_ms AS bigint)) AS max_wait_ms
FROM sys.dm_xe_session_events xe
WHERE xe.name = 'lock_acquired'
AND xe.event_data.value('(/event/data[@name="mode"]/text)[1]', 'varchar(20)') LIKE '%LOW_PRIORITY%'
GROUP BY DATEPART(hour, creation_time)
ORDER BY hour_of_day;
Fix Scripts
Increase MAX_DURATION for low priority operations
-- Modify existing ALTER operation timeout
-- Test this value based on your maintenance windows
ALTER INDEX IX_YourIndex ON dbo.YourTable REBUILD
WITH (ONLINE = ON,
WAIT_AT_LOW_PRIORITY (MAX_DURATION = 10 MINUTES,
ABORT_AFTER_WAIT = BLOCKERS));
-- WARNING: ABORT_AFTER_WAIT = BLOCKERS will kill blocking sessions
-- Consider ABORT_AFTER_WAIT = SELF for safer behavior
Kill long-running blocking sessions during maintenance windows
-- Identify and terminate sessions blocking low priority operations
-- Use extreme caution in production environments
DECLARE @BlockingSessionId INT;
SELECT @BlockingSessionId = blocking_session_id
FROM sys.dm_exec_requests
WHERE wait_type = 'LCK_M_RS_U_LOW_PRIORITY'
AND wait_time_ms > 300000; -- 5 minutes
IF @BlockingSessionId IS NOT NULL AND @BlockingSessionId > 50
BEGIN
PRINT 'Killing session: ' + CAST(@BlockingSessionId AS VARCHAR(10));
-- KILL @BlockingSessionId; -- Uncomment only after verification
END
-- Always verify the session is not critical before executing KILL
Convert to standard priority during off-peak hours
-- Switch to normal priority ALTER during maintenance windows
-- This bypasses low priority queuing entirely
IF DATEPART(hour, GETDATE()) BETWEEN 2 AND 5 -- 2 AM to 5 AM maintenance window
BEGIN
ALTER INDEX IX_YourIndex ON dbo.YourTable REBUILD
WITH (ONLINE = ON); -- No WAIT_AT_LOW_PRIORITY clause
END
ELSE
BEGIN
RAISERROR('Index rebuild scheduled for maintenance window only', 16, 1);
END
-- Schedule this during known low-activity periods
Implement progressive timeout strategy
-- Attempt low priority first, escalate to standard priority if timeout
DECLARE @StartTime DATETIME2 = GETDATE();
DECLARE @TimeoutMinutes INT = 15;
BEGIN TRY
ALTER INDEX IX_YourIndex ON dbo.YourTable REBUILD
WITH (ONLINE = ON,
WAIT_AT_LOW_PRIORITY (MAX_DURATION = @TimeoutMinutes MINUTES,
ABORT_AFTER_WAIT = SELF));
PRINT 'Low priority rebuild completed successfully';
END TRY
BEGIN CATCH
IF DATEDIFF(MINUTE, @StartTime, GETDATE()) >= @TimeoutMinutes
BEGIN
PRINT 'Retrying with standard priority after timeout';
ALTER INDEX IX_YourIndex ON dbo.YourTable REBUILD WITH (ONLINE = ON);
END
ELSE
THROW;
END CATCH
-- This pattern works best for automated maintenance scripts
AutoDBA generates fix scripts like these automatically, with impact estimates and rollback SQL included.
Prevention
Configure maintenance windows to align with actual low-activity periods using SQL Server Agent jobs scheduled during proven quiet hours. Monitor sys.dm_db_index_usage_stats to identify indexes with minimal read activity patterns for optimal low priority operation timing.
Implement progressive timeout strategies starting with conservative MAX_DURATION values (5-10 minutes) and escalating to ABORT_AFTER_WAIT = BLOCKERS only during designated maintenance windows. Never use ABORT_AFTER_WAIT = BLOCKERS during business hours as it terminates blocking user sessions.
Establish monitoring alerts for LCK_M_RS_U_LOW_PRIORITY waits exceeding 30 minutes, indicating either insufficient maintenance windows or unexpected concurrent workload patterns. Use sys.dm_xe_sessions to capture detailed lock wait events for historical analysis of blocking patterns.
Consider partitioning strategies for large tables where ALTER operations consistently timeout. Partition switching operations with low priority settings often complete faster than full table alterations. For frequently modified tables, evaluate columnstore indexes or In-Memory OLTP tables which support concurrent DML during many schema modification operations.
Design application retry logic to handle temporary unavailability during schema modifications. Low priority operations intentionally yield to production workloads, so applications should expect brief periods where ALTER operations may not complete as quickly as standard priority operations.
Need hands-on help?
Dealing with persistent lck_m_rs_u_low_priority issues across your environment? Samix Technology provides hands-on SQL Server performance consulting with 15+ years of production DBA experience.