在Drupal 8中保存数百个节点

时间:2017-09-24 12:09:34

标签: php drupal drupal-8

我工作的公司是为Drupal 8管理一个非常大的网站,为客户管理Mysql。

通过cron每5分钟我们导入大量数据(在100到1000之间),这些数据以自定义实体类型生成内容(类似于节点实体)。该网站在此过程中每分钟收到300次网页浏览。

我们遇到了Entity :: create / Entity :: save方法的问题,因为我们的mysql在保存过程中的某个时刻开始返回“SQLSTATE [40001]:序列化失败:1213在尝试获取锁定时发现死锁”。 有没有更好的方法来保存很多内容?

我们认为问题不在于服务器性能(8核和8GB RAM)。 Mysql也使用不同的工具进行了调整。

1 个答案:

答案 0 :(得分:0)

您应该尝试使用MySQL Transactions。 Drupal 8支持很好,Transaction class可用于database或任何storage服务。

这是一个创建超过2'000个节点的示例,一个接一个。

// Load services, should be injected in your Class/Service.

/** @var \Drupal\Core\Database\Connection $connection */
$connection = \Drupal::service('database');

/** @var \Drupal\node\NodeStorageInterface $nodeStorage */
$nodeStorage = \Drupal::service('entity_type.manager')->getStorage('node');

/** @var \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger */
$logger = \Drupal::service('logger.factory')->get('import-nodes');

// Save every node using transaction to avoid corruptions or MySQL failover on bulk creation.
$transaction = $connection->startTransaction();

// Nodes to be updated, up to thousands, change the code here.
$nodes = [
  3038 => [
    'title' => uniqid(),
  ],
  3039 => [
    'title' => uniqid(),
  ],
  // ...
];

try {
  foreach ($nodes as $nid => $node) {
    $new_node = $nodeStorage->create([
      'type'   => 'page',
      'bundle' => 'node',
      'title'  => $node['title'],
    ]);
    $new_node->save();
  }
}
catch (\Exception $e) {
  $transaction->rollback();
  $logger->error($e->getMessage());
}

您需要调整代码以检索$nodes& $new_node值。try-catch

使用事务将允许您通过安全回滚确保数据库完整性。例如。当您的脚本失败时(出于任何原因),事务将在{{1}}语句中回滚。

要进一步了解,请查看Batch API(使用Ajax进行UI批量操作),Batch API example& Queue Worker/API(使用cron进行后端批量操作)。

希望它会对你有所帮助!