Article planetscale.com ↗
Concurrency vs. Throughput: why more parallelism can make databases slower
Read the source ↗Key takeaways
- Little’s Law (
X = N/W): more in-flight requests only raise throughput while per-request timeWstays flat. Once each new arrival makes everyone else slower, the denominator grows with the numerator — adding concurrency reduces total throughput. - Gunther’s Universal Scalability Law: the coherency term
β·N(N−1)grows with the number of pairs of concurrent requests — double the concurrency, ~4× the mutual slowdown. PastN_max = √((1−α)/β)you get retrograde scaling. - The incident anatomy: one 15-minute uncommitted transaction + a pool that admitted 10k requests. The pile-up wasn’t lock waits — it was MVCC snapshot reads walking ever-longer version chains until the buffer pool thrashed and unrelated tables started failing.
- “Lock contention” is the wrong lens: the lock is just the junction. The damage around it — every admitted request making all others more expensive — is what scales quadratically.
- The fix was the reverse of the workaround: pool 10k → ~1k, and queue-for-slot with bounded waits instead of fail-fast errors. 60k QPS ran through fewer than 200 concurrent slots (~3ms each) with zero user-visible disruption during a 25–40k slot-req/s burst.
- Raising a limit until errors stop just hides the bottleneck. Backpressure can’t be avoided — design what happens at the gate (bounded queue) rather than letting latency accumulate inside.
- Not MySQL-specific: PgBouncer transaction pooling is the same pattern — more client concurrency than server concurrency.