错误场景介绍

做的有一个项目使用JDBC手动创建Connection实现了一个简单的自定义数据库连接池,用来支持Canal解析数据库Binlog指定业务库的插入修改SQL来进行数据库分表备份(按照月份)操作.
但是发现当一个一段时间(较长)没有进行数据库操作时,连接都失效了,导致SQL执行失败失效提示为No operations allowed after connection closed

查明原因

经过搜索发现这个问题是由于Mysql默认一个已创建的长连接28800秒(八小时)内没有任何动作则会断开连接,该值对应参数为wait_timeout.当超时时间内有执行动作则会重新计时

查验

查询Mysql超时连接时长命令show global variables like'wait_timeout'查看当前设置的超时断开连接时长.

将其改为10,本地服务运行功能发现重现了No operations allowed after connection closed错误,即确实是连接超时失效

解决方法

1. 修改Mysql配置

==该方法不能根治这个问题,因为不能确认服务空闲时长而精确设置timeout并且还会造成多余连接长时间未断开而影响性能,所以不建议使用.建议在代码层面进行解决==

  1. 通过set global wait_timeout=time(秒)来修改最长连接等待超时时间,但是这样设置当Mysql重启失效
  2. 可以通过修改my.ini文件永久改动超时时间,如下配置
    interactive_timeout=28800000
    wait_timeout=28800000

2. 连接丢弃重新创建连接

使用conn.isValid(int timeout)(秒)判断是否失效返回true表示连接有效,返回false表示连接失效.当失效时则重新获取一个数据库连接即可,之前的对象由于引用丢失会被回收掉.

3. 增加自动重连选项

在URL最后添加autoReconnect=true参数,jdbc:mysql://hostaddress:3306/xhb?autoReconnect=true.我这里对这个没有效果,可能是对框架连接池有用.

4. 定时执行一个动作进行超时时间刷新

比如默认时间是八小时,则每七小时对连接执行一次select 1语句来刷新该连接在数据库的超时等待时长

也可以1 2 4一起使用,来防止突然一个流量静默期间后突发流量高峰而导致获取连接不及时