在 Java 中,可以使用什么方法调查数据库连接使用情况?[已关闭]用于识别创建者的堆栈跟踪设置“陷阱”扩展想法

2022-09-04 20:30:17

在 Java 中,可以使用什么方法调查数据库连接使用情况?

开发人员正在支持一个复杂的Java程序,该程序偶尔会耗尽可用的数据库连接数。由于该问题是零星的,因此了解哪个线程已打开与数据库的多个连接以将精力集中在此区域会很有用。

最后,正确的解决方法似乎是重写程序以重用连接,而不是为每个线程打开多个连接。

我在问,开发人员应该在他的工具箱中拥有什么方法来调查资源,即线程分配的数据库连接。


答案 1

看看log4jdbc。它使您可以查看jdbc上的所有内容,包括打开/关闭连接以及连接号信息。


答案 2

不是特定的工具,而是一种调试技术,用于跟踪哪些代码负责打开连接或其他资源。

我假设您在java端使用一致的方法来获得数据库连接(池化与否无关紧要)。

这个想法是在连接工厂/池或其他任何东西周围创建一个非常轻的包装类。包装器将实现任何有意义的jdbc接口,因此您可以将其交换为普通连接对象,但大多数方法只会透明地调用/返回底层连接。最简单的方法是扩展你的DBConnection类是什么,并且只覆盖你需要监视的特定方法(不要忘记在适当的时候调用)。根据您的实现,您可能需要覆盖工厂以及连接。super.method()

如果您使用的是某种IoC框架(例如spring),您应该能够在配置级别轻松交换连接/工厂类。现在,您的所有 Java 代码都将使用新的 db 连接包装器。

如果您使用的是池,则调用通常只会将对象返回到池中,而不是破坏连接。因此,此技术适用于正常连接泄漏和“未返回到池(池已耗尽)”泄漏。connection.close()

现在,我们只需要记录有趣的位,并为泄漏的连接设置一个陷阱。

用于识别创建者的堆栈跟踪

在连接包装器的构造函数或工厂方法中,创建一个新对象,并将其作为本地/成员变量存储在包装器对象中以供以后使用。我们使用 a,因为它比使用 更快/更便宜。这会记录/牵连请求/建立连接的调用方。ThrowableThrowableThread.currentThread().getStackTrace()Throwable

设置“陷阱”

在包装类中实现该方法。这是 GC 在对象被销毁时调用的清理方法,因为它不再被使用。finalize

该方法应选中“我是否已关闭?如果已经关闭,那么一切都很好...但是,如果连接正在GCed并且尚未关闭...那么这是一个“泄漏”的连接。finalize

现在,它又开始发挥作用了。我们可以获取并输出一条漂亮的日志消息,内容如下:“我是一个泄露的连接,这里有一个堆栈跟踪,暗示我的创建者。ThrowableThrowable

扩展想法

这种方法可以适用于各种情况。当然,您可以将其他类型的数据保留在包装器中,以便对特定问题进行故障排除。例如创建时间。然后,您可以轮询长期连接,并再次牵连创建者。或者,您可以轮询现有连接并分析堆栈跟踪,以获取有关哪些代码在一段时间内使用了多少个连接的数据。Throwable

可能有一个现成的工具也可以做这些类型的事情,但在大多数情况下,应用这种技术所需的代码量非常少(假设你有一个简单的方法来交换我们的数据库连接/工厂,而无需搜索替换你的整个代码库)。但是,如果您需要搜索替换代码库的情况...这是清理代码以使用依赖关系注入的好机会,或者至少是一个中央工厂,您可以在其中更轻松地测试和控制数据库访问。


推荐