mysql性能优化需关注四大陷阱:慢查询日志必须开启(slow_query_log=on)、innodb缓冲池勿超系统内存合理阈值、废弃查询缓存(query_cache_type已移除)、tmp_table_size与max_heap_table_size须设为相同值。

MySQL慢查询没开,slow_query_log 一关就掉坑里
很多线上服务明明CPU、IO都不高,但SQL响应忽快忽慢,根本原因常是慢查询日志默认关闭,连问题都发现不了。不打开它,后续所有优化都是蒙眼摸象。
实操建议:
-
slow_query_log = ON必须设为ON(不是1或TRUE,MySQL 8.0+ 严格认字符串) -
long_query_time = 0.5比默认的10更实用——多数Web接口超500ms就该预警 -
log_output = TABLE比FILE更安全:避免日志文件权限失控或磁盘写满,查起来也快(SELECT * FROM mysql.slow_log LIMIT 5) - 别漏掉
log_queries_not_using_indexes = ON,但上线后要关——它会把全表扫描的WHERE条件全记下来,日志爆炸式增长
innodb_buffer_pool_size 设太大,Linux直接OOM kill mysqld
看到“内存越大越好”,就把 innodb_buffer_pool_size 设成物理内存的80%,结果MySQL跑半天被系统干掉。Linux内核在内存紧张时优先杀占用RSS最大的进程,而InnoDB Buffer Pool正是mysqld的RSS主力。
实操建议:
- 单机MySQL + 其他服务(如Nginx、PHP-FPM)共存时,
innodb_buffer_pool_size最多设为总内存的50%~60% - 纯数据库服务器可到75%,但必须留至少2GB给OS缓存和tmpfs(比如
/tmp、/var/run/mysqld) - 用
free -h和cat /proc/meminfo | grep -i "memavailable"看真实可用内存,别信MemFree - 改完重启MySQL前,先跑
mysql -e "SHOW ENGINE INNODB STATUS\G" | grep "Buffer pool"确认当前实际使用量
query_cache_type 还开着?MySQL 5.7已弃用,8.0直接删了
配置文件里还留着 query_cache_type = 1 和 query_cache_size = 64M?这不仅是无效配置,还会拖慢高并发写入——每次UPDATE/INSERT都要清空整个Query Cache,锁竞争严重。
实操建议:
- MySQL 5.7 起默认
query_cache_type = OFF,强行开只会增加开销;8.0 版本已移除所有相关变量,启动会报错 - 替代方案不是“换缓存”,而是用应用层缓存(Redis)或连接池预编译(
PREPARE+EXECUTE)减少解析开销 - 如果真要用查询结果缓存,确认客户端是否支持
SQL_CACHE提示(现在基本都不支持了)
tmp_table_size 和 max_heap_table_size 不配对,GROUP BY瞬间变磁盘临时表
执行一个带 GROUP BY 的报表SQL,EXPLAIN 显示 Using temporary; Using filesort,但 Created_tmp_disk_tables 计数狂涨——问题往往出在这俩参数没设一样大。
实操建议:
-
tmp_table_size和max_heap_table_size必须设为相同值(如都设64M),否则以较小者为准 - 临时表超过这个值,InnoDB就强制落盘到
/tmp或tmpdir,IO暴增;尤其注意tmpdir别挂在根分区,最好用独立SSD或tmpfs - 查当前使用情况:
SHOW GLOBAL STATUS LIKE 'Created_tmp%';,重点盯Created_tmp_disk_tables/Created_tmp_tables比值,超10%就得调
MySQL性能优化最麻烦的从来不是参数本身,而是每个值都得和你的硬件、负载模式、甚至其他进程抢内存的现实绑在一起。改一个参数前,先看 SHOW GLOBAL STATUS 里对应指标的实际变化,比背文档管用得多。










