我工作的公司是为Drupal 8管理一个非常大的网站,为客户管理Mysql。
通过cron每5分钟我们导入大量数据(在100到1000之间),这些数据以自定义实体类型生成内容(类似于节点实体)。该网站在此过程中每分钟收到300次网页浏览。
我们遇到了Entity :: create / Entity :: save方法的问题,因为我们的mysql在保存过程中的某个时刻开始返回“SQLSTATE [40001]:序列化失败:1213在尝试获取锁定时发现死锁”。 有没有更好的方法来保存很多内容?
我们认为问题不在于服务器性能(8核和8GB RAM)。 Mysql也使用不同的工具进行了调整。
答案 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进行后端批量操作)。
希望它会对你有所帮助!