先看缓冲池命中率再调innodb_buffer_pool_size,低于95%才需调大;设太高触发swap比设太低更伤性能;刚重启时80%+命中率属正常预热,应等待10–15分钟后再评估。

直接结论:别一上来就调 innodb_buffer_pool_size,先看缓冲池命中率;值设太高会触发 swap,比设太低更伤性能。
怎么看缓冲池是否够用?
命中率低于 95% 才真该调大,不是“内存多就堆”。SHOW ENGINE INNODB STATUS 输出里找 Buffer pool hit rate,或者用这个查询:
SELECT (1 - (VARIABLE_VALUE / (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests'))) * 100 AS hit_ratio FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads';
常见错误现象:刚重启 MySQL 就看到命中率只有 80% 多——这是正常预热过程,不是配置问题。等 10–15 分钟再查。
- 命中率持续
- 命中率 > 99.5% 但仍有大量
Pages written/s:可能是写入压力大,需关注innodb_log_file_size和innodb_io_capacity - 系统
free -h显示可用内存极少,且si/so(swap in/out)非零:说明innodb_buffer_pool_size已超限,必须下调
日志文件大小怎么设才不翻车?
innodb_log_file_size 不是越大越好,也不是越小越安全。它和你的最大事务体积、写入吞吐强相关。设错的典型后果是:Innodb_log_waits 持续上升,事务提交变慢。
查当前等待次数:SHOW GLOBAL STATUS LIKE 'Innodb_log_waits';,只要非零就得调。
- SSD + 写密集业务(如订单、日志):单个日志文件建议 256M–1G,
innodb_log_files_in_group = 3 - HDD 或读多写少:128M–256M 足够,
innodb_log_files_in_group = 2更稳妥 - 改这个参数必须停库:先
SET GLOBAL innodb_fast_shutdown = 0,再关 mysqld,删旧ib_logfile*,再启服务
innodb_flush_log_at_trx_commit 到底该选 0、1 还是 2?
这不是性能“开关”,而是数据持久性分级开关。选错的代价不是慢,是丢数据。
- 值 = 1:每次
COMMIT都强制刷盘。金融、支付类系统唯一合法选项;HDD 上延迟可能达 20ms+,SSD 上约 1–2ms - 值 = 2:日志写进 OS page cache,由 OS 异步刷盘。能扛住 mysqld 崩溃,但扛不住服务器断电;适合后台任务、分析型写入
- 值 = 0:每秒刷一次,崩溃可能丢 1 秒数据。仅限日志采集、埋点等可丢数据场景;千万别在核心业务上试
注意:sync_binlog 必须和它对齐。比如设了 innodb_flush_log_at_trx_commit = 1,但 sync_binlog = 0,主从一致性就不可靠。
容易被忽略的并发细节
innodb_buffer_pool_instances 在缓冲池 > 1GB 时必须设,否则所有线程抢同一把锁。默认是 8,但如果你的 innodb_buffer_pool_size 是 4GB,就该设成 4(即每实例 1GB),而不是硬套 8。
另一个隐形瓶颈是 innodb_io_capacity:它告诉 InnoDB 你的磁盘“每秒能干多少活”。SSD 不设就是按 200 算,严重低估;建议实测 fio 后填真实 IOPS 值(如 NVMe 盘填 3000–10000)。
最后提醒一句:所有调整都要配合监控。没开 performance_schema 或没接 Prometheus + Grafana,调参就是蒙眼开车。











