【问题标题】:MySQL Statement Cancellation Timer failed to StopMySQL 语句取消计时器未能停止
【发布时间】:2016-08-22 18:23:20
【问题描述】:

以下警告的原因是什么。

WARNING: The web application [TI] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Apr 28, 2016 11:03:25 AM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [TI] appears to have started a thread named [MySQL Statement Cancellation Timer] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:503)
java.util.TimerThread.mainLoop(Timer.java:526)
java.util.TimerThread.run(Timer.java:505)

每当我更改我的代码并tomcat 重新启动时就会发生这种情况。 我正在创建 mysql 连接,我认为我正在正确关闭它。
这是我的代码。

@RequestMapping(value = "/file/md5", method = RequestMethod.POST)
public ResponseEntity<?> md5Status(@RequestParam(required = true) String filename) {

    Connection con = SqlUtility.getMysqlConnection(host, port, database,username, password);
    SqlUtility.closeDbInstances(SqlUtility.mysqlConnection);
    SqlUtility.closeDbInstances(con);
    return new ResponseEntity<>(HttpStatus.CONFLICT);
}

这是实用程序代码。

public static Connection mysqlConnection = null;
private static PreparedStatement preparedStatement = null;
private static ResultSet resultSet = null;

public static Connection getMysqlConnection(String host, int port, String database, String username,
        String password) {
    MysqlDataSource mds = null;
    try {
        if (mysqlConnection == null || mysqlConnection.isClosed()) {
            if (database != null && host != null) {
                while (mds == null) {
                    System.out.println("In Loop");
                    mds = new MysqlDataSource();
                    mds.setServerName(host);
                    mds.setPortNumber(port);
                    mds.setDatabaseName(database);
                    mds.setUser(username);
                    mds.setPassword(password);
                    try {
                        mysqlConnection = mds.getConnection();
                    } catch (CommunicationsException e) {
                        System.out.format(
                                "Error occurred while trying to get connection with database [%s]. Are your database host [%s] and port [%s] correct? %n%s%n",
                                database, host, port, e);
                        mds = null;
                        // Had to handle for retrying again and again
                        // This is because your mysql is bind on localhost change it in my.cfg 
                    }
                }
            } else {
                System.out.format(
                        "Error occurred while trying to get connection with database [%s] with username [%s] and password [%s].\n [ATTN] Make sure your DB adapter properties file contains all required attributes. %n",
                        database, username, password);

            }

        }
    } catch (SQLException e) {
        System.out.format(
                "Error occurred while trying to get connection at host [%s] with database [%s] with username [%s] and password [%s] %n%s%n",
                host, database, username, password, e);
        // It might be because of the database privileges which must be grant to access 
    } catch (RuntimeException e) {
        System.out.format("Error occurred while trying to get [%s] Connection %n%s%n", database, e);
    }

    if (mysqlConnection != null)
        System.out.format("[%S] Connection Successfully Created%n", database);
    return mysqlConnection;

}

public static void closeDbInstances(Connection con) {
    System.out.println("Trying to close Database Connection...");
    if (con != null && preparedStatement != null && resultSet != null) {
        try {
            resultSet.close();
            preparedStatement.close();
            con.close();
            System.out.println("Database Connection Closed");
        } catch (SQLException e) {
            System.out.println("Error occurred while trying to close Database connection " + e);
        }
    }
}

【问题讨论】:

  • 你的tomcat库中有mysql连接器jar吗?
  • 没有必要吗?
  • 是的,在 tomcat lib 中添加连接器 jar,然后尝试,让我知道。
  • 不,它不会仍然给我同样的警告。
  • 我不认为这是一个 jar 缺失问题,因为在这种情况下,异常可能是 ClassNotFound 品种。

标签: java mysql tomcat


【解决方案1】:

(老问题,但我遇到了相同的错误/警告消息) 您是使用带有QueryTimeoutInterceptor 的jdbc 池还是调用statement.setQueryTimeout(320) 函数。它调用内部 mysqljdbc.jar 线程来取消长时间运行的查询。

Tomcat hotdeployment 无法识别它,因此线程被留在后面运行,并且仍然在 RAM 中保持死的 webapp 上下文。

  <Resource name="jdbc/BSManager" auth="Container" 
    type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    initialSize="2" maxActive="100" maxIdle="10" maxWait="30000"    
    username="myuser" password="mypwd"
    driverClassName="com.mysql.jdbc.Driver" 
    jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor(queryTimeout=320)"
    url="jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&amp;characterEncoding=utf8"
        validationQuery="SELECT 1" removeAbandoned="true" removeAbandonedTimeout="7200"
        testOnBorrow="true" maxAge="1800000"
  />

即使在tomcat/conf/server.xml 文件中激活了此侦听器,也会出现此警告消息The web application [TI] appears to have started a thread named [MySQL Statement Cancellation Timer] but has failed to stop it。我不知道在查询超时后是否释放了死 webapp。我决定不对 MySQL jdbc 驱动程序使用查询超时。

  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" 
        classesToInitialize="com.mysql.jdbc.NonRegisteringDriver" />

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-04
    • 2016-07-23
    • 2022-12-02
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    相关资源
    最近更新 更多