1

我正在将休眠 3 与 c3p0 一起用于一个程序,该程序不断地从某个源中提取数据并将其写入数据库。现在的问题是,数据库可能由于某些原因变得不可用(在最简单的情况下:我只是将其关闭)。

如果任何内容即将写入数据库,则不应出现任何异常 - 查询应一直等待,直到数据库再次可用。如果我没记错的话,这是连接池可以为我做的事情之一:如果数据库有问题,只需重试连接——在最坏的情况下是无穷大。

但相反,我得到了一个损坏的管道异常,有时随后是连接被拒绝,然后异常被传递给我自己的代码,这不应该发生。

即使我捕捉到异常,我怎么能再次干净地重新初始化休眠?(到目前为止,在没有 c3p0 的情况下,我只是再次构建了会话工厂,但如果这会泄漏连接(或者这样做可以吗?),我不会感到惊讶。

该数据库是 Virtuoso 开源版本。

我的 hibernate.xml.cfg c3p0 配置:

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
<property name="hibernate.c3p0.breakAfterAcquireFailure">false</property>
<property name="hibernate.c3p0.acquireRetryAttempts">-1</property>
<property name="hibernate.c3p0.acquireRetryDelay">30000</property>
<property name="hibernate.c3p0.automaticTestTable">my_test_table</property>

<property name="hibernate.c3p0.initialPoolSize">3</property>
<property name="hibernate.c3p0.minPoolSize">3</property>
<property name="hibernate.c3p0.maxPoolSize">10</property>

顺便说一句:创建了测试表,我得到了大量的调试输出 - 所以它似乎实际上读取了配置。

4

4 回答 4

3

如果我没记错的话,这是连接池可以为我做的事情之一:如果数据库有问题,只需重试连接 - 在最坏的情况下是无限的。

你错了。连接池只是...一个连接池,它包含一些已建立的与数据库的物理连接,用于避免在需要其中一个连接时创建这些连接的开销。

也就是说,这些连接可能会变得陈旧(例如,如果您重新启动数据库)。幸运的是,大多数连接池都可以配置为测试连接是否仍然有效,并在分发它们之前更新它们。c3p0 支持此功能,如配置连接测试中所述,您实际上已经在使用各种选项之一。所以当数据库恢复时你的连接应该被更新。

但是不要指望您的应用程序会在数据库出现故障时神奇地挂起,池不会这样做。

于 2009-10-30T23:06:54.533 回答
1

好吧,BoneCP 似乎已经实现了这一点。它可以设置为记录事务并在网络或数据库故障时重播:

http://jolbox.com/bonecp/downloads/site/apidocs/com/jolbox/bonecp/BoneCPConfig.html#setTransactionRecoveryEnabled(boolean)

于 2010-06-12T14:48:41.307 回答
0

谢谢你的回答。看来我还没有真正理解该部分的最后一段 http://www.mchange.com/projects/c3p0/index.html#configuring_recovery

因为一开始似乎 c3p0 可以做到(检测陈旧的连接并重试获取所有永恒的连接,而不会向应用程序代码抛出异常(当然,除非它的错误与 sql 语句相关而不是与连接相关),但在最后一段中 - 以非常混乱的方式编写 - 似乎 c3p0 无法确保 100%。

所以我的解决方案是为我需要的 jdbc Connection 接口的方法制作一个小包装器,如果由于连接错误导致查询失败,它会尝试重新连接。当然它有点hacky,因为我宁愿让我的组件使用标准的连接接口而不是我自己的接口,但至少它现在可以干净地工作。

于 2009-11-02T10:25:21.693 回答
0

你忘记了:

  • 你已经开始的交易呢?
  • 已经发送到数据库的任何准备好的语句呢?
  • ETC

因此,您的应用程序将不得不重新启动事务。我能想到的唯一可能的方法是让连接池跟踪对连接句柄的每次调用并在出现错误时重播这些调用,但这会大大减慢连接池的速度。

在 BoneCP ( http://jolbox.com ) 的情况下,池通过首先捕获 JDBC 驱动程序抛出的异常并通过将该连接标记为错误或通过重新创建整个连接池来处理它来检测发生故障.

编辑:现在正在处理。

于 2009-11-11T14:40:50.240 回答