Hibernate/C3P0: 有没有办法实时检查连接是否断开?
Hibernate/C3P0: Is there a way to check if the connection is down in real time?
我有一个应用程序,我们称之为 App.class
,它每秒检查一次数据库中的实时事件。
我遇到了数据库宕机的情况,App.class
不断重试并抛出异常。
我想实现的是实时判断是否有有效连接
我可以通过以下方式获取提供商:
C3P0ConnectionProvider provider = (C3P0ConnectionProvider) sessionFactoryImpl.getConnectionProvider()
我可以通过以下方式检查连接是否关闭:provider.getConnection().isClosed()
.
但是,如果数据库已关闭并且我尝试调用 provider.getConnection()
,App.class
会挂起一点(可能试图寻找连接),然后抛出异常。
我想知道是否有一种简单的方法来确定连接是否存在,而不仅仅是在连接发生时捕获 error/exception。
因此,c3p0 无法告诉您数据库是否 "down"。从形而上学和认识论上讲,它只是无法访问该信息。它只观察到网络墙上 DBMS 的影子。
c3p0 可以为您做一些事情:
- 它可以在将连接提供给您之前对其进行测试
- 它不能让你悬着
- 您可以提前询问是否有可能无需等待的连接。
听起来您已经要求 c3p0 在结帐时通过 hibernate.c3p0.validate
或 c3p0.testConnectionOnCheckout
为您测试连接。如果没有,当数据库关闭时,您不会看到您的应用程序在 getConnection() 上挂起,您只会在尝试使用 Connection 时看到失败。 (您可能会在签到和闲置时测试连接。下面会详细介绍这种可能性。)
您可以设置配置参数 c3p0.checkoutTimeout,而不是忍受挂起,这样如果 c3p0 没有良好的连接可以相对快速地交给您,它可以让您摆脱异常。
理想情况下,您可能更愿意在尝试签出并暂停之前提前知道是否有良好的连接可用。您可以通过 c3p0 的 PooledDataSource 接口上的方法询问 c3p0 连接是否可能立即可用。如果您有权访问 PooledDataSource pds
,您只需执行类似
的操作
int idle = pds.getNumIdleConnectionsDefaultUser();
并且可以知道如果至少有几个空闲连接,对 getConnection()
的调用是否可能很快成功。 (你不能保证,因为 c3p0 和 hibernate 是非常异步的,所以在你的检查和你的检查尝试之间,事情可能会改变。不,你不能尝试使用 synchronized
块或其他东西来使这些东西成为原子,c3p0 的池在内部进行锁定,而不是在外部 DataSource
级别。)
但即使有空闲连接,在测试之前您也不会知道它们是否良好,如果 DBMS 关闭,您将挂起,因为 c3p0 会尝试所有空闲连接,拒绝它们,然后徒劳地等待尝试获取连接。您希望 c3p0 预先测试连接,这样如果 none 正常,none 就显得空闲。
您无法完美地做到这一点,但您可以通过将结账时的连接测试替换为结账时的连接测试并结合空闲连接的频繁测试来接近。有关详细信息,请参阅 c3p0's docs。如果这样做,坏连接将很快从池中被逐出,空闲连接计数将接近空闲良好连接的计数。因此,您将有一些(尽管不完美)信心,如果您看到空闲连接,则 DBMS 已启动并且对 getConnection()
的调用将很快成功。在 DBMS 刚刚崩溃但 c3p0 尚未检测到它的时期用 checkoutTimeout
备份它,你将非常接近你想要的位置。
哦,要从休眠连接提供程序获取 PooledDataSource,looking at the source code,应该类似于...
import com.mchange.v2.c3p0.PooledDataSource;
PooledDataSource pds = provider.unwrap(PooledDataSource.class);
int idle = pds.getNumIdleConnectionsDefaultUser();
我还没有尝试过这段代码,而且我是在匆忙中写的(抱歉!),但是如果值得这么麻烦的话,那应该行得通。我认为大多数用户只是使用 c3p0.checkoutTimeout
来限制数据库中断的时间成本,而不会费心去获取 PooledDataSource
来询问空闲连接。但如果你需要它,你可以得到它。
我有一个应用程序,我们称之为 App.class
,它每秒检查一次数据库中的实时事件。
我遇到了数据库宕机的情况,App.class
不断重试并抛出异常。
我想实现的是实时判断是否有有效连接
我可以通过以下方式获取提供商:
C3P0ConnectionProvider provider = (C3P0ConnectionProvider) sessionFactoryImpl.getConnectionProvider()
我可以通过以下方式检查连接是否关闭:provider.getConnection().isClosed()
.
但是,如果数据库已关闭并且我尝试调用 provider.getConnection()
,App.class
会挂起一点(可能试图寻找连接),然后抛出异常。
我想知道是否有一种简单的方法来确定连接是否存在,而不仅仅是在连接发生时捕获 error/exception。
因此,c3p0 无法告诉您数据库是否 "down"。从形而上学和认识论上讲,它只是无法访问该信息。它只观察到网络墙上 DBMS 的影子。
c3p0 可以为您做一些事情:
- 它可以在将连接提供给您之前对其进行测试
- 它不能让你悬着
- 您可以提前询问是否有可能无需等待的连接。
听起来您已经要求 c3p0 在结帐时通过 hibernate.c3p0.validate
或 c3p0.testConnectionOnCheckout
为您测试连接。如果没有,当数据库关闭时,您不会看到您的应用程序在 getConnection() 上挂起,您只会在尝试使用 Connection 时看到失败。 (您可能会在签到和闲置时测试连接。下面会详细介绍这种可能性。)
您可以设置配置参数 c3p0.checkoutTimeout,而不是忍受挂起,这样如果 c3p0 没有良好的连接可以相对快速地交给您,它可以让您摆脱异常。
理想情况下,您可能更愿意在尝试签出并暂停之前提前知道是否有良好的连接可用。您可以通过 c3p0 的 PooledDataSource 接口上的方法询问 c3p0 连接是否可能立即可用。如果您有权访问 PooledDataSource pds
,您只需执行类似
int idle = pds.getNumIdleConnectionsDefaultUser();
并且可以知道如果至少有几个空闲连接,对 getConnection()
的调用是否可能很快成功。 (你不能保证,因为 c3p0 和 hibernate 是非常异步的,所以在你的检查和你的检查尝试之间,事情可能会改变。不,你不能尝试使用 synchronized
块或其他东西来使这些东西成为原子,c3p0 的池在内部进行锁定,而不是在外部 DataSource
级别。)
但即使有空闲连接,在测试之前您也不会知道它们是否良好,如果 DBMS 关闭,您将挂起,因为 c3p0 会尝试所有空闲连接,拒绝它们,然后徒劳地等待尝试获取连接。您希望 c3p0 预先测试连接,这样如果 none 正常,none 就显得空闲。
您无法完美地做到这一点,但您可以通过将结账时的连接测试替换为结账时的连接测试并结合空闲连接的频繁测试来接近。有关详细信息,请参阅 c3p0's docs。如果这样做,坏连接将很快从池中被逐出,空闲连接计数将接近空闲良好连接的计数。因此,您将有一些(尽管不完美)信心,如果您看到空闲连接,则 DBMS 已启动并且对 getConnection()
的调用将很快成功。在 DBMS 刚刚崩溃但 c3p0 尚未检测到它的时期用 checkoutTimeout
备份它,你将非常接近你想要的位置。
哦,要从休眠连接提供程序获取 PooledDataSource,looking at the source code,应该类似于...
import com.mchange.v2.c3p0.PooledDataSource;
PooledDataSource pds = provider.unwrap(PooledDataSource.class);
int idle = pds.getNumIdleConnectionsDefaultUser();
我还没有尝试过这段代码,而且我是在匆忙中写的(抱歉!),但是如果值得这么麻烦的话,那应该行得通。我认为大多数用户只是使用 c3p0.checkoutTimeout
来限制数据库中断的时间成本,而不会费心去获取 PooledDataSource
来询问空闲连接。但如果你需要它,你可以得到它。