innodb_thread_concurrency = 0 是多数场景的正确答案,表示启用InnoDB自适应线程调度,动态优化并发执行;仅当INNODB STATUS持续显示“Number of threads waiting in InnoDB queue”>5、CPU长期低于20%且已排除锁与IO瓶颈时,才考虑设为非零值。

innodb_thread_concurrency = 0 是多数场景的正确答案
MySQL 5.7 默认就是 innodb_thread_concurrency = 0,这不是“没设”,而是明确启用自适应线程调度。它会根据 CPU 核数、当前负载、IO 延迟动态调整真正进入 InnoDB 内核执行的线程数,比人为固定一个值更稳。你看到大量 Lock wait timeout exceeded 错误时,90% 以上不是这个参数的问题,而是事务锁等待本身——比如长事务未提交、缺失索引导致锁升级、或间隙锁冲突。
什么时候才该调非零值?看 INNODB STATUS 的硬指标
只有同时满足以下全部条件,才考虑设为非零(如 16 或 CPU核心数 × 2):
-
SHOW ENGINE INNODB STATUS\G中反复出现Number of threads waiting in InnoDB queue,且数值持续 > 5 - CPU 利用率长期低于 20%,但 QPS 却很高,响应延迟明显上升
-
SHOW PROCESSLIST里大量线程状态是executing(不是Locked),实际没做多少事 - 已排除锁问题:
SELECT * FROM information_schema.INNODB_TRX没有超 10 秒的活跃事务;INNODB_LOCK_WAITS为空;慢查询日志里没有高频 UPDATE/DELETE
不满足就别动——设成 4 或 8 反而会让简单主键查询变慢,因为线程全堵在 FIFO 队列里空转。
动态调整后为什么没立刻生效?连接池要配合重启
SET GLOBAL innodb_thread_concurrency = 16 立即生效,但只对新建立的连接起作用。已存在的活跃连接不受影响,也不会中断当前 SQL 执行。这意味着:
- 应用层必须触发连接池(如 HikariCP)重建连接,旧连接自然断开后才能体现效果
- 如果应用没配置连接最大生命周期(
maxLifetime)或空闲驱逐(idleTimeout),可能要等几十分钟甚至几小时 - 临时验证可用
SET SESSION innodb_concurrency_tickets = 100加速暴露排队行为,但仅限诊断,切勿上线
别指望改完参数立刻看到 TPS 上升——它不控制锁,也不加速 SQL,只调节线程进内核的节奏。真正的瓶颈往往在 SQL 本身、索引设计或事务边界。
容易被忽略的副作用:thread_sleep_delay 和 adaptive 调度失效
一旦设为 0,innodb_thread_sleep_delay 参数自动失效,无需额外处理。但如果你设了非零值,就得注意 innodb_adaptive_max_sleep_delay 的配合——MySQL 5.6+ 会基于当前负载自动调节休眠时长,避免手动调 innodb_thread_sleep_delay 的试错成本。
另外,绝对不要把 innodb_thread_concurrency 和过时的 thread_concurrency 混淆,后者在 Linux 上早已不生效,查到也别碰。


















