From 90a8c48bae468ee98c6a48520470c20a50af0d69 Mon Sep 17 00:00:00 2001 From: Colin Mollenhour Date: Thu, 29 Sep 2016 11:11:06 -0400 Subject: [PATCH] [impr-#103] Significant deadlock potential in cataloginventory/stock resource model --- .../CatalogInventory/Model/Resource/Stock.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php b/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php index 15faa2397838..bfc990c3c703 100644 --- a/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php +++ b/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php @@ -131,11 +131,24 @@ public function getProductsStock($stock, $productIds, $lockRows = false) $productTable = $this->getTable('catalog/product'); $select = $this->_getWriteAdapter()->select() ->from(array('si' => $itemTable)) - ->join(array('p' => $productTable), 'p.entity_id=si.product_id', array('type_id')) ->where('stock_id=?', $stock->getId()) ->where('product_id IN(?)', $productIds) ->forUpdate($lockRows); - return $this->_getWriteAdapter()->fetchAll($select); + $rows = $this->_getWriteAdapter()->fetchAll($select); + + // Add type_id to result using separate select without FOR UPDATE instead + // of a join which causes only an S lock on catalog_product_entity rather + // than an X lock. An X lock on a table causes an S lock on all foreign keys + // so using a separate query here significantly reduces the number of + // unnecessarily locked rows in other tables, thereby avoiding deadlocks. + $select = $this->_getWriteAdapter()->select() + ->from($productTable, array('entity_id', 'type_id')) + ->where('entity_id IN(?)', $productIds); + $typeIds = $this->_getWriteAdapter()->fetchPairs($select); + foreach ($rows as &$row) { + $row['type_id'] = $typeIds[$row['product_id']]; + } + return $rows; } /**