上线mysql前必须验证版本兼容、配置生效、权限最小化、日志可写四项硬性条件:执行select version()确认运行时版本与应用文档要求一致;用show variables验证my.cnf关键参数如innodb_buffer_pool_size、wait_timeout是否真实生效;通过select user,host和show grants确保线上用户权限精确到库+ip且不含高危权限;检查slow_query_log=on、log_error路径可写且tail -f能实时捕获ready for connections日志。

上线 MySQL 项目前,必须验证四个硬性条件:版本兼容、配置生效、权限最小化、日志可写。缺一不可,否则上线后大概率凌晨被叫醒处理连接中断或查询失败。
确认 MySQL 版本与应用真实兼容
很多故障不是代码问题,而是版本特性错配。比如应用用了 JSON_CONTAINS 函数,却部署在 MySQL 5.6 —— 这个函数从 5.7.8 才支持。
- 别信安装包名,执行
SELECT VERSION();查运行时版本 - 翻应用文档,重点看“最低支持版本”和“已知不兼容小版本”,例如 8.0.22 修复了
GROUP BY在严格模式下的解析 bug - 用 Docker 的话,
mysql:8.0这类 tag 不稳定,建议锁定为mysql:8.0.34(当前最新 patch 版) - 本地能跑 ≠ 线上能跑:检查
sql_mode是否含STRICT_TRANS_TABLES,旧版默认关闭,新版默认开启
验证 my.cnf 关键参数是否真正生效
改完配置文件不等于配置就生效了。MySQL 启动时可能加载了别的配置路径,或被命令行参数覆盖。
- 先查实际加载路径:
mysqld --verbose --help | grep "Default options",确认你改的是它读的那个my.cnf - 再查运行值:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';,对比配置文件里写的值,不一致就是没生效 - 重点关注三项:
wait_timeout(避免连接池被服务端静默断开)、max_connections(别设太高导致 OOM)、innodb_buffer_pool_size(设为物理内存的 50%–75%,但绝不能超可用内存) - 如果用 systemd 启动,检查
/etc/systemd/system/mysqld.service是否在ExecStart里硬编码了--max-connections=100—— 这会覆盖配置文件
检查用户权限与网络可达性
开发环境用 root@localhost 没问题,线上必须隔离。权限过大或过小都会出事。
- 执行
SELECT user, host FROM mysql.user;,确保没有'%'@'%'或'root'@'%'这类宽泛授权 - 查具体用户权限:
SHOW GRANTS FOR 'app_user'@'10.20.%.%';,只应有SELECT、INSERT、UPDATE、DELETE,禁止DROP、CREATE、FILE - 别只
pingIP,要真连:mysql -h <code>线上IP-u app_user -p -P 3306 -D app_db,输密码后进得去才算通 - 注意
bind-address配置:设成127.0.0.1就只能本地连;生产环境通常设0.0.0.0或具体内网 IP
确保慢查与错误日志已启用且可写
没日志的线上 MySQL 就像没刹车的车 —— 出事时只能靠猜。
- 检查开关:
SHOW VARIABLES LIKE 'slow_query_log';应为ON;long_query_time建议设1.0(别设0,会写爆磁盘) - 确认
log_error路径存在、MySQL 用户有写权限:ls -ld /var/log/mysql/,再sudo -u mysql touch /var/log/mysql/test.log - 看磁盘空间:
df -h /var/log,剩余空间低于 20% 就得预警 - 启动后
tail -f /var/log/mysql/error.log,等几秒看到ready for connections才算日志真正工作;如果只有启动信息没后续,可能是 SELinux 拦了写入
最容易被忽略的点是:配置改了但没重启 MySQL,或者重启了但没 reload 权限(FLUSH PRIVILEGES)。上线 checklist 里这两步必须手敲命令验证,不能凭记忆或截图。











