私は、高アクティビティの突風を伴うgrailsアプリを持っていますが、その後、数時間から一晩続くことがある非アクティブな期間が多いことがあります。朝の最初のユーザーが次のタイプの例外を受け取ることに気付きました。これは、プール内の接続が古くなり、MYSqlデータベースがそれらを閉じるためであると考えています。
コネクタ/ 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)
最も簡単なのは、接続プールを構成して、アプリケーションに渡される前に接続をテストするために実行するクエリを指定することです。
validationQuery="select 1 as dbcp_connection_test"
testOnBorrow=true
この同じ「接続検証」クエリは、他のイベントで実行できます。これらのデフォルトがわからない:
testOnReturn=true
testWhileIdle=true
また、プール内のアイドル接続の「年齢」を制限する構成設定もあります。これは、サーバー側でアイドル接続が閉じられている場合に役立ちます。
minEvictableIdleTimeMillis
timeBetweenEvictionRunsMillis
データベース接続を処理する最良の方法であるかどうかはわかりませんが、説明したのと同じ問題がありました。私は多くのことを試してみましたが、 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
}
}