前言:
之前就遇到过这种mysql创建链接8小时未访问断开的问题。当时解决了,但是没有记录。结果今天部署一个自己的项目又出现了这种问题,所以这次记录下来,防止以后再遇到。
前提:后台使用的是jdbc进行的连接。
问题排查:
部署服务后,由于使用人数不多,所以mysql的访问比较少。经过了一晚上之后,在访问就提示如下的错误:
com.mysql.jdbc.Communication***ception: Communications link failure due to underlying exception:
** BEGIN NESTED EXCEPTION **
java.net.SocketException
MESSAGE: Software caused connection abort: recv failed
......................................................
** END NESTED EXCEPTION **
Last packet sent to the server was 202211 ms ago.
这种就是典型的超过8小时未使用了连接过期的问题。
解决方案:
网上的解决方案主要有以下三种,这里着重说第三种,也是最推荐的一种方案。
1.配置层做,修改mysql数据库配置
改大mysql的超时时间。但是重启mysql后还是会失效。
interactive_timeout=28800000
wait_timeout=28800000
2.连接时修改
创建连接的url中,后面加上autoReconnect=true。
弊端:这种只适用于mysql5.0以下的版本,5.0以上还是不行。
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/staff?useUnicode=true&characterEncoding=utf8&autoReconnect=true";
String user = "xxx";
String password = "xxx";
return DriverManager.getConnection(url, user, password);
} catch (Exception e) {
}
3.代码层修改
对connection进行封装,使用前做一个合法性判断,如果是合法的在返回。
代码如下:
public Connection getConn() {
if (conn == null) {
conn = createConn();
return conn;
}
try {
if (conn.isValid(8 * 3600)) {
return conn;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
conn = createConn();
return conn;
}
private Connection createConn() {
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/staff?useUnicode=true&characterEncoding=utf8&autoReconnect=true";
String user = "xxx";
String password = "xxxx";
return DriverManager.getConnection(url, user, password);
} catch (Exception e) {
}
return null;
}
使用处的代码:
@Override
public boolean deleteShopModel(int accountId) {
String sql = "delete from " + ACCOUNT_TABLE + " where account_id =" + accountId;
Statement stmt = null;
try {
stmt = getConn().createStatement();
return stmt.executeUpdate(sql) > 0;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}