38

私は grails アプリを使用していますが、アクティビティが頻繁に発生しますが、非アクティブな期間が数時間から一晩続くことがよくあります。朝の最初のユーザーが次のような例外を受け取ることに気付きました。これは、プール内の接続が古くなり、MYSql データベースが接続を閉じたためだと思います。

Connector/J 接続プロパティ 'autoReconnect=true' を使用するのが良い考えかどうか (そして、接続が復元されてもクライアントが例外を受け取るかどうか)、または設定するかどうかについて、Google で矛盾する情報を見つけました。アイドル状態の接続を定期的に削除または更新したり、借用をテストしたりするその他のプロパティ。Grails はその下で DBCP を使用します。私は現在、以下のように単純な構成を持っており、長い非アクティブ期間の後にプールから取得された接続が有効であり、閉じられていないことを確認する最善の方法についての回答を探しています。

dataSource {
        pooled = true
        dbCreate = "update"
        url = "jdbc:mysql://my.ip.address:3306/databasename"
        driverClassName = "com.mysql.jdbc.Driver"
        dialect = org.hibernate.dialect.MySQL5InnoDBDialect
        username = "****"
        password = "****"
        properties {
          //what should I add here?
          }
    }

例外

    2012-06-20 08:40:55,150 [http-bio-8443-exec-1] ERROR transaction.JDBCTransaction  - JDBC begin failed
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 64,129,968 milliseconds ago.  The last packet sent successfully to the server was 64,129,968 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
    at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3851)
    ...... Lots more .......
Caused by: java.sql.SQLException: Already closed.
    at org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:114)
4

2 に答える 2

37

最も簡単なのは、接続プールを構成して、アプリケーションに渡される前に接続をテストするために実行するクエリを指定することです。

validationQuery="select 1 as dbcp_connection_test"
testOnBorrow=true

これと同じ「接続検証」クエリを他のイベントで実行できます。これらのデフォルトはわかりません。

testOnReturn=true
testWhileIdle=true

プール内のアイドル接続の「経過時間」を制限する構成設定もあります。これは、サーバー側でアイドル接続が閉じられている場合に役立ちます。

minEvictableIdleTimeMillis
timeBetweenEvictionRunsMillis

http://commons.apache.org/dbcp/configuration.html

于 2012-06-20T18:50:28.297 に答える
9

データベース接続を処理する最良の方法であるかどうかはわかりませんが、あなたが説明したのと同じ問題がありました。いろいろ試した結果、c3p0 接続プールになりました。

c3p0 を使用すると、一定時間後にアプリにデータベース接続を強制的に更新させることができます。

c3p0.jarをフォルダに配置libし、設定を に追加しますconf/spring/resources.groovy

resources.groovyはこのように見えます:

import com.mchange.v2.c3p0.ComboPooledDataSource
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

beans = {
    /**
    * c3P0 pooled data source that forces renewal of DB connections of certain age
    * to prevent stale/closed DB connections and evicts excess idle connections
    * Still using the JDBC configuration settings from DataSource.groovy
    * to have easy environment specific setup available
    */
    dataSource(ComboPooledDataSource) { bean ->
        bean.destroyMethod = 'close'
        //use grails' datasource configuration for connection user, password, driver and JDBC url
        user = CH.config.dataSource.username
        password = CH.config.dataSource.password
        driverClass = CH.config.dataSource.driverClassName
        jdbcUrl = CH.config.dataSource.url
        //force connections to renew after 4 hours
        maxConnectionAge = 4 * 60 * 60
        //get rid too many of idle connections after 30 minutes
        maxIdleTimeExcessConnections = 30 * 60
    }
 }  
于 2012-06-20T20:44:46.890 に答える