Quick Answer
LCK_M_RIN_S_LOW_PRIORITY occurs when a session waits to acquire a low priority shared range insert-null lock on an index range. This wait type appears during concurrent operations where one process needs to scan a range while another performs modifications, typically in scenarios involving filtered indexes, merge operations, or partition maintenance. Generally not concerning unless wait times exceed several seconds consistently.
Root Cause Analysis
This wait type manifests when SQL Server's lock manager cannot immediately grant a shared range insert-null lock due to conflicting locks held by other sessions. The RIN (Range Insert-Null) lock protects against phantom reads by locking ranges between existing key values in an index. The LOW_PRIORITY designation indicates the request uses the low priority lock acquisition mechanism, which yields to higher priority requests.
The lock manager queues low priority requests behind normal priority requests when lock conflicts occur. This behavior changed in SQL Server 2014 with the introduction of low priority wait options for DDL operations like ALTER INDEX REBUILD. The wait occurs specifically during index range scans where the query processor needs to ensure no new rows can be inserted into the scanned range while maintaining SERIALIZABLE or REPEATABLE READ isolation levels.
In SQL Server 2016 and later, the lock compatibility matrix treats RIN locks as compatible with shared locks but incompatible with exclusive and intent exclusive locks. The LOW_PRIORITY suffix indicates the session opted into delayed lock acquisition, commonly seen during online index rebuilds, partition switches, or when using WAIT_AT_LOW_PRIORITY options.
SQL Server 2019 introduced additional optimizations for low priority operations, including better lock queue management and improved timeout handling. SQL Server 2022 further refined the lock manager's priority queue processing, reducing unnecessary waits in highly concurrent environments.
AutoDBA checks Low priority lock timeout settings, index maintenance scheduling, and isolation level configurations across your entire SQL Server instance in 60 seconds. Download the free diagnostic script and see what else needs attention.
Diagnostic Queries
-- Check current blocking and low priority lock requests
SELECT
r.session_id,
r.blocking_session_id,
r.wait_type,
r.wait_time,
r.wait_resource,
t.text as sql_text,
r.command,
s.program_name,
s.login_name
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
WHERE r.wait_type = 'LCK_M_RIN_S_LOW_PRIORITY'
OR r.blocking_session_id > 0;
-- Analyze lock waits and timeouts for RIN locks
SELECT
wait_type,
waiting_requests_count,
wait_time_ms,
max_wait_time_ms,
signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type LIKE '%RIN%'
OR wait_type LIKE '%LOW_PRIORITY%'
ORDER BY wait_time_ms DESC;
-- Check for long-running transactions holding conflicting locks
SELECT
s.session_id,
s.login_name,
s.program_name,
t.transaction_id,
t.transaction_begin_time,
DATEDIFF(second, t.transaction_begin_time, GETDATE()) as duration_seconds,
t.transaction_state,
r.command,
r.percent_complete
FROM sys.dm_tran_active_transactions t
JOIN sys.dm_tran_session_transactions st ON t.transaction_id = st.transaction_id
JOIN sys.dm_exec_sessions s ON st.session_id = s.session_id
LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
WHERE t.transaction_begin_time < DATEADD(minute, -5, GETDATE())
ORDER BY t.transaction_begin_time;
-- Identify specific objects experiencing RIN lock contention
SELECT
l.resource_database_id,
DB_NAME(l.resource_database_id) as database_name,
l.resource_associated_entity_id,
OBJECT_NAME(l.resource_associated_entity_id, l.resource_database_id) as object_name,
l.resource_type,
l.request_mode,
l.request_status,
l.request_session_id,
r.wait_type,
r.wait_time
FROM sys.dm_tran_locks l
JOIN sys.dm_exec_requests r ON l.request_session_id = r.session_id
WHERE l.request_mode LIKE '%RIN%'
OR r.wait_type LIKE '%RIN%'
ORDER BY r.wait_time DESC;
-- Check for active index maintenance operations
SELECT
r.session_id,
r.command,
r.percent_complete,
r.estimated_completion_time,
r.wait_type,
t.text,
i.name as index_name,
o.name as table_name
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
LEFT JOIN sys.indexes i ON r.object_id = i.object_id AND r.index_id = i.index_id
LEFT JOIN sys.objects o ON r.object_id = o.object_id
WHERE r.command IN ('ALTER INDEX', 'DBCC', 'CREATE INDEX')
OR t.text LIKE '%REBUILD%'
OR t.text LIKE '%REORGANIZE%';
Fix Scripts
Terminate blocking low priority operations
-- Kill sessions with excessive RIN lock waits after identifying blocking chains
-- TEST IN DEV FIRST - This will terminate active sessions
DECLARE @session_id int;
DECLARE kill_cursor CURSOR FOR
SELECT DISTINCT r.session_id
FROM sys.dm_exec_requests r
WHERE r.wait_type = 'LCK_M_RIN_S_LOW_PRIORITY'
AND r.wait_time > 300000 -- 5 minutes
AND r.session_id != @@SPID;
OPEN kill_cursor;
FETCH NEXT FROM kill_cursor INTO @session_id;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Killing session ' + CAST(@session_id AS varchar(10));
-- KILL @session_id; -- Uncomment after verification
FETCH NEXT FROM kill_cursor INTO @session_id;
END;
CLOSE kill_cursor;
DEALLOCATE kill_cursor;
Adjust low priority operation timeouts
-- Modify existing ALTER INDEX operations to use shorter timeouts
-- This prevents indefinite waits in low priority operations
ALTER INDEX [your_index_name] ON [your_table_name]
REBUILD
WITH (
ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = BLOCKERS))
);
-- For partition maintenance operations
ALTER TABLE [your_table_name]
SWITCH PARTITION 1 TO [staging_table_name]
WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 2 MINUTES, ABORT_AFTER_WAIT = SELF));
Reduce isolation level for problematic queries
-- Change isolation level for queries causing excessive RIN lock waits
-- Only use if data consistency requirements permit
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- Or use query hints for specific statements
SELECT * FROM your_table WITH (READCOMMITTED)
WHERE your_conditions;
-- For reporting queries, consider snapshot isolation
ALTER DATABASE [your_database] SET READ_COMMITTED_SNAPSHOT ON;
Implement query timeout for low priority operations
-- Add explicit timeouts to prevent indefinite waits
-- Wrap problematic operations in try-catch blocks
BEGIN TRY
SET LOCK_TIMEOUT 120000; -- 2 minutes
-- Your low priority operation here
ALTER INDEX [problematic_index] ON [your_table] REBUILD
WITH (ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = BLOCKERS)));
SET LOCK_TIMEOUT -1; -- Reset to default
END TRY
BEGIN CATCH
SET LOCK_TIMEOUT -1; -- Ensure reset on error
PRINT 'Operation timed out or failed: ' + ERROR_MESSAGE();
-- Log error or implement retry logic
END CATCH;
AutoDBA generates fix scripts like these automatically, with impact estimates and rollback SQL included.
Prevention
Configure appropriate WAIT_AT_LOW_PRIORITY settings for all online index operations, using MAX_DURATION values between 1-10 minutes based on maintenance windows. Set ABORT_AFTER_WAIT to BLOCKERS rather than SELF to prevent cascading delays during maintenance operations.
Implement query timeouts for operations that frequently encounter RIN lock waits, typically setting LOCK_TIMEOUT to 30-120 seconds for interactive applications. Monitor sys.dm_os_wait_stats daily for increasing RIN-related waits and investigate when wait times exceed normal baselines.
Schedule index maintenance during low-activity periods and stagger operations across different databases to reduce lock contention. Consider using resumable online index rebuilds in SQL Server 2017+ for large tables, allowing operations to pause during high-contention periods.
Configure database-level READ_COMMITTED_SNAPSHOT isolation where appropriate to reduce shared lock duration, but evaluate application compatibility thoroughly before implementation. Partition large tables to isolate maintenance operations to specific partitions, reducing the scope of potential RIN lock conflicts.
Monitor partition switch operations closely, as they frequently generate RIN lock waits when switching between active partitions. Implement application-level retry logic with exponential backoff for operations that occasionally encounter lock timeouts, particularly during maintenance windows.
Need hands-on help?
Dealing with persistent lck_m_rin_s_low_priority issues across your environment? Samix Technology provides hands-on SQL Server performance consulting with 15+ years of production DBA experience.