5

我正在尝试使用 c3p0's 在我们的应用程序中记录数据库连接的创建和销毁ConnectionCustomizer。在其中,我有一些看起来像这样的代码:

log(C3P0Registry.getPooledDataSources())

我遇到了僵局。我发现 c3p0 在其库中至少有几个使用同步方法的对象,并且似乎没有指定它们预期的锁定顺序。当我记录连接时,我会锁定C3P0Registry并最终PoolBackedDataSource(只需创建数据源列表即可访问导致锁定的哈希码)。

关闭连接提供程序(调用C3P0ConnectionProvider.close())会导致以相反的顺序调用锁。但是,当子数据源被关闭时,我的日志记录被触发了。结果是死锁。

似乎我对 c3p0 库进行的两个调用都是有效的预期调用:

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

似乎(除非在文档中明确说明)管理它自己的锁定策略应该是库的责任。(我说这不是为了责怪任何人.. 只是为了确认我对最佳实践的理解)

我应该如何处理这个问题?由于 c3p0 使用同步方法而不是更现代的机制,因此我无法真正测试锁。

从我的DataSource关闭代码中,我可以C3P0Registry在关闭DataSource. 我会猜测正确的锁定顺序,我不知道我是否觉得舒服。

我不认为我可以反转日志调用的锁定顺序。我需要C3P0Registry来获取 的列表DataSources,所以如果DataSources没有先锁定C3P0Registry来获取对它们的引用,我就无法锁定 。

当然,另一种解决方案是在 c3p0 之上提供另一个更高级别的锁。在连接池的情况下,这似乎违背了这一点。

现在,我正在回滚我的日志记录。谢谢你的帮助。

4

1 回答 1

0

我不知道如何解决锁定问题,但我认为你应该退后一步,想想原来的问题。“我正在尝试在我们的应用程序中记录数据库连接的创建和破坏......”

我会推荐以下。

创建一个类并使其实现 javax.sql.DataSource。创建一个相同类型的字段并将所有方法委托给它。在 getConnection() 方法中,返回您自己的 Connection 类,包裹 java.sql.Connection 等等。然后将此类包装在您的原始数据源周围。在您的课程中,您现在可以简单地创建一个记录器并记录您希望在日志中看到的所有操作。

于 2011-02-05T06:11:14.867 回答