5

c3p0 を使用して、アプリケーションでのデータベース接続の作成と破棄をログに記録しようとしていますConnectionCustomizer。その中に、次のようなコードがあります。

log(C3P0Registry.getPooledDataSources())

私はデッドロックに陥っています。c3p0 のライブラリには、同期メソッドを使用する少なくとも 2 つのオブジェクトがあり、意図したロック順序を指定していないようです。接続をログに記録すると、ロックがかかっていてC3P0Registry、最終的にはPoolBackedDataSource(単純にデータソースのリストを作成すると、ハッシュコードにアクセスしてロックが発生します)。

接続プロバイダーをシャットダウンする ( を呼び出すC3P0ConnectionProvider.close()) と、ロックが逆の順序で呼び出されます。しかし、子データソースがシャットダウンされている間、ログがトリガーされています。その結果、デッドロックが発生します。

私がc3p0ライブラリに行っている呼び出しは両方とも有効で、予想される呼び出しのようです:

  • C3P0ConnectionProvider.close()
  • C3P0Registry.getPooledDataSources()

また、(ドキュメントに明示的に記載されていない限り)独自のロック戦略を管理するのはライブラリの責任であるように思われます。(これは誰かを責めるために言っているのではありません..ベストプラクティスについての私の理解を確認するためだけです)

この問題にどのように対処すればよいですか? c3p0 は最新のメカニズムではなく同期メソッドを使用しているため、実際にロックをテストすることはできません。

DataSourceクロージング コードから、最初にC3P0Registryロックを取得してからDataSource. 私は正しいロック順序を推測していますが、それが快適かどうかはわかりません。

ロギング呼び出しのロック順序を逆にすることはできないと思います。C3P0Registryのリストを取得するにはが必要なので、それらへの参照を取得するために最初にロックしDataSourcesないと をロックできませんでした。DataSourcesC3P0Registry

もちろん、別の解決策は、すべての c3p0 の上に別のより高いレベルのロックを提供することです。接続プールの場合、それはポイントを無効にしているようです。

今のところ、ログをロールバックしています。助けてくれてありがとう。

4

1 に答える 1

0

ロックの問題を解決する方法はわかりませんが、ここで一歩戻って元の問題について考えるべきだと思います。「アプリケーションでのデータベース接続の作成と破棄をログに記録しようとしています...」

以下をお勧めします。

クラスを作成し、javax.sql.DataSource を実装します。同じタイプのフィールドを作成し、すべてのメソッドをそれに委譲します。getConnection() メソッドでは、java.sql.Connection などをラップする独自の Connection クラスを返します。次に、このクラスを元のデータ ソースにラップします。クラスでは、単純にロガーを作成し、ログに表示したいすべてのアクションを記録できるようになりました。

于 2011-02-05T06:11:14.867 に答える