diff --git a/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php b/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php index 6f265f863e64..dcc19b96b37f 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; } /**