Magento deadlocks

werd picture werd · Nov 9, 2012 · Viewed 12.6k times · Source

I am using Magento 1.7.0.2 Community Edition and I have encountered a big problem - deadlocks and "Lock wait timeout exceeded" errors. Problem exists while specific CRON tasks are executed

  • Importing/updating products(sizes, colors, manufacturers as well). There are around 5000 products but in 90% script gets "Lock wait timeout exceeded" errors or a deadlock error. Script is developed using Magento guidelines and it works fine if no other processes are running. For example if reindex is running, we get an error for sure. It seams that is because of table locks
  • Magento puts a read lock in some cases. I have read several topics about this already and the only proper solution seams to be changing /lib/Zend/Db/Statement/Pdo.php _execute function. As we are looking forward for upgrading Magento to the latest stable version we can`t afford changing core files.

So my question - is there a way how to avoid this(whether on PHP, MySQL or server(we use nginx) level)?

Answer

james picture james · Nov 12, 2012

I came across this issue whilst trying to import more than five or six products at once. There is more information on deadlocks available here.

To solve this problem I had to place my database queries in SERIALIZABLE transactions where possible, like so:

$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

Transaction example:

$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;
}

If you require any further help on this, feel free to let me know.