Magento陷入僵局

时间:2012-11-09 13:50:23

标签: magento database-deadlocks

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

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

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

5 个答案:

答案 0 :(得分:9)

我在试图同时导入超过五六种产品时遇到了这个问题。有关死锁的更多信息here

要解决这个问题,我必须尽可能将数据库查询放在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;
}

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

答案 1 :(得分:4)

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

答案 2 :(得分:3)

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

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

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

magento的问题在于编程是slopy,事件驱动的swiss-army-knife编码方法导致了magento内部机制中的许多深层次问题。

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

答案 3 :(得分:1)

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

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

答案 4 :(得分: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();
}