我正在尝试使用c3p0的ConnectionCustomizer
在我们的应用程序中记录数据库连接的创建和销毁。在其中,我有一些看起来像这样的代码:
log(C3P0Registry.getPooledDataSources())
我遇到了僵局。我发现c3p0在其库中至少有几个使用synchronized方法的对象,并且似乎没有指定它们的预期锁定顺序。当我记录连接时,我正在对C3P0Registry
进行锁定,最终PoolBackedDataSource
(只是创建数据源列表正在访问导致锁定的哈希码)。
关闭连接提供程序(调用C3P0ConnectionProvider.close()
)会导致以相反的顺序调用锁。但是当子数据源被关闭时,我的日志记录正在被触发。结果是僵局。
似乎我在c3p0库中进行的两次调用都是有效的,预期的调用:
C3P0ConnectionProvider.close()
C3P0Registry.getPooledDataSources()
似乎(除非在文档中明确说明)它应该是图书馆负责管理它自己的锁定策略。 (我不是说这应该责怪任何人......只是为了确认我对最佳实践的理解)
我该如何处理这个问题?由于c3p0使用的是同步方法而不是更现代的机制,我无法真正测试锁。
在我的DataSource
结束代码中,我可以先关闭C3P0Registry
锁定,然后再关闭DataSource
。我会猜测正确的锁定顺序,我不知道我是否感到满意。
我认为我无法反转日志记录调用的锁定顺序。我需要C3P0Registry
来获取DataSources
的列表,因此我无法在未先锁定DataSources
的情况下锁定C3P0Registry
以获取对它们的引用。
另一种解决方案当然是在c3p0的所有内容之上提供另一个更高级别的锁定。在连接池的情况下,这似乎打败了这一点。
现在,我正在回滚我的伐木。谢谢你的帮助。
答案 0 :(得分:0)
我不知道如何解决锁定问题,但我认为你应该退一步思考原始问题。 “我正在尝试在我们的应用程序中记录数据库连接的创建和销毁......”
我会推荐以下内容。
创建一个类并使其实现javax.sql.DataSource。 创建相同类型的字段并将所有方法委托给它。 在getConnection()方法中,返回自己的Connection类环绕 java.sql.Connection等。 然后将此类包装在原始数据源周围。 在您的课程中,您现在只需创建一个记录器并记录您希望在日志中看到的所有操作。