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

jim*_*kun 5 java mysql spring hibernate transactions

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

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

这在我的开发环境中运行良好.但是,在生产中我遇到以下异常:

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
Run Code Online (Sandbox Code Playgroud)

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

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

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

Pet*_*ans 6

我认为保持交易持续时间长.在我的职业生涯中,"扩展"的定义从几秒钟下降到毫秒.

它是不可重复的问题和头疼问题的无穷无尽的根源.

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


Jus*_*tin 1

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

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

事务超时:您应该创建第二个具有更长超时时间的连接池/数据源。使用该连接池来执行长时间运行的任务。我认为您的生产环境正在“尝试”通过检测卡住的连接来帮助您解决问题。