IL-0441 ZOZO · 2021-03-04 (published)database
A ZOZO SQL Server database stalled and applications hit timeout storms whenever batch executions peaked in sales
ZOZO investigated the failure with three sources: SQL Server metrics from Performance Monitor, the blocked_process_report extended event, and DMV (dynamic management view) data saved to a table every minute. The metrics only showed that queries piled up for some reason until the worker threads ran out and timeouts followed. Possible reasons considered were SOS_SCHEDULER_YIELD waits from high CPU, non-page latch contention, and long locks on a busy area causing blocking. The latch data suggested that ACCESS_METHODS_HOBT_VIRTUAL_ROOT waits might come from many last-page inserts into one table, and that ACCESS_METHODS_ACCESSOR_CACHE waits rise with compilations. ZOZO did not find a definite root cause.
Instead, ZOZO looked for things observed during the failure that could be removed or reduced. When the failure happened again on another day, counting blocked_process_report events by waitresource showed blocking caused by waits for the compilation of specific stored procedures, so ZOZO fixed the plan guides of those four stored procedures. Compilations and recompilations were also reduced: the sql_statement_recompile extended event showed that the recompile_cause of most recompilations was "Statistics changed". ZOZO listed the tables whose statistics were updated during the failure window, disabled automatic statistics updates on them only for periods of expected high traffic with `UPDATE STATISTICS tablename WITH NORECOMPUTE`, and enabled them again with `UPDATE STATISTICS tablename` once traffic calmed down. Because plan cache evictions are controlled by SQL Server's memory management, ZOZO compressed the large indexes held in the data cache as a best-effort step.
After these measures the failure stopped. With the same rise in batch executions, queries no longer piled up, connections stayed low, errors disappeared, peak CPU fell from close to 100% to about 60%, compilations and recompilations dropped clearly, and no lock contention was seen even at the highest batch rate. ZOZO's hypothesis for the drop in compilations is that compression shrank the data cache, which stabilised the plan cache.
- Severity
- –
- Scope
- Applications using one SQL Server database got many timeout errors during traffic peaks
- Users affected
- –
- Region
- –
- Time to detect
- –
- Time to resolve
- –
Symptoms
From around mid-2020, a SQL Server database behind one ZOZO feature made the applications throw many timeout errors whenever batch executions per second passed a certain threshold.
Traffic rises at events such as sales and lucky-bag (fukubukuro) launches. A batch in SQL Server is a group of one or more queries. At the moment the errors began, batch executions per second dropped sharply while total batch execution time rose steeply, so each query was taking much longer.
The Performance Monitor metrics for SQL Server showed CPU usage close to 100% at the peak, driven mainly by batches using 20 to 100 msec of CPU in Batch Resp Statistics. They also showed blocking, errors on the SQL Server side, a spike of non-page latch waits early in the failure, compilations rising with batch executions, more queries granted workspace memory, and many waits to obtain a worker thread, which suggested the worker threads had run out.
Looking at a shorter time window around the start of the errors, CPU usage fell when the Attention events appeared, so CPU was unlikely to be the cause. The first changes were Page Latch, then Non-Page Latch, then blocking. In the blocked_process_report extended event, the first blocking event was recorded about 15 seconds after the failure began, because the event is only written after blocking passes a threshold; the first blocker was a background process that was itself waiting on a latch of type ACCESS_METHODS_HOBT_VIRTUAL_ROOT, and what it was doing could not be found. The DMV data showed no CPU-heavy query worth tuning; the largest total latch waits were ACCESS_METHODS_ACCESSOR_CACHE, then BUFFER, then ACCESS_METHODS_HOBT_VIRTUAL_ROOT, and apart from the secondary THREADPOOL wait most waiting time was non-page latches, page latches and locks.
Symptom Intermittent timeoutsDatabase overloadLock contention or deadlock
Root cause
- Trigger
- Traffic increases during sales and lucky-bag launches pushed batch executions per second on the database above a threshold.
Detection
–
Remediation
- Fixed the plan guides of the four stored procedures whose compilation waits caused blocking
- Disabled automatic statistics updates on the affected tables during periods of expected high traffic
- Enabled automatic statistics updates again once traffic calmed down
- Compressed the large indexes held in the data cache to use memory more efficiently
Action items
–
Lessons
When the root cause of a failure cannot be found, choosing among the things observed during the failure those that can be removed or reduced, and acting on them, can still create a state in which the failure no longer happens.
Sources
Related cases
IL-0545Wasabi API calls in all regions returned HTTP 5XX when the message queue stopped spreading requests over database nodesWasabi · 2024same root cause · shared Database
IL-0335A bugcheck in the primary SQL Server put the Stack Exchange network into read-only mode and then offline for 12 minutesStack Exchange · 2017same root cause · shared Database
IL-0387Mailgun MongoDB secondaries were overloaded by rising connections, and a rollback then moved reads onto the primary tooMailgun · 2017same root cause · shared Database
IL-0393Load on the BBC programme metadata database surged and metadata requests failed, leaving BBC iPlayer down over a weekendBBC · 2014same root cause · shared Database
Check your cluster for this
For AI tools and scripts
- This case as JSON: https://incidentlib-api.benchlet.com/cases/IL-0441
- The cases most like it: https://incidentlib-api.benchlet.com/cases/IL-0441/similar
- MCP server (Streamable HTTP, no key):
https://incidentlib-mcp.benchlet.com/mcp
The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.