java如何使用MySQL后端设置Hibernate save()调用的超时?
上周,我们在一个基于Java和Hibernate的大型系统中遇到了一个问题。我们的后端MySQL数据库(托管在Amazon RDS上)在5-10分钟内没有响应(它仍然可以接受连接,但由于硬件问题,它的写入吞吐量降至零)。这段代码:
getSession().save(entity); //session is an instance of org.hibernate.Session
最后被吊了8.5分钟。所以很明显,在我的特定场景中,这个语句需要某种超时条件才能使它失败。我不能保证将来不会出现类似的硬件问题
我应该提到的是,我对Hibernate还是相当陌生的,所以我可能不理解一些事情,比如使用save()
与使用条件、事务等之间的关联。因此我发现了以下几点:
hibernate.c3p0.timeout
可用于设置C3P0连接池上的连接超时getSession().getTransaction().setTimeout(...)
可用于使事务超时getSession().createQuery(...).setTimeout(...)
可用于使查询超时- 我看过JPA2
javax.persistence.query.timeout
,但我不完全确定它是我想要的(我也不认为我的Hibernate版本足够新)
这些似乎都不是我想要做的(除了JPA2)。这看起来应该很简单。这里有我遗漏的东西吗
谢谢
# 1 楼答案
# 2 楼答案
我以前也找过类似的东西,但是在后端使用Oracle而不是MySQL。就我所见,在任何库中都没有实现这一点的机制,包括JDBC驱动程序。甚至你列出的超时,比如交易。setTimeout(),不要做你期望的事情。它们只需等待数据库语句完成执行,然后在超过给定超时时抛出TimeoutException。如果你有一个无限期挂起的查询,这是非常无用的。我发现的唯一一个现成的解决方案是在数据库本身上设置查询超时,在Oracle上这是一个全局设置,将影响对数据库的所有查询。这不是很有用。据我所知,要做你想做的事情,你必须启动一个单独的线程来计时查询,并在查询超时时以某种方式中断查询。我在Oracle或任何与数据库相关的库/框架中都找不到任何支持
# 3 楼答案
如果问题是前端响应性,可以考虑以最适合您的方式异步运行DB命中。那么你就不必为后端的及时性所累了。您可以使用JMS桥,或者如果您在Spring中,您可以使用
@Async
,或者任何其他异步的东西如果正在运行EJB,则可以在容器上设置事务超时,或者如果正在使用BMT,则可以在事务本身上设置事务超时。此设置将在超时后终止发送
或者,您也可以将数据库移动到本地