DB接続プーリングにc3p0を使用している永続層としてHibernateを使用して、MySQL 5データベースに接続するJavaサーバーがあります。
私はc3p0と休止状態のドキュメントに従ってみました:
本番サーバーで次のようなエラーが発生しています。
... 原因: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: 接続が閉じられた後、操作は許可されません。根本的な例外/エラーのため、接続は暗黙的に閉じられました:
ネストされた例外の開始
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
メッセージ: サーバーから正常に受信された最後のパケットは 45000 秒前でした。サーバーに正常に送信された最後のパケットは 45000 秒前で、サーバーが構成した 'wait_timeout' の値よりも長くなっています。この問題を回避するには、アプリケーションで使用する前に接続の有効性を期限切れにするかテストするか、クライアント タイムアウトのサーバー設定値を増やすか、Connector/J 接続プロパティ 'autoReconnect=true' を使用することを検討する必要があります。
スタックトレース:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: サーバーから正常に受信された最後のパケットは 45000 秒前でした。サーバーに正常に送信された最後のパケットは 45000 秒前で、サーバーが構成した 'wait_timeout' の値よりも長くなっています。この問題を回避するには、アプリケーションで使用する前に接続の有効性を期限切れにするかテストするか、クライアント タイムアウトのサーバー設定値を増やすか、Connector/J 接続プロパティ 'autoReconnect=true' を使用することを検討する必要があります。
次のように c3p0 接続プールのプロパティを設定しました。
hibernate.c3p0.max_size=10
hibernate.c3p0.min_size=1
hibernate.c3p0.timeout=5000
hibernate.c3p0.idle_test_period=300
hibernate.c3p0.max_statements=100
hibernate.c3p0.acquire_increment=2
デフォルトの MySQL の wait_timetoutは 28800 秒 (8 時間) に設定されています。報告されたエラーは、45000 秒 (約 12.5 時間) を超えていることを示しています。c3p0 構成では、5000 秒後に使用されていないアイドル状態の接続を「タイムアウト」し、300 秒ごとにチェックすると記載されていますが、アイドル状態の接続が 5299 秒より長く存続することはありません。
開発者の MySQL (Windows では my.ini、Unix では my.cnf) を wait_timeout=60 に設定し、c3p0 のアイドル タイムアウト値を 60 秒未満に下げることで、ローカルでテストしました。これにより、アイドル接続が適切にタイムアウトし、新しい接続が作成されます。また、DB 接続をリークして接続を保持していないことも確認しましたが、そうではないようです。
これは、c3p0 が接続を適切に処理していることを確認するために開発者環境でテストするために使用している c3p0.properties ファイルです。
hibernate.properties (MySQL の wait_timeout=60 でテスト)
hibernate.c3p0.max_size=10
hibernate.c3p0.min_size=1
hibernate.c3p0.timeout=20
hibernate.c3p0.max_statements=100
hibernate.c3p0.idle_test_period=5
hibernate.c3p0.acquire_increment=2
c3p0.properties
com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL=ALL
com.mchange.v2.log.MLog=com.mchange.v2.log.FallbackMLog
c3p0.debugUnreturnedConnectionStackTraces=true
c3p0.unreturnedConnectionTimeout=10