一、连接超时是个什么鬼?
大家有没有遇到过这种情况:你在MySQL客户端里敲了半天SQL,突然想去接杯水,回来发现连接断开了?或者你的应用程序半夜跑着跑着就报"Lost connection to MySQL server"的错误?这很可能就是连接超时在作怪。
MySQL服务器不会无限期地保持空闲连接,它有两个重要的超时参数来控制这种行为:
- wait_timeout:非交互式连接的超时时间(比如JDBC连接)
- interactive_timeout:交互式连接的超时时间(比如MySQL命令行客户端)
这两个参数的单位都是秒,默认值通常是28800秒(8小时)。但实际生产环境中,这个默认值往往需要调整。
二、wait_timeout详解
wait_timeout控制的是非交互式连接的空闲超时时间。举个例子,你的Java应用通过连接池获取MySQL连接,如果这个连接空闲超过wait_timeout设置的时间,服务器就会主动断开它。
// Java示例:通过JDBC获取连接
try (Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb?user=root&password=123456")) {
// 假设这里执行完查询后,连接被放回连接池
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// ...处理结果集
} catch (SQLException e) {
// 如果连接因为超时被断开,这里可能会捕获到异常
e.printStackTrace();
}
这里有个坑:如果连接池不知道连接已经被服务器断开,下次从池中取出这个连接使用时就会报错。所以好的连接池(比如HikariCP)都会有连接健康检查机制。
三、interactive_timeout详解
interactive_timeout针对的是交互式连接,比如你用mysql命令行客户端连接服务器:
# 连接到MySQL服务器
mysql -u root -p
# 连接成功后,可以查看当前的interactive_timeout值
SHOW VARIABLES LIKE 'interactive_timeout';
假设interactive_timeout设置为1800秒(30分钟),如果你在命令行里30分钟不执行任何操作,下次执行命令时可能会看到: "ERROR 2006 (HY000): MySQL server has gone away"
这个参数对DBA特别重要,因为他们经常需要长时间保持连接但又不执行查询。
四、如何设置这些参数
设置方法有多种,我们来看最常用的几种:
- 配置文件my.cnf中设置(永久生效):
[mysqld]
wait_timeout = 600
interactive_timeout = 1800
- 动态设置(立即生效,但重启后会失效):
-- 设置全局值(影响之后新建的连接)
SET GLOBAL wait_timeout = 600;
SET GLOBAL interactive_timeout = 1800;
-- 设置当前会话的值
SET SESSION wait_timeout = 600;
- 启动时通过命令行参数设置:
mysqld --wait_timeout=600 --interactive_timeout=1800
五、实际应用中的注意事项
- 连接池配置要与超时设置匹配:
// HikariCP配置示例
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("123456");
// 设置连接最大空闲时间略小于wait_timeout
config.setIdleTimeout(500000); // 500秒,比wait_timeout的600秒小
长事务会阻止连接超时: 即使连接空闲,如果有未提交的事务,连接也不会被断开。
监控超时连接:
-- 查看当前所有连接及其状态
SHOW PROCESSLIST;
六、为什么需要调整默认值
默认的28800秒(8小时)在很多场景下不合适:
- 对于Web应用,通常几分钟不用的连接就可以回收了
- 保持过多空闲连接会浪费服务器资源
- 连接泄漏时,太长的超时会导致问题迟迟不能暴露
但也不能设得太短:
- 避免频繁重建连接的开销
- 考虑慢查询和批处理的执行时间
- 考虑应用可能的不活跃时段(如夜间)
七、常见问题排查
当出现连接断开问题时,可以这样排查:
- 检查当前设置:
SHOW VARIABLES LIKE '%timeout%';
- 检查连接最后活跃时间:
SELECT * FROM performance_schema.threads
WHERE PROCESSLIST_COMMAND != 'Sleep';
- 检查错误日志:
# MySQL错误日志通常记录连接断开信息
[Note] Aborted connection 12345 to db: 'mydb' user: 'root' host: '10.0.0.1'
(Timeout)
八、最佳实践建议
- 生产环境建议设置:
- wait_timeout: 300-600秒(5-10分钟)
- interactive_timeout: 1800-3600秒(30-60分钟)
- 应用层配合:
- 使用连接池并配置合理的验证查询
- 对于长时间不用的连接,主动关闭
- 实现连接重试逻辑
- 监控:
- 监控连接数变化
- 监控连接断开事件
- 设置告警当异常断开增多时
记住,没有放之四海而皆准的配置,要根据你的具体应用特点来调整。
评论