Understanding Long Sync IO in SQL Server: Scheduler in Nonpreemptive Mode Longer Than 1000 ms
Compatibility: This warning and the troubleshooting approach apply to SQL Server 2012 and later. There are no version-specific changes to this behavior in SQL Server 2025. The message, the underlying mechanics, and the diagnostic steps are the same across all supported versions. For the Always On AG-specific impact of these warnings see the SQLYARD article on Error 833 and Long Sync IO in Always On.
One of the more concerning messages in the SQL Server error log is:
This message often appears alongside blocking complaints, slow performance, or application timeouts and commonly raises the question: is this a storage issue or a code issue?
The short answer is that the message confirms a serious I/O stall occurred but does not identify the root cause. In many environments, especially after a deployment or data growth event, this warning can become part of the system’s new steady state. Understanding what it means and how to diagnose it is what this article covers.
What the Message Actually Means
This warning indicates that a SQL Server worker thread issued a synchronous I/O request and waited longer than 1,000 milliseconds for the operating system to complete it. SQL Server logs the message as a signal that its I/O subsystem is experiencing stalls well beyond what normal operation should produce. The target context switch time for a SQL Server scheduler is around 4 ms, making 1,000 ms a significant overshoot.
- The I/O is synchronous: the thread is blocked, not asynchronously waiting in the background
- The thread is in nonpreemptive mode: SQL Server cannot interrupt it or yield to other work
- The scheduler is effectively stalled: no other work can be dispatched on that scheduler while it waits
- Other sessions pile up: any work queued behind that scheduler must wait until the I/O completes
- This is not a wait statistic: it is a safety warning written to the error log when SQL Server detects an abnormally long kernel-level wait
Never ignore Long Sync IO messages. They confirm that real I/O stalls occurred and that the SQL Server scheduler was disrupted. The message does not explain why, but the fact that it appeared is not negotiable. Something took over a second to complete an I/O that should complete in single-digit milliseconds.
Why Nonpreemptive Mode Matters
SQL Server uses cooperative scheduling, not preemptive OS scheduling. Worker threads normally yield voluntarily so other threads can run. Nonpreemptive mode is an exception: it occurs when a worker executes code that directly calls the operating system, such as reading or writing a file. While in this state:
- SQL Server cannot interrupt the thread; it must wait for the OS call to return
- The scheduler cannot dispatch other work: the owned scheduler is frozen
- Blocking chains grow quickly: sessions waiting for locks behind that scheduler keep accumulating
- The effect is multiplied under load; a single stalled scheduler on a busy server can back up dozens of waiting sessions
This is by design. SQL Server must make synchronous OS calls for certain I/O operations. But it is also why a storage subsystem that is merely slow can produce blocking symptoms that look far more severe than the latency numbers alone would suggest.
Blocking vs I/O: How They Amplify Each Other
Blocking and I/O slowness are related but not the same thing. Understanding the relationship is critical for diagnosing these symptoms correctly.
- Blocking occurs when sessions wait on locks held by other sessions
- I/O delays extend the duration of transactions: a transaction that writes slowly holds its locks for longer
- Longer lock hold times mean blocking becomes more severe and more visible to end users
- Slow I/O does not usually cause blocking directly; it amplifies it by extending transaction lifetime
Long Sync IO messages often appear at exactly the same time as blocking complaints even though the blocking itself is lock-based. The I/O slowness is not the lock holder; it is the reason the lock holder is taking so long to finish its work. Fix the I/O and the blocking often resolves itself.
PAGEIOLATCH_* waits represent time spent waiting for physical data page reads from disk. WRITELOG waits represent time spent waiting for transaction log I/O to complete. Both contribute to extended transaction durations and therefore extended lock hold times.
Is This Code or Storage?
The correct answer is often both, but not equally. The distinction matters because the fix is different in each case.
Storage Is More Likely the Driver When
- OS or SAN latency is consistently above SLA thresholds
- Storage queue depth is persistently saturated
- Multiple systems on the same storage show the same symptoms
- The issue occurs independently of workload changes
- Latency is elevated even during off-peak periods
Code or Workload Is More Likely the Driver When
- A recent deployment increased write volume
- New data loads increased transaction size or frequency
- Index usage changed from seek to scan
- Logging pressure increased after a schema change
- Transactions became longer or less efficient
When Long Sync IO messages continue to appear weeks after a permanent code or load change, the question is no longer what changed; it is whether the platform can sustain the new steady workload. At that point two paths lead to different remediation choices:
If Storage Latency Is Within Acceptable Limits
- Reduce I/O demand through query optimization
- Improve index coverage to reduce scan-based reads
- Reduce transaction scope or split large batch operations
- Review logging pressure: minimize unnecessary writes
If Storage Latency Exceeds Acceptable Limits
- Increase storage throughput or IOPS allocation
- Move the transaction log to a dedicated faster volume
- Review backup, snapshot, and maintenance overlap
- Consider NVMe or dedicated log disk for write-heavy workloads
The error log message alone cannot choose the fix. Metrics are needed: SQL Server I/O latency figures, OS-level disk counters, and storage queue depth. These are needed before deciding whether to optimize the workload or upgrade the storage. Acting without data leads to changes that solve nothing.
Additional Cause: Idle Sessions Holding Open Transactions
A less obvious contributor to Long Sync IO symptoms is sessions that are idle but holding an open transaction. These sessions are not actively running. They appear quiet in sys.dm_exec_requests but they are keeping transactions open. Other sessions pile up behind those held locks, and the blocked work continues generating WRITELOG waits and I/O pressure as it retries or queues.
Common causes include a missing COMMIT or ROLLBACK, a user who opened a transaction and walked away, or connection pooling holding a transaction open longer than intended.
Check for Open Transactions
-- Confirm open transactions exist on the instance
DBCC OPENTRAN;
Find Idle Sessions with Open Transactions
SELECT
s.session_id,
s.login_name,
s.host_name,
s.program_name,
s.status,
r.blocking_session_id,
at.transaction_begin_time,
DATEDIFF(MINUTE, at.transaction_begin_time, GETDATE()) AS tran_age_min,
t.text AS last_sql_text
FROM sys.dm_exec_sessions s
LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
LEFT JOIN sys.dm_tran_session_transactions st ON s.session_id = st.session_id
LEFT JOIN sys.dm_tran_active_transactions at ON st.transaction_id = at.transaction_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1
AND at.transaction_begin_time IS NOT NULL
ORDER BY tran_age_min DESC;
status = 'sleeping' and a large tran_age_min value are holding open transactions without doing active work. Any session idle for several minutes with an uncommitted transaction is a candidate for investigation. The fix is almost always application-side: ensure every transaction is committed or rolled back promptly, and avoid wrapping multiple statements in an explicit transaction unless absolutely necessary.
Workshop: Classifying Long Sync IO in a Steady Load System
Goal: Determine whether continued Long Sync IO events indicate a workload capacity problem, a storage capacity problem, or idle sessions amplifying I/O pressure so the right fix can be applied.
This walkthrough assumes the Long Sync IO messages continue to appear, the code and data load are now permanent, and the question is whether the system can sustain the new load.
Capture Timestamps of Long Sync IO Messages
Start with the error log. The time window they cluster in is what every subsequent step uses for correlation.
-- Read Long Sync IO messages from the current error log
EXEC sys.xp_readerrorlog 0, 1, 'Long Sync IO';
-- Read from the previous error log (after a restart)
EXEC sys.xp_readerrorlog 1, 1, 'Long Sync IO';
Check Average I/O Latency Inside SQL Server
Run this during or immediately after the problem window. This is SQL Server’s own view of storage performance, which is the most direct evidence of whether I/O is slow from the database engine’s perspective.
-- File-level I/O latency from SQL Server's perspective
SELECT
DB_NAME(vfs.database_id) AS database_name,
mf.name AS file_name,
mf.type_desc,
vfs.num_of_reads,
vfs.io_stall_read_ms / NULLIF(vfs.num_of_reads, 0) AS avg_read_ms,
vfs.num_of_writes,
vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes, 0) AS avg_write_ms,
vfs.io_stall_read_ms + vfs.io_stall_write_ms AS total_io_stall_ms
FROM sys.dm_io_virtual_file_stats(NULL, NULL) vfs
JOIN sys.master_files mf
ON vfs.database_id = mf.database_id
AND vfs.file_id = mf.file_id
ORDER BY total_io_stall_ms DESC;
A concrete example of what concerning output looks like:
| Database | File Name | Type | avg_read_ms | avg_write_ms |
|---|---|---|---|---|
| tempdb | tempdev | ROWS | 85 | 30 |
| Sales | sales_log | LOG | 2 | 114 |
| Orders | orders_data | ROWS | 22 | 4 |
In this example TempDB is read-heavy and underperforming, likely on slow or shared storage. The Sales log at 114 ms write latency is the most urgent: transaction log writes at that latency will produce WRITELOG waits and extend every transaction’s commit time. Move TempDB to SSD or a separate LUN. Move the Sales log file to dedicated fast storage and enable Instant File Initialization to reduce growth stall duration.
Identify Dominant Wait Types
This confirms whether SQL Server is primarily waiting on data file reads or transaction log writes.
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
wait_time_ms / NULLIF(waiting_tasks_count, 0) AS avg_wait_ms
FROM sys.dm_os_wait_stats
WHERE wait_type LIKE 'PAGEIOLATCH%'
OR wait_type = 'WRITELOG'
OR wait_type = 'ASYNC_IO_COMPLETION'
ORDER BY wait_time_ms DESC;
WRITELOGdominating: transaction log write pressure. Focus on the LDF file, logging volume, and transaction batch sizes.PAGEIOLATCH_SHorPAGEIOLATCH_EXdominating: data file read pressure. Focus on MDF/NDF files, missing indexes, and scan-heavy queries.ASYNC_IO_COMPLETIONelevated: backup or large file operation overlap with peak workload.- High
avg_wait_msconfirms sustained pressure rather than rare spikes.
Check for Idle Sessions Holding Open Transactions
Before correlating with blocking, rule out idle sessions with open transactions. These are invisible to standard blocking queries but are often the real amplifier.
DBCC OPENTRAN;
SELECT
s.session_id,
s.login_name,
s.host_name,
s.program_name,
s.status,
r.blocking_session_id,
at.transaction_begin_time,
DATEDIFF(MINUTE, at.transaction_begin_time, GETDATE()) AS tran_age_min,
t.text AS last_sql_text
FROM sys.dm_exec_sessions s
LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
LEFT JOIN sys.dm_tran_session_transactions st ON s.session_id = st.session_id
LEFT JOIN sys.dm_tran_active_transactions at ON st.transaction_id = at.transaction_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1
AND at.transaction_begin_time IS NOT NULL
ORDER BY tran_age_min DESC;
status = 'sleeping' and a tran_age_min of more than 1 to 2 minutes holding an open transaction is a problem. While that session sits idle, its held locks are forcing other sessions to wait. That wait generates continued I/O pressure as blocked sessions retry. The fix is application-side: ensure transactions are committed or rolled back promptly and are never left open waiting for user input or external calls.
Correlate Active Blocking with I/O Stalls
Run this during the problem window to identify what is actively blocking and whether it ties back to the I/O wait types identified in Step 3.
SELECT
r.session_id,
r.blocking_session_id,
r.wait_type,
r.wait_time / 1000.0 AS wait_time_sec,
r.status,
r.command,
t.text AS sql_text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.blocking_session_id <> 0
ORDER BY r.wait_time DESC;
wait_type values of WRITELOG or PAGEIOLATCH_* on blocked sessions confirm the I/O connection. If blocking aligns with the same time window as Long Sync IO messages, slow I/O is directly extending lock hold time and amplifying the blocking chain.
Validate Storage Metrics Externally
SQL Server has confirmed when the problem occurs, what type of I/O is slow, and that blocking is being extended. The final question is whether storage is underperforming or simply being asked to do more than it was sized for.
Ask the infrastructure or storage team for the following metrics covering the same time window identified in Step 1:
- Disk latency at the OS or SAN level: compare to SQL Server’s view from Step 2
- Storage queue depth: elevated queue depth during the window confirms saturation
- Competing activity: backup jobs, snapshots, or compression running during peak hours
- Firmware and driver versions: outdated HBA or RAID controller firmware is a surprisingly common cause
Two hidden causes worth checking before escalating to storage: First, confirm antivirus software excludes all SQL Server data, log, and backup files (*.mdf, *.ndf, *.ldf, *.bak) and the TempDB path. Real-time scanning of these files during peak workload directly causes I/O stalls that surface as Long Sync IO warnings. Second, on VMware or Hyper-V confirm the virtual disk controller is PVSCSI (VMware) or SCSI (Hyper-V), and that the host is not overcommitted on storage. Hypervisor-level latency can be invisible to SQL Server DMVs but fully visible in host-level counters.
- Latency within SLA: storage is meeting targets, workload must be optimized. Reduce I/O demand through query tuning, index improvements, and smaller transaction batches.
- Latency outside SLA: storage capacity must be addressed. The workload has grown beyond what the current storage tier can sustain. Increase IOPS, move log files to dedicated faster storage, or split I/O across additional volumes.
Workshop Outcome
By completing this walkthrough, the following statements should be supportable with evidence behind each one:
- Long Sync IO is real and recurring, confirmed from the error log with specific timestamps
- It aligns with a specific time window, correlated to business hours or known peak load periods
- It is driven by read pressure, write pressure, or both, identified from wait stats
- Idle sessions are or are not contributing, confirmed with DBCC OPENTRAN and transaction age query
- Active blocking is or is not being amplified by the I/O stalls, confirmed from dm_exec_requests during the window
- Storage is or is not meeting latency targets, confirmed from infrastructure metrics
- The fix path is workload optimization or storage capacity, a decision based on data, not guesswork
Final Thoughts
Long Sync IO warnings are serious but not self-diagnosing. They confirm that SQL Server waited far longer than expected on synchronous I/O, but they do not explain why. That answer comes from correlating the error log timestamps with file-level latency metrics, wait statistics, active blocking data, and external storage counters.
When code and data loads become permanent, continued messages mean the system is operating near or beyond its I/O capacity. At that point the choice is clear: reduce I/O demand, increase I/O capacity, or fix the application-level transaction patterns that are holding locks far longer than necessary.
Treat Long Sync IO warnings as signals to investigate, not background noise to acknowledge and move on from. Every one of those messages represents a scheduler stall that affected concurrency and extended every transaction running behind it during that second.
References
- Microsoft Docs: SQL Server I/O Subsystem Requirements and Storage Architecture
- Microsoft Docs: SQL Server Thread and Task Architecture Guide
- Microsoft Docs: sys.dm_io_virtual_file_stats
- Microsoft Docs: sys.dm_os_wait_stats
- Microsoft SQL Server Team: How It Works: Sync IOs in Nonpreemptive Mode Longer Than 1000 ms
- Microsoft Docs: sys.dm_exec_requests
- Microsoft Docs: sys.dm_tran_active_transactions
- SQLYARD: SQL Server Error 833 and Long Sync IO in Always On Availability Groups
- SQLYARD: When SQL Server Is Slow: Triage Playbook
Discover more from SQLYARD
Subscribe to get the latest posts sent to your email.


