innodb_spin_wait_delay实际控制每次自旋循环中PAUSE指令的数量上限,其值决定随机选取的PAUSE次数范围(0到该值减1),再乘以pause_multiplier,默认生成0/50/100/150/200/250次PAUSE,而非直接设定微秒级等待时间。

别调,除非你已经确认 lock_mutex 或 rw_lock 的平均等待时间超过 1ms,且 CPU 使用率偏低、TPS 明显卡在锁竞争上。
innodb_spin_wait_delay 实际控制的是什么?
它不直接设“等待多少微秒”,而是决定每次自旋循环中插入的 PAUSE 指令数量上限。InnoDB 会从 0 到 innodb_spin_wait_delay - 1 中随机选一个整数,再乘以 innodb_spin_wait_pause_multiplier(默认 50),得到本次自旋要执行的 PAUSE 次数。
例如:innodb_spin_wait_delay=6 → 随机值 ∈ {0,1,2,3,4,5} → PAUSE 次数 ∈ {0,50,100,150,200,250}。
-
PAUSE是 CPU 级指令,不是 sleep,线程不放弃 CPU,但功耗和流水线干扰比空循环小 - Skylake 及更新 CPU 上,单次
PAUSE持续时间被拉长(约 140 cycles),等效于自旋变“慢”了 - 所以同样设为 6,在老 CPU 和 Skylake 上,实际自旋时长可能差 2–3 倍
什么时候调大 innodb_spin_wait_delay 反而更慢?
当锁持有时间极短(比如
- 典型现象:
show engine innodb status中Spin rounds per wait很高(>100),但OS waits并没减少 - 监控指标:
performance_schema.data_lock_waits中LOCK_TRX_ID频繁切换,lock_mutex平均等待时间跳变剧烈 - sysbench 测试中,
innodb_spin_wait_delay=180比=1吞吐量低 30% 以上(见 2019 年实测数据)
为什么 innodb_spin_wait_delay=0 不等于禁用自旋?
设为 0 仅表示“不插入任何 PAUSE”,但 InnoDB 仍会执行至少一次原子检查(test-and-set),并立即 fallback 到 mutex sleep。这会导致:
- 所有锁等待都走系统调用路径,上下文切换开销陡增
- 在低并发、锁粒度细(如单行更新)场景下,TPS 可能比默认值 6 还低 15–20%
- MySQL 5.5 测试明确显示:
innodb_spin_wait_delay=0时 TPS 最低,=6时最优
真正关键的判断点不在参数本身,而在 performance_schema.events_waits_summary_global_by_event_name 里 wait/synch/mutex/innodb/lock_mutex 的 AVERAGE_TIMER_WAIT —— 如果它长期高于 10⁶ cycles(≈ 0.4ms),且占 SQL 总耗时 >5%,才值得尝试微调;否则,默认值 6 就是经过多代硬件验证的平衡点。


















