2012-06-20 6 views
33

Grails 2のアプリでは、活動度の高いフロリダがありますが、しばしば非アクティブな期間が過ぎることがあります数時間から一晩。私は、午前中の最初のユーザーが次のような例外を受け取ることに気がつきました。これは、プール内の接続が古くなり、MYSqlデータベースがそれらを閉じていることが原因であると考えています。Grails 2アプリ

私は、Connector/J接続プロパティ 'autoReconnect = true'を使用することが良いアイデアであるかどうか、また接続が復元されてもクライアントが引き続き例外を受け取るかどうかについて、Googlingに矛盾する情報があることを発見しました。または定期的にアイドル状態の接続をリフレッシュまたはリフレッシュするその他のプロパティを設定するかどうか、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) 

答えて

29

最も簡単にはそれがアプリケーションに渡される前に、接続をテストするために実行されるクエリを指定するには、接続プールを設定することです:

validationQuery="select 1 as dbcp_connection_test" 
testOnBorrow=true 

これを他のイベントでも同じ「接続検証」クエリを実行できます。私は、これらのデフォルトのわからない:

testOnReturn=true 
testWhileIdle=true 

アイドル状態の接続は、サーバー側で閉じられている場合に役立ちますプールでアイドル接続の「年齢」を制限した構成の設定もあります。 。

minEvictableIdleTimeMillis 
timeBetweenEvictionRunsMillis 

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

+0

おかげで、何とかJavadocをまっすぐに行くことによって、そのページを逃しました。私はそれらの組み合わせを実装し、どのように動作するかを見ていきます。 – Peter

+0

残念ながら、DBCPには接続の経過時間や接続が使用された回数がプールから削除される前に制限される構成はありません。 (他の接続プールの実装では) – spencer7593

+0

ただし、spencer7593は、接続が使用されているかどうかは関係ありませんが、使用していない状態から悪くなったときに追い払い/更新されても問題はありません。 – Peter

7

それがデータベース接続を処理するための最良の方法であるかどうかは知りませんが、desribedと私は同じ問題を抱えていました。私はたくさん試して、c3p0 connection poolで終わった。

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

libフォルダにc3p0.jarを置き、設定を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 
    } 
} 
+0

+1一部の接続プールの実装では、DBCPよりも堅牢な機能が提供されています。より最近のバージョンのDBCPでは、「最大アイドル時間」が経過したときに追い出しをサポートしていますが、DBCPには最大年齢や最大使用回数などの他の設定オプションがまだありません。 – spencer7593

+1

Grailsスタックで接続タイムアウトの問題が発生すると、C3POがうまく動作することがわかりました。 –

関連する問題