使用Spring和Hibernate进行长时间的事务处理?

时间:2010-06-02 13:52:42

标签: java mysql hibernate spring transactions

我想要解决的基本问题是运行一个在MySQL中生成几个临时表的任务,这些表需要保持足够长的时间以便在创建Java后从Java中获取结果。由于涉及的数据大小,任务必须分批完成。每个批处理都是对通过JDBC调用的存储过程的调用。对于大型数据集,整个过程可能需要半个小时或更长时间。

为了确保访问临时表,我在一个带有TransactionCallbackWithoutResult的Spring事务中运行整个任务,从头到尾完成。否则,我可以得到一个不能访问临时表的不同连接(这会偶尔发生在我将事务包装在事务中之前)。

这在我的开发环境中运行良好。但是,在制作中我得到以下例外:

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction

在执行长时间运行的事务期间,当另一个任务尝试访问某些相同的表时,会发生这种情况。令我困惑的是长时间运行的事务只插入或更新到临时表中。对非临时表的所有访问都是仅选择。从我可以找到的文档中,默认的Spring事务隔离级别不应该导致MySQL在这种情况下阻塞。

所以我的第一个问题,这是正确的方法吗?我可以确保在没有长时间运行的事务的情况下通过Hibernate模板重复获得相同的连接吗?

如果长时间运行的事务方法是正确的,那么我应该检查隔离级别?我的理解是正确的,Spring / MySQL事务中的默认隔离级别不应该锁定只能通过选择访问的表吗?我该怎么做才能调试哪些表导致冲突,并防止这些表被事务锁定?

3 个答案:

答案 0 :(得分:6)

我认为保持交易开放时间长了一段时间。在我的职业生涯中,“扩展”的定义从几秒钟下降到毫秒。

这是一个无法解决的不可重复问题和头疼问题。

在这种情况下,我会咬紧牙关并在软件中保留一份“工作日志”,如果批次失败,您可以反向重播以清理。

答案 1 :(得分:1)

当你说你的表是临时的时,它的事务范围是什么?这可能导致其他事务(可能在不同的事务上)无法查看/访问它。也许涉及真实表和临时表的连接会以某种方式锁定真实表。

根本原因:您是否尝试过使用MySQL工具来确定锁定连接的内容?它可能类似于下一行锁定。我不太了解MySQL工具,但在oracle上你可以看到哪些连接阻塞了其他连接。

事务超时:您应该创建一个具有更长超时的第二个连接池/数据源。将该连接池用于长时间运行的任务。我认为您的生产环境“试图”通过检测卡住的连接来帮助您。

答案 2 :(得分:0)

正如Justin关于事务超时所提到的,我最近遇到了连接池(在我的案例中是Tomcat 7中的tomcat dbcp)的设置,该设置应该标记长时间运行的连接标记放弃然后关闭它们。在调整这些参数后,我可以避免这个问题。