yymmiinngg 发表于 2013-1-29 22:31:08

mysql-connector-java-5.0.3.jar Bug之 Statement.setQueryTimeout(int seconds)

    我们都知道在java.sql.Statement接口规范中有这么一个方法,如下代码片段:
    /**   * Sets the number of seconds the driver will wait for a      * <code>Statement</code> object to execute to the given number of seconds.   * If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC   * driver must apply this limit to the <code>execute</code>,   * <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC driver   * implementations may also apply this limit to <code>ResultSet</code> methods   * (consult your driver vendor documentation for details).   *   * @param seconds the new query timeout limit in seconds; zero means      *      there is no limit   * @exception SQLException if a database access error occurs,      * this method is called on a closed <code>Statement</code>   *            or the condition seconds >= 0 is not satisfied   * @see #getQueryTimeout   */    void setQueryTimeout(int seconds) throws SQLException;  
    从这段代码中我们能看到“@param seconds the new query timeout limit in seconds; zero means there is no limit”,也就是说“seconds”设置查询的超时“秒”数,如果为0则无超时。
 
    然而在mysql-connector-java-5.0.3.jar的实现中却不是这么按照接口规范做的(但符合JAVA接口规则),请看下面的代码片段: 
/** * 这里是com.mysql.jdbc.Statement类中设置查询超时时长的实现 */public void setQueryTimeout(int seconds)throws SQLException{    if (seconds < 0) {      throw SQLError.createSQLException(Messages.getString("Statement.21"), "S1009");    }    this.timeout = seconds;}// 这一段是在com.mysql.jdbc.Statement类中使用超时时长的代码if ((this.timeout != 0) && (locallyScopedConn.versionMeetsMinimum(5, 0, 0))) {      timeoutTask = new CancelTask(this);      Connection.getCancelTimer().schedule(timeoutTask, this.timeout);} 
    从以上的代码可以看出setQueryTimeout方法设置的this.timeout 的值被Connection.getCancelTimer().schedule(timeoutTask, this.timeout);直接应用,而没进行任何的单位转换。
 
    于是我们如果设置想设置10秒的查询超时就必需写成setQueryTimeout(10000),而之前我一直是按照接口的规范写成setQueryTimeout(10) 。
 
    起初我数据库的数据量非常少,而随着时间的推移,数据量会越来越多,这时数据库查询的响应速度就会随之变慢,所以经过一段时间后,我就发现【com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client】这种错误越来越多,大家应该很清楚是什么原因造成的吧?之前的数据库响应在10毫秒内没问题,因为数据量小,但数据量多了,于是响应就慢了,这时这种异常就多了,甚至到最后根本无法返回正常的查询结果。
 
    经过分析得出结论:这是mysql-connector-java-5.0.3.jar的严重BUG。
 
    对于这个BUG的解决方法就是使用mysql-connector-java-5.0.8-bin.jar或更高版本的JAR包。 
页: [1]
查看完整版本: mysql-connector-java-5.0.3.jar Bug之 Statement.setQueryTimeout(int seconds)