9

我正在使用 Magento 1.7.0.2 社区版,我遇到了一个大问题 - 死锁和“超过锁定等待超时”错误。执行特定CRON任务 时存在问题

  • 导入/更新产品(尺寸、颜色、制造商以及)。大约有 5000 种产品,但在 90% 的脚本中出现“超过锁定等待超时”错误或死锁错误。脚本是使用 Magento 指南开发的,如果没有其他进程正在运行,它可以正常工作。例如,如果 reindex 正在运行,我们肯定会得到一个错误。它接缝是因为表锁
  • Magento 在某些情况下会设置读锁。我已经阅读了几个关于此的主题,唯一合适的解决方案是更改/lib/Zend/Db/Statement/Pdo.php _execute 函数。由于我们期待将 Magento 升级到最新的稳定版本,我们无法承受更改核心文件的费用。

所以我的问题 - 有没有办法避免这种情况(无论是在 PHP、MySQL 还是服务器(我们使用 nginx)级别)?

4

5 回答 5

9

我在尝试一次进口超过五六种产品时遇到了这个问题。这里有更多关于死锁的信息。

为了解决这个问题,我必须尽可能将我的数据库查询放在SERIALIZABLE事务中,如下所示:

$adapter = Mage::getModel('core/resource')->getConnection('core_write');
// Commit any existing transactions (use with caution!)
if ($adapter->getTransactionLevel > 0) {
    $adapter->commit();
}
$adapter->query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');
$product->save(); // etc

交易示例:

$adapter = Mage::getModel('core/resource')->getConnection('core_write');
// Commit any existing transactions (use with caution!)
if ($adapter->getTransactionLevel > 0) {
    $adapter->commit();
}
$adapter->query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');
$adapter->beginTransaction();
try {
    $adapter->query(/* SQL goes here */);
    $adapter->commit();
} catch (Exception $e) {
    // Rollback on fail always
    $adapter->rollBack();
    throw $e;
}

如果您在这方面需要任何进一步的帮助,请随时告诉我。

于 2012-11-12T20:39:00.000 回答
4

我们遇到了类似的问题,当客户试图将某些东西添加到他们的购物车中时,每天会出现几次死锁。我们的似乎也与当时正在刷新的索引有关(很可能是目录表的重新索引)。最终为我们解决这个问题的唯一事情是实现异步重新索引(我们最终购买了一个扩展)。

于 2013-05-24T15:09:22.683 回答
3

我们在尝试并行保存产品时也遇到了这个问题。

我们面临的主要问题是,在最初保存产品后,随后的索引过程并未包含在产品保存事务中。因此,每当我们遇到死锁时,它都是由索引器引起的,最重要的是,我们有一个不一致的数据库,导致无效的产品 URL 并迫使我们在每次发生时重新索引所有内容。

我们最终得到的解决方案是将索引器包含在事务中并重试最终陷入死锁的事务。然而,这不是一个理想的解决方案,它是我们能想到的最好的解决方案,而且它在 99% 的时间内都有效。

magento 的问题在于编程是草率的,并且事件驱动的瑞士军刀编码方法在 magento 的内部机制中导致了许多深刻的问题。

我们的下一个方法将是我们自己的界面,从头开始编写,以并行保存产品并为数据库留下与 magento 保存相同的结果。这当然意味着我们不能再添加扩展而不将它们集成到这个新概念中,以防它们与产品相关。

于 2013-10-09T07:07:57.403 回答
1

这是很棒的开源解决方案 - https://github.com/AOEpeople/Aoe_DbRetry

该模块非常简单,专注于一项任务。它将数据库适配器替换为扩展版本,如果连接丢失、查询无法获得所需的锁或发生死锁,它将重试查询。这三种情况是通过异常消息检测到的。底层(父)代码实际上将这些异常中的至少一个包装在另一个异常中,因此我们检查它并在需要时解开异常。

于 2018-04-05T21:24:06.353 回答
0

在使用 CRON 脚本导入之前,我将索引模式设置为 MANUAL。

$indexCollection = Mage::getSingleton('index/indexer')->getProcessesCollection(); 
foreach ($indexCollection as $process) {
    $process->setMode(Mage_Index_Model_Process::MODE_MANUAL)->save();
    //$process->setMode(Mage_Index_Model_Process::MODE_REAL_TIME)->save();
}
于 2015-12-08T08:51:20.613 回答