Java Spring和Hibernate的长时间运行事务?

Java Spring和Hibernate的长时间运行事务?,java,mysql,hibernate,spring,transactions,Java,Mysql,Hibernate,Spring,Transactions,我想要解决的基本问题是运行一个任务,在MySQL中生成几个临时表,这些临时表需要在创建后停留足够长的时间才能从Java获取结果。由于涉及的数据量很大,因此必须分批完成任务。每个批处理都是对通过JDBC调用的存储过程的调用。对于大型数据集,整个过程可能需要半小时或更长时间 为了确保对临时表的访问,我使用TransactionCallbackWithoutResult在一个Spring事务中运行整个任务start To finish。否则,我可能会得到一个不同的连接,该连接无法访问临时表(在将所有内

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

为了确保对临时表的访问,我使用TransactionCallbackWithoutResult在一个Spring事务中运行整个任务start To finish。否则,我可能会得到一个不同的连接,该连接无法访问临时表(在将所有内容打包到事务中之前,偶尔会发生这种情况)

这在我的开发环境中运行良好。然而,在生产中,我得到了以下例外:

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
在执行长时间运行的事务期间,当不同的任务试图访问某些相同的表时,就会发生这种情况。让我困惑的是,长时间运行的事务只会插入或更新到临时表中。对非临时表的所有访问仅为选择。从我可以找到的文档来看,默认的Spring事务隔离级别在这种情况下不应该导致MySQL阻塞

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


如果长时间运行的事务方法是正确的,我应该在隔离级别方面检查什么?我的理解是否正确,Spring/MySQL事务中的默认隔离级别不应该锁定仅通过SELECT访问的表?如何调试导致冲突的表,并防止这些表被事务锁定?

当您说您的表是临时表时,它是否属于事务范围?这可能会导致其他事务(可能在不同的事务上)无法查看/访问它。可能一个包含实表和临时表的连接会以某种方式锁定实表

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


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

< P>我认为把交易保持在一个延长的时间里是邪恶的。在我的职业生涯中,“扩展”的定义已经从秒下降到毫秒

它是不可重复问题和头颅断裂问题的无休止来源


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

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

您有“维护连接”问题的解决方案吗?在我的例子中,Spring和Hibernate调解了我与数据库的连接,我每次都很难获得相同的连接,而不是在单个事务中包装所有内容。如果不保持相同的连接,我将无法访问临时表。如果您保留一个带有id的工作日志以及批处理过程中达到的里程碑,则可以创建名为TEMP_uustuff的常规表。根据已达到的里程碑,您可以提前跳过并继续中止批处理过程。在处理完成一次(即达到里程碑完成)后,删除表并记录达到里程碑的“已清理”。现在可以使用细粒度事务完成所有处理。这种方法的不方便之处在于,当批处理作业启动时,您看不到数据库状态的“快照”。这可能是个问题,也可能不是。这是个很好的建议。然而,我还有一个问题。一些初始处理会创建在每个批中访问的临时表。这一初始处理需要大量的时间,如果必须对每个批次重复,这将对性能造成重大影响。我不确定如何处理这个初始处理,但我会再考虑一下。