应根据连接模式选择修改interactive_timeout或wait_timeout:客户端显式声明interactive_client=1时生效的是interactive_timeout,否则为wait_timeout;两者建议设为相同值(如3600秒),并确保配置加载且无网络中间件干扰。

interactive_timeout 和 wait_timeout 到底改哪个?
如果你连的是 MySQL 客户端(比如 mysql 命令行工具),或者用 JDBC/Connector Python 等驱动显式声明了 interactive_client=1,那真正起作用的是 interactive_timeout;否则默认走 wait_timeout。别只改一个——很多同学只调了 wait_timeout,结果客户端还是 8 小时断连,就是因为没意识到自己连的是 interactive 模式。
判断方法:连上后执行 SELECT @@session.interactive_timeout, @@session.wait_timeout;,再看应用连接时有没有带 CLIENT_INTERACTIVE 标志(JDBC 叫 useInteractiveClient=true)。
在 my.cnf 里怎么安全地改?
直接写进 [mysqld] 段就行,但注意两点:一是必须重启 mysqld 才生效(动态 SET 只影响当前会话,且不改变新连接的初始值);二是别设太小,比如 interactive_timeout = 60 看似防长连接,但开发调试时敲个 SELECT SLEEP(61) 就直接断开,反而干扰排查。
[mysqld] interactive_timeout = 28800 wait_timeout = 28800
- 28800 秒(8 小时)是默认值,生产环境建议不低于 3600(1 小时)
- 两个值设成一样最省心,除非你有明确区分 interactive/non-interactive 连接池的需求
- 如果用 Docker,记得把配置挂载进容器并确认 mysqld 启动时加载了它(可查
mysqld --verbose --help | grep "Default options")
应用层连上后还能不能临时调?
能,但只对当前连接有效,且得在登录后立刻 SET,不能等连接空闲快超时了才去改——那时可能已经触发断连逻辑了。
常见错误:在 ORM(如 Django、SQLAlchemy)里执行 SET interactive_timeout = 3600,结果发现没用。因为 ORM 通常用连接池,这个 SET 只影响池中某一个连接,而且下次归还再取出时又恢复成全局值。
- 推荐方式:在连接建立后的初始化 SQL 里加(如 MySQL 的
init_command参数) - JDBC 示例:连接串末尾加
&sessionVariables=interactive_timeout=3600 - Python mysql-connector:构造
connect(..., connection_timeout=3600)不影响服务端超时,得靠set_session或 init_command
为什么改了配置还是被断?
最常见的三个原因:防火墙/SLB 主动 kill 空闲连接、客户端驱动自身心跳未开启、MySQL 实际运行的配置不是你以为的那个 my.cnf。
先确认生效:登录后执行 SHOW VARIABLES LIKE '%timeout%';,看输出的值是不是你设的;再抓包或看客户端日志,确认断连前是否有 Lost connection to MySQL server during query 或 MySQL server has gone away ——前者大概率是网络中间件干的,后者才是 MySQL 主动断的。
容易被忽略的一点:某些云数据库(如阿里云 RDS、腾讯云 CDB)会强制覆盖部分 timeout 参数,后台管理界面改了也不一定生效,得看文档是否允许自定义。










