【问题背景】
1、开发人员偶尔会发一些JDBC Exception信息,问异常背后的原因?而DBA在没有环境的情况下,往往难根据Exception推断出此异常信息背后的实际含义。
2、JDBC、DAO及数据库连接池 等都是介于数据库与应用程之间的,往往开发人员和DBA都太深入理解,比如参数,异常信息和命令行的异常信息存在不同。
3、部门的DAO的Query timeout是基于jdbc的setQueryTime()方法,但开发人员往往配置不合理和程序不合理,在特定情况下出现少量的异常信息。
下面简单列举常常遇到jdbc 异常,及其背后的原因。
【异常信息】
一、异常1:异常信息:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException : Communications link failure
Last packet sent to the server was 9773 ms ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0( Native Method)
----------------------省略--------------------------------------------
Caused by: java.io.EOFException: Can not read response from server. Expected to read 54,539 bytes, read 23,419 bytes before connection was unexpectedly lost.
at com.mysql.jdbc.MysqlIO.readFully( MysqlIO.java:2431)
原因分析:这种异常的原因是jdbc连接数据库成功后,连接被服务器,或者第三方力量强制断开了,一般会抛出Communications link failure的异常信息。
但也细分为以下几种原因:
原因1:由于连接进行sleep状态wait_timeout秒后: 应用连接数据库后。
连接池并没有回收此空闲的连接,当连接达进行sleep状态wait_timeout的秒后(如wait_timeout=7200);那么2小时,此连接会被MySQL server断开,但
应用端的连接池却不知道,当应用再次向此连接发送命令时,就会出现此异常。
不过有个细微处:Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
注意:上面read 0 bytes,说明还未读取任何的mysql server 信息。
原因2:连接在执行的过程中被强制断开了,如网络闪断,vip漂移,super权限的user(自己也可以kill)把它kill掉了。
Caused by: java.io.EOFException: Can not read response from server. Expected to read 54,539 bytes, read 23,419 bytes before connection was unexpectedly lost.
注意:这个时候的 Expected to read 54,539 bytes, read 23,419 bytes before connection was unexpectedly lost
read字节数是有的。
原因3:是使用了MySQL JDBC的setQueryTimeout()方法导致。
代码示例:
String sql ="select * from t_pic_0 ";
try {
Statement st = conn.createStatement();
System. out.println(new Date());
st.setQueryTimeout(10);
}
不过: 些Exception只有java.sql.SQLException: Query execution was interrupted 没有后面的Caused by: java.io.EOFException:
关于setQueryTimeout()方法的问题,请见另一文章:《关于mysql jdbc的setQueryTimeout() 的bug和Query execution was interrupted 的调查》