Php 在Drupal 8中保存数百个节点

Php 在Drupal 8中保存数百个节点,php,drupal,drupal-8,Php,Drupal,Drupal 8,我工作的公司正在为一个客户管理一个相当大的Drupal8和Mysql网站 每隔5分钟,我们通过cron导入大量数据(100到1000之间),这些数据以自定义实体类型(类似于节点实体)生成内容。在这个过程中,网站每分钟会收到大约300次浏览量 我们在使用Entity::create/Entity::save方法时遇到问题,因为我们的mysql在保存过程中的某个时候开始返回“SQLSTATE[40001]:序列化失败:尝试获取锁时发现1213死锁”。 有没有更好的方法来保存大量内容 我们认为问题不在

我工作的公司正在为一个客户管理一个相当大的Drupal8和Mysql网站

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

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

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

您应该尝试使用。Drupal 8很好地支持它们,可以与
数据库
或任何
存储
服务一起使用


这里是一个创建超过2000个节点的示例,一个接一个

// 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\u节点


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

要进一步了解,请查看(使用Ajax的UI批量操作)和(使用cron的后端批量操作)


希望它能帮助你

我添加了关于批量操作的第一个答案。但是,如果您向我们展示更多的代码,我们可以帮助您提高性能并修复瓶颈。感谢您的回答,但我需要的是一种允许mySql在不中断的情况下处理所有内容的方法,例如通过提交一次事务。如果使用您建议的方法,即使其中一个节点出现故障,也不会保存新节点。我需要他们不要失败。您知道是否可以使用类似于commit()的方法吗?谢谢。你可以在每次扑救时将试接球移动,而不是整个扑救。因此,它将只回滚最后一个失败的。这对您有帮助吗?这很好,但是drupal中是否有一种方法可以通过一个保存查询构建和创建所有节点。类似于插入条件中设置的值数组。