LCK_M_RS_S is a wait to acquire a Range Shared lock: a shared lock on a key value plus a shared lock on the range between it and the previous key. Range locks only exist under SERIALIZABLE isolation, where SQL Server must prevent phantom rows from appearing in a range a transaction has read.
Seeing this wait tells you two things at once: something is running under serializable isolation, and it is being blocked while trying to lock a key range.
Is It a Problem?
Range lock waits deserve attention because most workloads never intend to use serializable isolation in the first place. It gets switched on silently by distributed transactions (MSDTC promotes to serializable by default), by some ORM and framework defaults, and by HOLDLOCK hints. Serializable range locks block a much wider surface than plain row locks, so blocking and deadlocks climb sharply once they appear.
If your application genuinely requires serializable semantics, some LCK_M_RS_S is the price of correctness. The question is whether the isolation level is deliberate.
Common Causes
- Distributed transactions or linked-server activity defaulting to serializable.
- Application code or connection strings setting
SERIALIZABLE, sometimes inherited via connection pooling when a previous user of the connection changed the level. HOLDLOCKtable hints in old stored procedures.- Range scans under serializable on columns without a supporting index, which locks far more range than intended.
What To Do
- Confirm who is using serializable:
sys.dm_exec_sessions.transaction_isolation_level = 4. Trace it back to the application or job. - If it is unintentional, fix the source, the ORM setting, the DTC usage, or the hint. Most workloads are fine with
READ COMMITTEDor snapshot-based isolation. - If serializable is required, index the predicate columns so range locks stay narrow, and keep those transactions short.
- Watch for connection pool leakage. Reset the isolation level explicitly on connection open, or use
sp_reset_connection-safe drivers (modern ones reset by default).
How To See It
Rank it against everything else with Get-WaitStatistics. If LCK_M_RS_S or other LCK_M_R* waits register at all, audit isolation levels before anything else.
Part of the SQL Server Wait Types Library.
Related deep dive: LCK_M_X, LCK_M_S, and LCK_M_U Wait Types.
Leave a Reply