Java应用Hibernate连接MySQL服务器遇Connection reset异常求助
解决方案:Hibernate+C3P0连接MySQL服务器出现Connection Reset问题
碰到过一模一样的场景,本地跑WAR包完全正常,部署到服务器就报这个连接重置的错——虽然能Ping通数据库,但Ping只是ICMP层面的连通性,不代表TCP端口和应用层连接真的没问题,给你几个亲测有效的排查和解决方向:
- 先确认MySQL端口的TCP连通性:Ping通不代表3306端口能访问,在应用服务器上执行
telnet your-db-host 3306或者nc -zv your-db-host 3306,如果连接失败,说明端口被防火墙/安全组拦截,或者MySQL根本没监听这个端口。 - 检查MySQL的bind-address配置:登录MySQL服务器,查看
my.cnf(Windows是my.ini)里的bind-address参数,如果是127.0.0.1,说明MySQL只允许本地连接,改成0.0.0.0(允许所有IP访问)或者应用服务器的专属IP,然后重启MySQL服务。 - 调整C3P0连接池的空闲连接验证配置:从异常栈看是定时任务触发的问题,说明是长时间空闲的连接被MySQL/网络设备断开了,需要让连接池定期清理无效连接并验证新连接,在Hibernate配置里加上:
这些参数的作用是:每次取连接时自动验证,每300秒检查一次空闲连接,空闲1800秒就回收,用hibernate.c3p0.testConnectionOnCheckout=true hibernate.c3p0.idleConnectionTestPeriod=300 hibernate.c3p0.maxIdleTime=1800 hibernate.c3p0.preferredTestQuery=SELECT 1SELECT 1作为轻量验证查询。 - 调整MySQL的连接超时参数:登录MySQL执行
SHOW VARIABLES LIKE '%timeout%';,查看wait_timeout和interactive_timeout,默认是8小时(28800秒),如果设置得太小(比如300秒),会自动断开空闲连接,需要调大:
记得在SET GLOBAL wait_timeout=28800; SET GLOBAL interactive_timeout=28800;my.cnf里也加上这两个参数,避免MySQL重启后配置失效。 - 检查JDBC驱动版本兼容性:如果MySQL服务器是8.0及以上版本,一定要用
mysql-connector-java:8.0.x版本的驱动,旧的5.x驱动和新版MySQL存在兼容性问题,会导致连接重置。同时JDBC URL里的驱动类也要对应:8.0用com.mysql.cj.jdbc.Driver,5.x用com.mysql.jdbc.Driver。 - 开启TCP Keepalive:如果应用服务器和数据库之间有负载均衡、VPN这类中间件,它们可能会主动断开长时间空闲的TCP连接,可以在JDBC URL里加上
tcpKeepAlive=true参数:jdbc:mysql://your-db-host:3306/your-db?useSSL=false&tcpKeepAlive=true&serverTimezone=UTC - 排查网络中间件的超时设置:如果有负载均衡、防火墙这类设备,检查它们的空闲连接超时时间,确保这个时间比MySQL的
wait_timeout和连接池的maxIdleTime更长,避免中间件提前把连接断开。
内容的提问来源于stack exchange,提问作者Mayank Mahajan
相关产品推荐
相关产品推荐

