由于各种原因,池中的连接可能会变得无效:服务器连接超时、网络问题......
我的理解是,Tomcat JDBC 连接池不对它提供给应用程序的连接的有效性提供任何保证。
为了防止(实际上只是降低风险)从池中获取无效连接,一个解决方案似乎是配置连接验证。验证连接意味着对数据库运行非常基本的查询(例如,SELECT 1;
在 MySQL 上)。
Tomcat JDBC 连接池提供了几个选项来测试连接。我觉得比较有趣的两个是 testOnBorrow
和 testWhileIdle
。
首先,我认为 testOnBorrow
是最佳选择,因为它基本上会在将连接提供给应用程序之前验证连接(最大频率由 validationInterval
定义)。
但过了一秒钟,我意识到在使用之前测试连接可能会影响应用程序的响应能力。所以我认为使用 testWhileIdle
可以更有效,因为它可以在未使用时测试连接。
无论我选择哪个选项,它们似乎只能降低获得无效连接的风险,但这种风险仍然存在。
所以我最后问:我应该使用 testOnBorrow
还是 testWhileIdle
还是两者混合使用?
顺便说一句,令我惊讶的是 validationInterval
不适用于 testOnReturn
并且我没有真正理解 testOnConnect
.
最佳答案
对此没有 100% 正确的答案。这是一个权衡和上下文的问题。
- 大多数时候,testOnBorrow 是风险最小的,因为它确保(尽可能地)在从池中返回连接供您使用之前,已经进行了基本的健全性检查客户端和数据库服务器处于对话状态。
- 它仍然不能阻止服务器连接断开的竞争条件,在进行“健全性检查”的时间和您的应用程序使用连接的时间之间。
但考虑到这是一个极端情况,testOnBorrow 提供了很好的保证。
现在需要权衡的是,每次您请求连接时,都会对数据库服务器进行一次查询(无论多么轻量级)。这可能很快,但成本仍然不为零。
如果您有一个繁忙的应用程序,具有非常好的数据库连接可靠性,那么您将开始从数据中看到,“对池中的每个连接请求进行有效性检查”的成本超过了好处检测连接问题。
- 另一方面,如果您的应用程序不是一直很忙(就像大多数现实世界的应用程序一样),那么使用 testOnBorrow 选项会非常有益。
它最大程度地确保您在使用之前拥有良好的连接。特别是考虑到从失败的数据库操作中“无法轻松恢复”的成本(重试 + 手动干预 + 工作流程丢失等)。
现在想象一下,如果您有 testOnIdle 选项。这要求您的连接在进行健全性检查之前进入空闲状态(取决于连接的空闲超时)。
- 这是对 testOnBorrow 的性能改进,但它也有自己的缺点。
- 现实世界中的应用程序到数据库的连接不仅仅是基于空闲超时的中断,它们还可以根据防火墙规则、网络拥塞、正在维护/修补的数据库服务器等进行删除。
- 因此,当您没有任何类型的“连接验证”时,它又回到了数据中观察到的连接错误数量的数据测量。
- 使用此选项需要注意的一件事是,当您的池在最大连接数下运行最佳且您的应用程序运行良好时,以及出于某种原因,如果您的数据库服务器经历了重启或类似情况。所有实时连接(从客户端的角度来看)现在大部分都会出错,直到空闲超时开始。因此,您的数据库问题(这本来是一场交火)现在有点复杂,直到应用程序连接再次恢复正常或者您也重新启动应用程序。
最后一个数据点是,对于某些应用程序,关键路径不是“验证查询”时间(希望在较低毫秒内)。应用程序有更大的问题需要处理。当然,对于某些应用程序来说,这段时间非常重要。
关于Tomcat JDBC 连接池 : testOnBorrow vs testWhileIdle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41998490/