MySQL重启时连接中断是正常行为,因systemctl restart会强制终止进程;平滑重启需配合代理摘流或MySQL 8.0.22+的innodb_fast_shutdown=0+mysqladmin shutdown,但无法完全避免中断。

MySQL 重启时连接中断怎么办
MySQL 直接 systemctl restart mysqld 会强制终止所有活跃连接,应用端大概率报 Lost connection to MySQL server during query 或 Connection refused。这不是 bug,是默认行为——MySQL 服务进程被 kill 后,TCP 连接立即断开,没有缓冲期。
真正“平滑”的关键不是重启本身,而是让新实例接管前,旧连接能自然耗尽或被优雅拒绝。实际中,systemctl restart 本身不提供连接 draining 能力,必须配合 MySQL 自身机制或外部负载层。
- 如果用的是 MySQL 8.0.22+,可先执行
SET GLOBAL innodb_fast_shutdown = 0(确保脏页刷盘),再mysqladmin shutdown,最后手动拉起;但依然不解决连接中断问题 - 若前端有代理(如 HAProxy、ProxySQL),应先在代理层摘除该节点,等
SHOW PROCESSLIST中非 SYSTEM 用户连接数归零,再重启 - 单纯依赖
systemctl reload mysqld仅重载配置(如my.cnf中的max_connections),不触发进程重启,也不影响已有连接 —— 但它不能重载所有参数,比如innodb_buffer_pool_size必须重启才生效
systemctl reload 和 restart 的本质区别
systemctl reload mysqld 实际调用的是 mysqld 的 SIGHUP 信号,MySQL 收到后只重新读取部分配置项(主要是日志路径、慢查阈值、字符集等运行时可变参数),并刷新权限表(相当于隐式执行 FLUSH PRIVILEGES)。它不会重建连接池,也不会释放 buffer pool。
systemctl restart mysqld 是先 kill -TERM 当前进程,再 fork 新进程,整个内存结构重初始化。这意味着:
-
innodb_buffer_pool_size、key_buffer_size等内存参数变更必须 restart 才生效 -
max_connections变更在 reload 后即刻生效,但已建立的连接仍计入旧限制(新连接受新值约束) - 某些发行版的
mysqldunit 文件未定义ReloadSignal=HUP,此时reload实际退化为restart—— 可用systemctl cat mysqld查看 Unit 定义确认
如何判断一次 restart 是否真的“平滑”
没有绝对平滑,只有可控中断。核心观察点不是“有没有报错”,而是“中断是否可预期、可收敛”。重点检查三处:
- 用
mysqladmin ping -h127.0.0.1 -P3306 || echo "down"在重启前后快速轮询,看中断窗口是否 ≤ 3 秒(取决于磁盘刷脏页速度) - 重启后立刻查
SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Uptime',若数值很小(如 - 对比重启前后
SHOW GLOBAL STATUS LIKE 'Threads_connected',若新值远低于旧峰值,说明连接未被复用,是干净重启;若接近,则可能有连接池复用旧 socket(少见,多见于长连接未设 timeout)
配置文件修改后 reload 失效的常见原因
最常踩的坑是:改了 my.cnf,执行 systemctl reload mysqld,但 SHOW VARIABLES 里值没变。原因往往很具体:
- 配置写在了错误 section:MySQL 只读取
[mysqld]下的参数,[client]或[mysql]下的无效 - 参数名拼错或大小写敏感:比如
max_connection(少 s)、Max_connections(大写 M)都不会被识别 - 配置被覆盖:Docker 容器中挂载的
/etc/my.cnf.d/下多个文件可能互相覆盖;systemd 启动时加了--defaults-file参数,会跳过系统级配置 - 权限问题:MySQL 进程用户(通常是
mysql)无法读取你修改的配置文件路径,journalctl -u mysqld -n 50里会出现Can't read config file类提示
真正麻烦的从来不是怎么重启,而是怎么确认这次重启既生效了,又没让下游服务雪崩。每次改配置前,先 mysqld --verbose --help | grep -A 1 "Default options" 看它到底加载了哪些文件路径,比盲目 reload 更省时间。


















