mysql的交互式连接+非交互式连接超时时间设置和解释: Communications link failure The last packet successfully received from the server was XXX milliseconds ago

问题:

1.搭建了一个nginx反向的代理mysql db的TCP代理,实现用jar包去操作db操作数据库,发现执行业务执行时间太长(比如tc执行时间长)就会出现报错:Communications link failure The last packet successfully received from the server was XXX milliseconds ago

2.MySQL服务器有一个wait_timeout参数,它控制了非交互式连接的空闲超时时间 请问这个“非交互式连接的空闲超时时间” 是什么意思,能解释下“非交互式连接的空闲”的意思吗?

总结解决思路:

1. mysql 是长连接,在程序一启动(jar包被执行时,就会自动和mysql建议数据库连接), client就会建立和 mysql db的连接。 这个连接一致保持,直到程序执行结束时才会关闭。
所以方案一是:nginx里面TCP空闲连接超时时间(proxy_timeout参数),最好弄成永久不超时。
2.方案二:给DB 连接加心跳 :  
在application.properity文件中配置: spring.datasource.hikari.connection-test-query=SELECT 1

 

 

我们首先需要理解MySQL中“交互式连接”和“非交互式连接”的区别。
交互式连接:通常指的是用户通过MySQL客户端(如mysql命令行的客户端)直接与服务器进行交互的连接。在这种连接中,用户输入一条命令,服务器返回结果,然后用户可能停顿一段时间再输入下一条命令。
非交互式连接:通常指的是由应用程序通过连接池、驱动程序(如JDBC)等建立的连接,用于执行查询并获取结果,而不需要人工干预。

那么,“非交互式连接的空闲超时时间”指的是:当一个非交互式连接在一段时间内(由wait_timeout参数指定,单位是秒)没有进行任何操作(即没有发送任何SQL命令)时,MySQL服务器会自动关闭这个连接。

这个机制是为了释放服务器上不必要的资源,因为维持一个空闲连接会占用内存和连接数资源。

举个例子
假设wait_timeout设置为300(秒),那么如果一个非交互式连接在300秒内没有进行任何数据库操作MySQL服务器就会断开这个连接。之后,如果应用程序尝试在这个已经关闭的连接上执行操作,就会收到一个连接错误

在应用程序中,我们通常通过连接池来管理数据库连接,连接池可以配置为定期发送测试查询(如SELECT 1)以保持连接活跃,或者当连接被返回池中时重置其空闲时间,或者在从池中取出连接时检查连接是否仍然有效。

image

 

另外,MySQL还有一个参数interactive_timeout,用于控制交互式连接的空闲超时时间,其行为与wait_timeout类似,但适用于交互式连接

注意:

在MySQL配置中,如果没有单独设置interactive_timeout,那么它会使用wait_timeout的值。但是,为了明确,通常建议两个参数都设置。

所以,当你的应用程序遇到“MySQL server has gone away”这样的错误时,有可能是因为连接空闲时间超过了wait_timeout而被服务器关闭了。

解决方法:

    1. 调整MySQL的wait_timeout和interactive_timeout参数,增加超时时间。

    2. 在应用程序的连接池配置中,设置一个比wait_timeout短的最大空闲时间,确保在连接被服务器关闭之前,连接池就会将其关闭并重建

    3. 配置连接池定期进行连接有效性检查,例如使用测试查询。

MySQL连接类型详解

什么是"非交互式连接"

非交互式连接指的是应用程序通过编程接口(如JDBC、ODBC、PHP PDO等)与MySQL建立的连接,主要用于:

  • Web应用程序连接数据库

  • 批处理作业

  • 后台服务

  • 脚本程序执行SQL

什么是"交互式连接"

交互式连接指的是用户通过客户端工具直接与MySQL交互:

  • MySQL命令行客户端(mysql -u -p)

  • MySQL Workbench

  • phpMyAdmin等图形化工具

  • 用户手动输入SQL并查看结果

"空闲"的含义

空闲指的是连接建立后,在指定时间内:

  • 没有执行任何SQL语句

  • 没有数据包传输

  • 连接处于"静默"状态

参数对比

 
参数控制对象默认值适用场景
wait_timeout 非交互式连接空闲超时 28800秒(8小时) 应用程序连接
interactive_timeout 交互式连接空闲超时 28800秒(8小时) 命令行客户端

实际示例

1. 非交互式连接场景

前提:数据库的wait_timeout=600(10分钟),或者数据库的TCP反向代理设置的proxy_timeout=600s: (参考: https://www.cnblogs.com/pingguomang/p/19222365
//
Java应用程序 Connection conn = DriverManager.getConnection(url, user, password); // 连接建立 - 开始计时 // 执行查询 Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users"); // 有数据交互 - 重置空闲计时器 // 接下来10分钟没有数据库操作 Thread.sleep(600000); // 此时如果wait_timeout=600(10分钟),连接会被服务器关闭 // 再次尝试使用连接会报错 stmt.executeQuery("SELECT * FROM orders"); // 抛出CommunicationsException

2. 查看和设置参数

-- 查看当前超时设置
SHOW VARIABLES LIKE '%timeout%';
SHOW VARIABLES WHERE Variable_name IN ('wait_timeout', 'interactive_timeout');

-- 设置全局超时(需要SUPER权限)
SET GLOBAL wait_timeout = 600;        -- 10分钟
SET GLOBAL interactive_timeout = 1800; -- 30分钟

-- 设置会话级超时
SET SESSION wait_timeout = 300;       -- 仅当前连接生效

问题表现和影响

连接超时的错误现象

Communications link failure
The last packet successfully received from the server was XXX milliseconds ago

对应用程序的影响

  1. 连接池失效:连接池中的空闲连接被服务器关闭

  2. 应用报错:下次使用该连接时出现通信错误

  3. 性能下降:需要重新建立连接,增加开销

解决方案

1. 应用程序层面

// 连接池配置(HikariCP示例)
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setIdleTimeout(300000);        // 5分钟(小于MySQL的wait_timeout)
config.setMaxLifetime(1800000);       // 30分钟
config.setConnectionTestQuery("SELECT 1");
config.setValidationTimeout(5000);

2. 数据库层面优化

-- 合理的超时设置
SET GLOBAL wait_timeout = 600;        -- 应用连接:10分钟
SET GLOBAL interactive_timeout = 1800; -- 交互连接:30分钟

-- 其他相关参数
SET GLOBAL net_read_timeout = 120;    -- 读取超时
SET GLOBAL net_write_timeout = 120;   -- 写入超时

3. 连接保持策略--这一点非常重要

// 定期执行轻量级查询保持连接活跃
@Scheduled(fixedRate = 300000) // 每5分钟执行一次
public void keepAlive() {
    jdbcTemplate.execute("SELECT 1");
}

最佳实践建议

超时时间设置原则

# MySQL配置文件 my.cnf
[mysqld]
# 应用程序连接 - 根据业务特点设置
wait_timeout = 600                    # 10分钟

# 交互式连接 - 可以设置更长
interactive_timeout = 3600            # 1小时

# 网络相关超时
net_read_timeout = 120
net_write_timeout = 120
connect_timeout = 10

 

连接池配置匹配

# 确保连接池超时 < MySQL超时
spring.datasource.hikari.max-lifetime=1800000     # 30分钟 < wait_timeout
spring.datasource.hikari.idle-timeout=300000      # 5分钟 < wait_timeout

总结

"非交互式连接的空闲超时时间" 指的是:

  • 非交互式连接:应用程序建立的数据库连接

  • 空闲:连接建立后没有进行任何数据交互的状态

  • 超时时间:MySQL服务器自动关闭空闲连接的等待时间

这个机制是为了释放服务器资源,防止长时间空闲连接占用内存和连接数。合理配置这个参数对于应用程序的稳定性至关重要。

posted @ 2025-11-14 17:04  苹果芒  阅读(3)  评论(0)    收藏  举报