2

我正在尝试为批量查询爬虫操作创建一个抽象。这个想法是执行查询,获得结果集,并为每一行执行提交或回滚的操作。要求是所有行的处理与是否有故障无关,并且结果集没有预先加载到内存中。

问题归结为这样一个事实,即在回滚后无法维护打开的结果集。根据规范,游标可保持性在提交时可维护(使用 ResultSet.HOLD_CURSORS_OVER_COMMIT),但在回滚时不可维护。

一个带有 JTA/JDBC 语义的简单实现,提供两个扩展点,一个用于指定查询,一个用于指定每一行的实际操作,如下所示:

UserTransaction tx = getUserTransaction();
tx.begin();
ResultSet rs = executeQuery(); //extension point
tx.commit();
while(rs.next()) {
    tx.begin();
    try {
        performOperationOnCurrentRow(ResultSet rs); //extension point
        tx.commit();
        logSuccess();
    }catch(Exception e) {
        tx.rollback();
        logFailure(e);
    }
}

这似乎不是一个牵强的场景,但是我在网上发现的相关信息很少。问题是,任何流行的框架都优雅地解决了这个问题吗?我不一定需要开箱即用的解决方案,我只是想知道是否有一种已知的良好/普遍接受的方法来处理这种情况。

一种解决方案是跟踪失败的行并在该点之后重新打开游标,这通常需要强制执行一些扩展规则(例如,有序结果集、在 where 子句中使用最后失败的行 ID 进行查询等)。

另一种方法是使用两个不同的线程进行查询和行操作。

你会怎么办?

4

1 回答 1

1

由于这已经有几年没有回答了,我将继续自己回答。

我们制定的解决方案围绕着流程(称为BatchProcess)执行Query(不限于 SQL,请注意)并将其结果添加到并发的想法QueueBatchProcess生成许多QueueProcessor​​对象(在新线程上运行),这些对象使用条目并Queue执行Operation使用条目作为输入的条目。每次Operation执行都作为单个工作单元执行。底层事务管理器是一个 JTA 实现。

有点过时了,但在某些时候实施是这样的https://bo2.googlecode.com/svn/trunk/Bo2ImplOpen/main/gr/interamerican/bo2/impl/open/runtime/concurrent/BatchProcess.java

该仓库中的某处甚至还有一个用于 BatchProcess 监视和管理的 GUI;)

免责声明:这个人与这个设计和实现有很多关系https://stackoverflow.com/users/2362356/nakosspy

批处理对象的 UML 图

于 2014-08-01T12:14:29.043 回答