mediumLocking

LCK_M_IU_LOW_PRIORITY Wait Type Explained

LCK_M_IU_LOW_PRIORITY wait type occurs with SQL Server LOW_PRIORITY ALTER operations. Learn diagnosis, fixes, and prevention for Intent Update lock waits.

Quick Answer

LCK_M_IU_LOW_PRIORITY occurs when a session waits for an Intent Update lock while using the LOW_PRIORITY option in ALTER TABLE or ALTER INDEX operations. This wait type indicates the low priority operation is yielding to normal priority operations accessing the same resource. Generally not concerning as it represents expected throttling behavior.

Root Cause Analysis

This wait type manifests exclusively with SQL Server 2014's introduction of the LOW_PRIORITY locking option for online index operations and table alterations. When ALTER TABLE or ALTER INDEX specifies WAIT_AT_LOW_PRIORITY, the lock manager places these requests in a separate low priority queue within the lock compatibility matrix.

The Intent Update (IU) lock requests from low priority operations must wait behind all normal priority lock requests on the same resource. The lock manager's scheduler processes normal priority requests first, causing low priority operations to accumulate wait time in this state. This behavior prevents schema modification operations from blocking user transactions while still allowing them to complete during quiet periods.

SQL Server 2016 enhanced this mechanism by improving the lock escalation logic for low priority operations. SQL Server 2019 introduced additional telemetry for these waits in sys.dm_exec_session_wait_stats. SQL Server 2022 further optimized the lock manager's handling of low priority requests by reducing context switching overhead between priority levels.

The wait accumulates in two scenarios: when competing with user transactions holding shared or exclusive locks on the target object, or when multiple low priority operations queue behind each other. The MAX_DURATION parameter determines how long the operation waits before timing out or killing blockers based on the ABORT_AFTER_WAIT setting.

AutoDBA checks Low priority lock configuration, blocking session detection, and schema modification timing across your entire SQL Server instance in 60 seconds. Download the free diagnostic script and see what else needs attention.

Diagnostic Queries

-- Identify active low priority operations and their blocking chains
SELECT 
    s.session_id,
    r.blocking_session_id,
    r.wait_type,
    r.wait_time,
    r.resource_description,
    t.text AS current_sql,
    s.program_name
FROM sys.dm_exec_requests r
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.wait_type = 'LCK_M_IU_LOW_PRIORITY';
-- Analyze low priority wait statistics by session
SELECT 
    session_id,
    wait_type,
    waiting_tasks_count,
    wait_time_ms,
    max_wait_time_ms,
    signal_wait_time_ms
FROM sys.dm_exec_session_wait_stats
WHERE wait_type = 'LCK_M_IU_LOW_PRIORITY'
    AND session_id > 50
ORDER BY wait_time_ms DESC;
-- Examine lock requests and compatibility for low priority operations
SELECT 
    tl.resource_type,
    tl.resource_database_id,
    tl.resource_associated_entity_id,
    tl.request_mode,
    tl.request_type,
    tl.request_status,
    tl.request_session_id,
    er.command,
    er.percent_complete
FROM sys.dm_tran_locks tl
INNER JOIN sys.dm_exec_requests er ON tl.request_session_id = er.session_id
WHERE er.wait_type = 'LCK_M_IU_LOW_PRIORITY';
-- Check for long-running transactions that might block low priority operations
SELECT 
    s.session_id,
    s.login_time,
    s.last_request_start_time,
    t.transaction_id,
    t.transaction_begin_time,
    DATEDIFF(second, t.transaction_begin_time, GETDATE()) as transaction_duration_seconds,
    t.transaction_state,
    t.transaction_type
FROM sys.dm_exec_sessions s
INNER JOIN sys.dm_tran_session_transactions st ON s.session_id = st.session_id
INNER JOIN sys.dm_tran_active_transactions t ON st.transaction_id = t.transaction_id
WHERE DATEDIFF(second, t.transaction_begin_time, GETDATE()) > 300
ORDER BY transaction_duration_seconds DESC;

Fix Scripts

Terminate Low Priority Operation Safely

-- Identify and kill low priority operations that have exceeded reasonable wait time
-- WARNING: Test in development first, this will terminate running operations
DECLARE @SessionID int;
SELECT @SessionID = session_id 
FROM sys.dm_exec_requests 
WHERE wait_type = 'LCK_M_IU_LOW_PRIORITY' 
    AND wait_time > 300000; -- 5 minutes

IF @SessionID IS NOT NULL
BEGIN
    PRINT 'Terminating session ' + CAST(@SessionID AS varchar(10));
    -- KILL @SessionID; -- Uncomment after testing
END;

Adjust Low Priority Settings for Existing Operation

-- Cannot modify running operation, but can prepare improved retry
-- Example of better LOW_PRIORITY configuration
ALTER INDEX IX_YourIndex ON dbo.YourTable REBUILD
WITH (
    ONLINE = ON,
    WAIT_AT_LOW_PRIORITY (
        MAX_DURATION = 10, -- 10 minutes instead of default 0
        ABORT_AFTER_WAIT = BLOCKERS -- Kill blockers instead of self
    )
);

Identify and Terminate Blocking Sessions

-- Find sessions blocking low priority operations and optionally terminate them
-- CAUTION: Only use during maintenance windows or with business approval
SELECT DISTINCT
    blocking_session_id,
    COUNT(*) as blocked_sessions
FROM sys.dm_exec_requests 
WHERE wait_type = 'LCK_M_IU_LOW_PRIORITY'
    AND blocking_session_id != 0
GROUP BY blocking_session_id;

-- Uncomment and modify after identifying legitimate blockers to terminate
-- KILL 52; -- Example session ID

Reschedule with Optimal Low Priority Settings

-- Template for rescheduling failed low priority operations
-- Adjust MAX_DURATION and ABORT_AFTER_WAIT based on maintenance window
ALTER TABLE dbo.YourTable 
ADD CONSTRAINT CK_YourConstraint CHECK (YourColumn > 0)
WITH (
    WAIT_AT_LOW_PRIORITY (
        MAX_DURATION = 30, -- 30 minute maximum wait
        ABORT_AFTER_WAIT = SELF -- Abort this operation, not blockers
    )
);

AutoDBA generates fix scripts like these automatically, with impact estimates and rollback SQL included.

Prevention

Schedule low priority operations during maintenance windows when user activity is minimal. Configure MAX_DURATION parameters based on your maintenance window length, typically 15-60 minutes for most environments.

Use ABORT_AFTER_WAIT = BLOCKERS only during dedicated maintenance windows when terminating user sessions is acceptable. For operations during business hours, use ABORT_AFTER_WAIT = SELF to prevent disrupting user transactions.

Monitor sys.dm_exec_session_wait_stats regularly to identify patterns of excessive low priority waits. If operations consistently time out, increase MAX_DURATION or reschedule to quieter periods.

Implement connection pooling limits and query timeouts to prevent long-running user transactions from indefinitely blocking low priority operations. Consider using Resource Governor to limit concurrent long-running queries during planned maintenance.

Configure alerts when LCK_M_IU_LOW_PRIORITY waits exceed your defined thresholds, typically 10-15 minutes for most online operations. This prevents operations from waiting hours without intervention.

Need hands-on help?

Dealing with persistent lck_m_iu_low_priority issues across your environment? Samix Technology provides hands-on SQL Server performance consulting with 15+ years of production DBA experience.

Related Pages