解析巨大的 XML - 记住上次成功处理的节点,以便在下次运行时设置偏移量


Parse huge XML - remember last successfully processed node to set offset on next run

我有一些非常大的xml文件用于计划导入。我使用 cron 来解析它们。问题是处理需要太多时间,并且总是超过php"max_execution_time"。由于我使用 XMLReader,这允许"逐行"读取 xml,这是我看到的唯一解决方案:跟踪当前的工作"节点",记住它并在下一次 cron 运行时设置节点偏移量。

现在我有

  $xml = new XMLReader;
  $xml->open($file);
  $pointer = 0;
  while($xml->read()) {
    if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'Product') {
      $chunk = array();
      $chunk['ProductID'] = $xml->getAttribute('ProductID');
      $chunk['ProductName'] = $xml->getAttribute('ProductName');
      process_import($chunk); // Process received date
      save_current_node_in_BD($pointer++); // insert current position in BD
    }
  }
  $xml->close();
}

使用 $pointer++ 对已处理的节点进行计数是个好主意吗?如何为下一次 cron 运行设置偏移量?

首先,当你从cron执行php时,你通常使用默认max_execution_time为0(禁用)的cli版本。如果您无法更改,请继续阅读。

如果您的 XML 可以在时间内解析(仅解析,不处理),则可以有两个 crons:

  1. 第一个 cron 将解析 XML 并将新任务转储到一堆上。
  2. 第二个 cron 将从堆中获取工作,处理它,然后将其从堆中删除。

桩可以通过几种方式实现,其中包括:

  • 数据库表
  • 工作项
  • 目录(每个工作项是一个文件)

编辑

如果无法禁用执行时间限制,则可以保留一个包含文件名和位置的小文件。在每次迭代中,您可以打开此文件以确定是否仍有工作要做。为了确保它在时间用完时保存该文件,您需要注册一个关闭函数。