hibernate c3p0 断管
我使用 hibernate 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>
顺便说一句:测试表已创建,我得到了大量的调试输出 - 所以看起来它实际上读取了配置。
I'm using hibernate 3 with c3p0 for a program which constantly extracts data from some source and writes it to a database.
Now the problem is, that the database might become unavailable for some reasons (in the simplest case: i simply shut it down).
If anything is about to be written to the database there should not be any exception - the query should wait for all eternity until the database becomes available again.
If I'm not mistaken this is one of the things the connection pool could do for me: if there is a problem with the db, just retry to connect - in the worst case for infinity.
But instead i get a broken pipe exception, sometimes followed by connection refused and then the exception is passed to my own code, which shouldn't happen.
Even if I catch the exception, how could i cleanly reinitialize hibernate again? (So far without c3p0 i simply built the session factory again, but i wouldn't be surprised if that could leak connections (or is it ok to do so?)).
The database is Virtuoso open source edition.
My hibernate.xml.cfg c3p0 config:
<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>
btw: The test table is created and i get tons of debug output- so it seems it actually reads the config.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你错了。连接池只是......一个连接池,它包含一些已经建立的到数据库的物理连接,用于避免在需要其中一个连接时创建这些连接的开销。
也就是说,这些连接可能会变得过时(例如,如果您重新启动数据库)。幸运的是,大多数连接池都可以配置为测试连接是否仍然有效并在分发连接之前更新它们。 c3p0 支持此功能,如配置连接测试中所述,您可以实际上已经在使用各种选项之一。因此,当数据库恢复时,您的连接应该更新。
但不要指望当数据库出现故障时您的应用程序会神奇地挂起,池不会这样做。
You're mistaken. A connection pool is just... a connection pool, it contains some already established physical connections to the database and is used to avoid the overhead of creating these connections when you need one of them.
That said, these connections can become stale (e.g. if you restart the database). Luckily, most connection pools can be configured to test if a connection is still valid and to renew them before to distribute them. c3p0 support this feature as documented in Configuring Connection Testing and you're actually already using one of the various options. So your connections should be renewed when the database comes back.
But don't expect your application to be magically suspended when the database goes down, a pool won't do this.
看来 BoneCP 确实实现了这一点。它可以设置为记录事务并在网络或数据库故障时重播:
http://jolbox.com/bonecp/downloads/site/apidocs/com/jolbox/bonecp/BoneCPConfig.html#setTransactionRecoveryEnabled(boolean)
Well it seems that BoneCP has actually implemented this. It can be set to record the transaction and replay it upon network or database failure:
http://jolbox.com/bonecp/downloads/site/apidocs/com/jolbox/bonecp/BoneCPConfig.html#setTransactionRecoveryEnabled(boolean)
谢谢你的回答。
看来我还没有真正理解本节的最后一段
http://www.mchange.com/projects/c3p0/index.html# configuration_recovery
因为一开始 c3p0 似乎可以做到这一点(检测过时的连接并重试永久获取连接,而不会向应用程序代码抛出异常(当然,除非它是与 sql 语句相关的错误而不是)到连接),但在最后一段中 - 以相当混乱的方式编写 - 似乎 c3p0 无法确保 100%
所以我的解决方案是为我需要的 jdbc 方法制作一个小包装器。连接接口,如果查询由于连接错误而失败,它会尝试重新连接当然这有点老套,因为我宁愿让我的组件使用标准连接接口而不是我自己的接口,但至少它可以干净地工作。现在。
Thank you for the answer.
It seems i just haven't really understood the last paragraph of the section
http://www.mchange.com/projects/c3p0/index.html#configuring_recovery
Because at first it seems c3p0 could do it (detect stale connections and retry to acquire connections for all eternity without ever throwing an exception to the application code (unless of course when its an error related to the sql statement and not to the connection), but in the last paragraph - which is written in pretty confusing way - it seems as if c3p0 can't ensure that to 100%.
So my solution was to make a small wrapper for the methods i needed from the jdbc Connection interface, which attempt to reconnect if a query fails due to a connection error. Of course its a bit hacky, because i'd rather have my components use the standard Connection-interface instead of my own interface, but at least its working cleanly now.
您忘记了:
,您的应用程序将必须重新启动事务。我能想到的唯一可能的方法是让连接池跟踪对连接句柄的每次调用,并在出现错误时重播这些调用,但这会大大减慢连接池的速度。
对于 BoneCP (http://jolbox.com),池通过捕获异常来检测是否发生了故障首先由 JDBC 驱动程序抛出,然后通过将该连接标记为错误或重新创建整个连接池来处理它。
编辑:目前正在处理中。
You're forgetting:
Your application will therefore have to restart the transaction. The only possible way I can think of is for the connection pool to keep track of every call to the connection handle and replay those in case of error but this would greatly slow down the connection pool.
In the case of BoneCP (http://jolbox.com), the pool detects a failure has occured by catching the exception thrown by the JDBC driver first and handling it by either flagging that connection as faulty or else by recreating the entire connection pool.
Edit: It's being handled now.