运维管理18 分钟阅读
MySQLTuner 一键巡检教程:5 分钟定位 MySQL 性能瓶颈
MySQLTuner 是一款轻量级 Perl 脚本,运行一次就能全面扫描 MySQL 实例的配置、性能指标和安全隐患。本文详细讲解安装、运行、报告解读,以及如何结合 OraCheck 形成 Oracle + MySQL 双引擎巡检体系。
2026年5月6日阅读—点赞—收藏—
mysql
在知识库中专注阅读,并随时返回相关工具与课程
MySQLTuner 是一款轻量级 Perl 脚本,运行一次就能全面扫描 MySQL 实例的配置、性能指标和安全隐患。本文详细讲解安装、运行、报告解读,以及如何结合 OraCheck 形成 Oracle + MySQL 双引擎巡检体系。
如果你管理过 MySQL 数据库,一定遇到过这样的场景:线上慢查询突然增多,CPU 使用率飙到 80%,但你打开 my.cnf 看了半天也不知道该调哪个参数。这时候就需要一个"老中医"帮你把脉——MySQLTuner 就是这样一款工具。
MySQLTuner 是一个用 Perl 编写的开源脚本,托管在 GitHub 上,目前已经积累了超过 9000 个 star。它的核心思路非常简单:连接到你的 MySQL 实例,读取 SHOW GLOBAL STATUS、SHOW GLOBAL VARIABLES 等信息,然后根据内置的规则引擎给出优化建议。
它的优势在于:
一句话总结:MySQLTuner 就是 MySQL 世界的"体检报告"。
安装 MySQLTuner 有好几种方式,选最适合你环境的就行。
这是最快的方式,一条命令搞定:
1# 下载最新版本23> **本章目标**:掌握本章核心知识点4> **前置要求**:完成前序章节学习5> **预计时长**:60 分钟67wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl -O /usr/local/bin/mysqltuner.pl89# 赋予执行权限10chmod +x /usr/local/bin/mysqltuner.pl如果你的服务器无法访问 GitHub,可以先在本地下载,再通过 scp 传过去:
1scp mysqltuner.pl root@your-server:/usr/local/bin/如果你想保留完整的项目文件(包括文档、CVE 漏洞数据库等),可以 clone 整个仓库:
1git clone https://github.com/major/MySQLTuner-perl.git2cd MySQLTuner-perl3perl mysqltuner.pl这种方式的好处是可以随时 git pull 获取最新规则。
部分 Linux 发行版的官方仓库已经收录了 MySQLTuner:
1# Debian / Ubuntu2sudo apt-get install mysqltuner34# CentOS / RHEL (需要 EPEL 源)5sudo yum install epel-release6sudo yum install mysqltuner78# Arch Linux9sudo pacman -S mysqltuner注意
注意:包管理器里的版本通常比 GitHub 上的旧一些。如果你需要最新的规则和修复,建议用 wget 方式。
无论用哪种方式安装,都可以用以下命令确认:
1perl /usr/local/bin/mysqltuner.pl --help看到帮助信息就说明一切正常。
在 MySQL 所在的服务器上,直接运行:
1perl mysqltuner.pl脚本会尝试通过 socket 连接本机的 MySQL,如果当前用户有 .my.cnf 配置文件,甚至不需要输入密码。
连接远程 MySQL 或指定用户名密码:
1perl mysqltuner.pl \2 --host 192.168.1.100 \3 --port 3306 \4 --user root \5 --pass 'YourP@ssw0rd'安全提示:在命令行里直接写密码会被记录到
bash_history。生产环境建议使用--forcemem和--forceswap参数并通过.my.cnf文件传递凭据。
生产环境推荐的完整运行命令:
1perl mysqltuner.pl \2 --host 127.0.0.1 \3 --user tuner_user \4 --pass 'SecurePass123!' \5 --forcemem 16384 \6 --forceswap 8192 \7 --outputfile /var/log/mysqltuner/report_$(date +%Y%m%d).txt建议为 MySQLTuner 创建一个专用的只读账号:
1CREATE USER 'tuner_user'@'localhost' IDENTIFIED BY 'SecurePass123!';2GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO 'tuner_user'@'localhost';3FLUSH PRIVILEGES;这样既能获取足够的信息,又不会给予多余的权限。
MySQLTuner 的报告分为多个板块,每个板块用不同颜色标记状态。下面逐一讲解。
这是报告开头的部分,显示 MySQL 的版本、运行时间、连接数等基础信息:
1-------- General Statistics ------------------------------------------------2[--] Skipped version check for MySQLTuner script3[OK] Currently running supported MySQL version 8.0.364[OK] Operating on 64-bit architecture5[OK] Uptime: 45d 12h 30m (3931800 seconds)6[OK] Total connections: 15234567[OK] Avg connections per second: 0.387关注点:
1-------- Storage Engine Statistics -----------------------------------------2[--] Data in InnoDB tables: 125.6G (Tables: 342)3[--] Data in MyISAM tables: 256.0M (Tables: 15)4[OK] Total fragmented tables: 3关注点:
OPTIMIZE TABLE。这是报告的核心部分,涵盖了多个子项:
1-------- Performance Metrics -----------------------------------------------2[OK] Total buffers: 2.0G global + 16.5M per thread (151 max threads)3[OK] Query cache: disabled4[!!] Sorts requiring temporary tables: 12% (> 10%)5[!!] Joins performed without indexes: 15236[OK] Temporary tables created on disk: 5% (< 25%)7[!!] Thread cache hit rate: 85% (< 90%)关注点:
sort_buffer_size 偏小或者查询本身需要优化。thread_cache_size。1-------- InnoDB Metrics ----------------------------------------------------2[OK] InnoDB File per table: ON3[OK] InnoDB buffer pool / data size: 8.0G / 5.2G4[OK] InnoDB buffer pool hit rate: 99.8%5[!!] InnoDB log waits: 12 (> 0)6[OK] InnoDB buffer pool instances: 8关注点:
innodb_buffer_pool_size。innodb_log_file_size。1-------- Security Recommendations ------------------------------------------2[!!] User 'app_user'@'%' has wildcard host access3[!!] User 'root'@'%' has no password4[OK] No anonymous accounts found5[!!] 3 users have SUPER privilege6[!!] CVE-2024-XXXX: Upgrade to MySQL 8.0.37 or later关注点:
'%' 意味着从任意 IP 都能连接,生产环境应该限制为具体 IP 或网段。MySQLTuner 跑完以后,最常见的几个告警以及对应的解决方案如下。
告警示例:
1[!!] InnoDB buffer pool / data size: 128.0M / 12.5G2[!!] InnoDB buffer pool hit rate: 92.3% (< 95%)分析:InnoDB Buffer Pool 是 MySQL 最重要的内存区域,用来缓存数据页和索引页。如果它比你的数据量小很多,就会频繁地从磁盘读取,性能自然上不去。
修复方案:
一般建议设置为物理内存的 50%~70%(前提是这台机器专跑 MySQL):
1# /etc/mysql/mysql.conf.d/mysqld.cnf2[mysqld]3innodb_buffer_pool_size = 8G4innodb_buffer_pool_instances = 8如果你不想重启 MySQL,8.0 以上版本支持在线调整:
1SET GLOBAL innodb_buffer_pool_size = 8589934592; -- 8G小贴士:调整后观察
Innodb_buffer_pool_read_requests和Innodb_buffer_pool_reads的比值,命中率应该在 99% 以上。
告警示例:
1[!!] Table cache hit rate: 58% (1200 open / 2048 opened)分析:每次打开一个表都需要消耗文件描述符和内存。如果 cache 太小,MySQL 会频繁关闭和重新打开表,增加开销。
修复方案:
1[mysqld]2table_open_cache = 40963table_open_cache_instances = 16同时需要确保操作系统的文件描述符上限足够:
1# 查看当前限制2ulimit -n34# 临时调整5ulimit -n 6553567# 永久调整,编辑 /etc/security/limits.conf8mysql soft nofile 655359mysql hard nofile 65535告警示例:
1[!!] Slow queries log is NOT enabled.分析:慢查询日志是排查性能问题的第一手资料。不开启等于盲人摸象。
修复方案:
1[mysqld]2slow_query_log = 13slow_query_log_file = /var/log/mysql/slow.log4long_query_time = 15log_queries_not_using_indexes = 1也可以在线开启(不需要重启):
1SET GLOBAL slow_query_log = 'ON';2SET GLOBAL long_query_time = 1;3SET GLOBAL log_queries_not_using_indexes = 'ON';开启后配合 pt-query-digest 工具分析慢日志,效果更佳:
1pt-query-digest /var/log/mysql/slow.log > /tmp/slow_report.txt告警示例:
1[!!] Temporary tables created on disk: 35% (> 25%)分析:当临时表的大小超过 tmp_table_size 或 max_heap_table_size(取两者的较小值)时,MySQL 会把临时表写入磁盘,性能会显著下降。
修复方案:
1[mysqld]2tmp_table_size = 256M3max_heap_table_size = 256M注意
注意:这两个参数必须设置成一样的值,因为 MySQL 取两者的最小值作为实际上限。另外也不要设得太大——每个连接都可能分配一个临时表,连接数多的情况下可能导致内存不足。
手动跑 MySQLTuner 适合临时排查,但在生产环境中,我们更需要的是定期自动巡检。下面介绍如何用 cron 实现。
1#!/bin/bash2# /opt/scripts/mysql_inspect.sh3# MySQL 自动巡检脚本45REPORT_DIR="/var/log/mysqltuner"6DATE=$(date +%Y%m%d_%H%M)7REPORT_FILE="${REPORT_DIR}/report_${DATE}.txt"8EMAIL="dba-team@your-company.com"910# 确保目录存在11mkdir -p ${REPORT_DIR}1213# 运行 MySQLTuner14perl /usr/local/bin/mysqltuner.pl \15 --host 127.0.0.1 \16 --user tuner_user \17 --pass 'SecurePass123!' \18 --forcemem 16384 \19 --forceswap 8192 \20 --outputfile ${REPORT_FILE} \21 --nogood \22 2>&12324# 检查是否有警告项25WARNING_COUNT=$(grep -c '\[!!\]' ${REPORT_FILE})2627# 根据告警数量决定邮件主题28if [ ${WARNING_COUNT} -gt 0 ]; then29 SUBJECT="[WARNING] MySQL 巡检发现 ${WARNING_COUNT} 个问题 - $(hostname) - ${DATE}"30else31 SUBJECT="[OK] MySQL 巡检正常 - $(hostname) - ${DATE}"32fi3334# 发送邮件35mail -s "${SUBJECT}" ${EMAIL} < ${REPORT_FILE}3637# 清理 30 天前的旧报告38find ${REPORT_DIR} -name "report_*.txt" -mtime +30 -delete3940echo "[$(date)] 巡检完成,报告已保存至 ${REPORT_FILE}"别忘了加执行权限:
1chmod +x /opt/scripts/mysql_inspect.sh1# 编辑 crontab2crontab -e34# 每周一早上 6 点执行巡检50 6 * * 1 /opt/scripts/mysql_inspect.sh >> /var/log/mysqltuner/cron.log 2>&167# 如果是核心业务库,可以每天跑一次80 6 * * * /opt/scripts/mysql_inspect.sh >> /var/log/mysqltuner/cron.log 2>&1如果你有自己的监控平台(比如 Grafana + Prometheus,或者企业微信/钉钉告警),可以用 JSON 输出格式接入:
1perl mysqltuner.pl \2 --host 127.0.0.1 \3 --user tuner_user \4 --pass 'SecurePass123!' \5 --json \6 --outputfile /tmp/mysqltuner.json然后用 Python 或 shell 脚本解析 JSON,提取关键指标推送到告警系统:
1# 简单示例:提取告警数量并推送到企业微信2WARNING_COUNT=$(cat /tmp/mysqltuner.json | python3 -c "3import sys, json4data = json.load(sys.stdin)5warnings = [r for r in data.get('Recommendations', []) if 'adjust' in r.lower() or 'increase' in r.lower()]6print(len(warnings))7")89if [ "${WARNING_COUNT}" -gt 0 ]; then10 curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY" \11 -H 'Content-Type: application/json' \12 -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"MySQL巡检告警:发现 ${WARNING_COUNT} 个需要关注的项,请查看邮件报告。\"}}"13fi很多企业同时使用 Oracle 和 MySQL 两种数据库。Oracle 官方提供了一个叫 OraCheck(现在改名叫 Autonomous Health Framework / AHF)的巡检工具,和 MySQLTuner 定位类似但针对 Oracle 生态。
如果你的公司同时管理 Oracle 和 MySQL,可以这样组织巡检体系:
MySQLTuner 与 OraCheck 双引擎巡检流程
这样做的好处是:统一巡检节奏,统一告警通道,统一报告格式。DBA 团队不需要分别维护两套流程。
下面分享一个真实的生产环境案例(已脱敏),展示如何根据 MySQLTuner 的报告一步步优化 MySQL 性能。
运行 MySQLTuner 后,得到了以下告警:
1[!!] InnoDB buffer pool / data size: 2.0G / 28.5G2[!!] InnoDB buffer pool hit rate: 94.2% (< 95%)3[!!] InnoDB log waits: 156 (> 0)4[!!] Slow queries: 12% (2345 / 19523)5[!!] Sorts requiring temporary tables: 18% (> 10%)6[!!] Temporary tables created on disk: 32% (> 25%)7[!!] Table cache hit rate: 62% (512 open / 825 opened)8[!!] Thread cache hit rate: 78% (< 90%)9[!!] Slow queries log is NOT enabled.一共 8 个严重告警,问题还不少。
第一步:扩大 InnoDB Buffer Pool
数据量 28.5G,但 buffer pool 只有 2G,命中率只有 94.2%——这意味着大量数据需要从磁盘读取。
1-- 在线调整到 20G(服务器总内存 32G 的 62.5%)2SET GLOBAL innodb_buffer_pool_size = 21474836480;同时写入配置文件,防止重启丢失:
1[mysqld]2innodb_buffer_pool_size = 20G3innodb_buffer_pool_instances = 8第二步:增大 InnoDB Redo Log
156 次 log waits 说明 redo log 太小,写入繁忙时会阻塞:
1[mysqld]2innodb_log_file_size = 1G3innodb_log_files_in_group = 3注意
注意:修改 redo log 大小需要重启 MySQL。建议在低峰期操作。
第三步:开启慢查询日志并优化 SQL
1SET GLOBAL slow_query_log = 'ON';2SET GLOBAL long_query_time = 0.5;3SET GLOBAL log_queries_not_using_indexes = 'ON';开启后收集了两天的慢日志,用 pt-query-digest 分析:
1pt-query-digest /var/log/mysql/slow.log --limit 20发现排名前三的慢查询:
第四步:调整临时表和缓存参数
1[mysqld]2tmp_table_size = 256M3max_heap_table_size = 256M4table_open_cache = 40965table_open_cache_instances = 166thread_cache_size = 64一周后再次运行 MySQLTuner,对比结果如下:
所有告警清零,高峰期 RT 从 200ms 降到了 15ms。整个过程没有升级硬件,纯靠参数调优和 SQL 优化。
MySQLTuner 是每个 MySQL DBA 工具箱里应该有的工具。总结几个关键建议:
max_connections,但真正该做的是引入连接池。EXPLAIN 执行计划、SHOW ENGINE INNODB STATUS 等手段深入排查。最后,附上几个有用的链接:
希望这篇教程对你有帮助。如果你的 MySQL 服务器也有性能问题,不妨现在就跑一次 MySQLTuner 试试吧。
本章介绍了以下核心内容: