Comments (16)
Interesting.. Also worth noting is that ALTER TABLE
causes in-progress transactions to be implicitly committed. I didn't look to see if these happen in the middle of a transaction or not but I'm definitely in favor of completely removing support for MyISAM wherever possible (see #105 for all reasons).
from magento-lts.
from magento-lts.
Following up on this I've been looking into the indexing that happens during checkout (specifically price & stock). I was seeing a couple of database errors when many orders were placed simultaneously:
- A deadlock on the event_* tables
- A duplicate insert error on the price indexer *_tmp tables
There are a few requirements to see this behaviour:
- The order must bring a product's inventory level below the 'Qty for Item's Status to Become Out of Stock' or 'Notify for Quantity Below'
- Ordered products must have backorders set to 'No backorders' or 'Allow Qty Below 0 and Notify Customer'
- The config option 'Display out of stock products' must be set to 'No'
While looking for the solution I found a few issues:
Some database transactions with missing/unsafe try catch blocks (though most are probably harmless)
The rest of the issues are related to Mage_CatalogInventory_Model_Observer::reindexQuoteInventory():
Stock & price indexers are called directly, bypassing the indexer locking and mode check.
- No locking can cause duplicate insert errors in the price index tmp tables
- The indexers always run, even if the indexer update mode is set to manual
If a product's stock status is likely to change (ie. it has fallen below the minimum qty) then its stock item is saved
- The stock items were loaded before the order was placed - they potentially contain stale data
- Saving the stock item triggers a full reindex (by all indexers) of the ordered products.
That last point is where things get very confusing - products are re-indexed multiple times:
- Stock indexer is run directly in reindexQuoteInventory()
- Stock indexer is run after the stock item is saved.
2a. When the stock indexer runs, it also registers a mass_action catalog_product index event.
2b. Once the stock indexer has finished, it forces the mass_action event to be processed - The price indexer is run directly in reindexQuoteInventory()
Step 2a. results in calls to Mage_Index_Model_Indexer::logEvent()
, which causes deadlocks if it is run at the same time as step 2b. (or any other indexer)
So the stock indexer will run 3 times, the price indexer 2 times, and any other indexers set to real time mode will run once.
EDIT: The stock indexer will run 2 times, the price indexer 2 times, and if set to real-time mode these indexers will run once: catalog_product_attribute, catalogsearch_fulltext
I'm just guessing really, but I think the original intention was to make sure the price indexer runs after the stock indexer, because the price index is responsible for hiding out of stock products. But it looks like the logic has been duplicated and is being run twice, once by reindexQuoteInventory()
and again by $stockItem->save()
. I don't think there is any reason for the other indexers to run, its just a side effect of the mass_action event.
I've created a couple of branches with a proof of concept alternative solution:
added index locking and removed stock item save
removed mass_action index event from stock item save
from magento-lts.
Here's a version I've been using in production
I doubt it can be accepted in its current state, but I'm unable to spend any more time on it so I'm leaving it here in case anyone else is interested.
The main benefits I've seen are:
- Reduced database errors under heavy checkout load
- Increased checkout performance (orders/min), especially for backordered/low stock items
from magento-lts.
This is excellent work, @bob2021! I don't have time to play with it at the moment but I would love to see this type of improvement get merged. I'd encourage you to go ahead and submit a PR, but just don't expect it to be merged really soon since it is pretty deep.
from magento-lts.
Thanks, I've split it up into a few PRs to try and make it easier
from magento-lts.
Firstly, thanks for the effort here.
Wanted to share a thought/idea with you, related to this topic, and get some feedback.
If promising (and not WTF are you doing!, are you MAD? results), I will go through effort to get a PR going.
So, my thought is as thus: If a product is not setup to do stock management, then is there any need to even initiate a re-index for stock (and price) for said product? I would think no.
Thus, in a store setup, where stock management is not done at all, or is limited to less products than the total products available, eliminating the final stock/price indexing in this routine (for some/all products in order) should improve matters.
Resulting code/patch that I done to eliminate those products:
diff --git a/docroot/app/code/core/Mage/CatalogInventory/Model/Observer.php b/docroot/app/code/core/Mage/CatalogInventory/Model/Observer.php
index 1e5f1664b..ab0daa8f4 100755
--- a/docroot/app/code/core/Mage/CatalogInventory/Model/Observer.php
+++ b/docroot/app/code/core/Mage/CatalogInventory/Model/Observer.php
@@ -737,6 +737,15 @@ class Mage_CatalogInventory_Model_Observer
}
}
+ /**
+ * get product stock setup.
+ * We only want to re-index products that actually have stock management setup
+ **/
+ $stockCollection = Mage::getModel('cataloginventory/stock_item')->getCollection()
+ ->addFieldToFilter('product_id' , array('in' => $productIds))
+ ->addFieldToFilter('manage_stock' , array('eq' => 1));
+ $productIds = $stockCollection->getColumnValues('product_id');
+
if (count($productIds)) {
Mage::getResourceSingleton('cataloginventory/indexer_stock')->reindexProducts($productIds);
}
Thoughts? See any issue I did not consider?
from magento-lts.
Any thoughts on this? Did you maybe find some time to test this / or even run in a production env?
from magento-lts.
I have been using this in a production environment for about 7 months now. Not implemented as a patch, but extended the actual observer with a custom module.
We used to have a lot of checkout lock issues, which was identified as stock indexing locking the tables, and caused issues with checkout (ye old lock table timeout error) especially under big load (major promotional periods)
I had actually forgotten about this code, most likely as we have never had any lock timeouts again.
I have this in my custom module for overriding the observer
<sales_model_service_quote_submit_success>
<observers>
<inventory>
<type>disabled</type>
</inventory>
<enjo_inventory>
<class>enjo_catalog/inventory_observer</class>
<method>reindexQuoteInventory</method>
</enjo_inventory>
</observers>
</sales_model_service_quote_submit_success>
and my custom class obviously extends the core one
class Enjo_Catalog_Model_Inventory_Observer extends Mage_CatalogInventory_Model_Observer
and my method:
public function reindexQuoteInventory($observer)
{
// Reindex quote ids
$quote = $observer->getEvent()->getQuote();
$productIds = array();
foreach ($quote->getAllItems() as $item) {
$productIds[$item->getProductId()] = $item->getProductId();
$children = $item->getChildrenItems();
if ($children) {
foreach ($children as $childItem) {
$productIds[$childItem->getProductId()] = $childItem->getProductId();
}
}
}
/**
* get product stock setup.
* We only want to re-index products that actually have stock management setup
**/
$stockCollection = Mage::getModel('cataloginventory/stock_item')->getCollection()
->addFieldToFilter('product_id', array('in' => $productIds))
->addFieldToFilter('manage_stock', array('eq' => 1));
$productIds = $stockCollection->getColumnValues('product_id');
if (count($productIds)) {
Mage::getResourceSingleton('cataloginventory/indexer_stock')->reindexProducts($productIds);
}
// Reindex previously remembered items
$productIds = array();
foreach ($this->_itemsForReindex as $item) {
$item->save();
$productIds[] = $item->getProductId();
}
Mage::getResourceSingleton('catalog/product_indexer_price')->reindexProductIds($productIds);
$this->_itemsForReindex = array(); // Clear list of remembered items - we don't need it anymore
return $this;
}
It is from this I derived the previously noted patch
Note: unless theer is a stock-out sale on the site, none of the products ever have stock management setup. So, for us, stock re-indexing hardly ever runs, which I think is a great improvement.
from magento-lts.
@bob2021 Suffering quite badly with timeouts at checkout in our shop and we have a lot of stock that needs inventory managed. Do you know if your modifications (the one you share as having been run in production) still works OK and is believed safe to put into production?
Thanks for yours (and everyone else's) hard work on figuring this out!
from magento-lts.
Hi @doctea, I left the job where I was working on this a few years ago so I can't say for sure if the changes still work ok. They were certainly running in production at the time I originally created this issue, but unfortunately that doesn't mean they will work well in your specific Magento deployment or that problems weren't found after I left that I just don't know about. From the comments on some of the PRs it seems like these patches have issues with 3rd party indexing modules.
What tables are you seeing lock timeouts on?
from magento-lts.
Hi @doctea, I left the job where I was working on this a few years ago so I can't say for sure if the changes still work ok. They were certainly running in production at the time I originally created this issue, but unfortunately that doesn't mean they will work well in your specific Magento deployment or that problems weren't found after I left that I just don't know about. From the comments on some of the PRs it seems like these patches have issues with 3rd party indexing modules.
What tables are you seeing lock timeouts on?
Thanks for getting back to me, @bob2021 ! Seeing sporadic timeout problems in many different tables, mostly customer and sales related. (Perhaps I'm conflating multiple issues but my investigations lead me here anyway -- timeouts seemed to surround order creation/indexing mostly).
I also found some problems when using the MantiCorp_SphinxSearch module (DDL statements can't be executed in a transaction..) but I think I found a way to work around that.
In the end I found that hundreds of downloadable products had stock management enabled unnecessarily, so I've disabled all of those and hopefully that'll solve the issue. I've got a local branch based on your patch ready to try if that doesn't work though :)
Thanks again!
from magento-lts.
Did this improvement materialize in a PR or did it remain in the discussion stage?
there are many PRs linked to this issue, thanks to the original author ;-)
from magento-lts.
This seems to be merged https://github.com/OpenMage/magento-lts/blob/v20.1.0-rc2/app/code/core/Mage/CatalogInventory/Model/Observer.php#L761
from #562
from magento-lts.
Not 100% correct. This is an overall discussion on the topic. The merge you are refering to was here: #562
from magento-lts.
@ProxiBlue Okay, thanks for making it clear.
from magento-lts.
Related Issues (20)
- Composer patches incompatible with shardj/zf1-future (1.23.2) HOT 3
- CHECK_ZERO_TOTAL fails with Discount making Quote Zero HOT 1
- API session clean-up
- Allow valid TLDs to be configurable or allow that no validation takes place
- Underline active links in Backend menu (Next only) HOT 7
- Uncaught Error: Class "Zend_Controller_Request_Http" not found in get.php HOT 9
- Google Maps stopped working on all OpenMage instances after update to 3.54.1
- Ability to override Zend library HOT 1
- Deprecated functionality: imagecolorallocate() HOT 2
- Cm_RedisSession Module Rewrites Session Handler HOT 18
- Uncaught TypeError: Mage_Sales_Model_Quote::setCouponCode() HOT 11
- Composer patches not applied successfully HOT 5
- Timezone Setting Not Reflecting Outside of Mage.php HOT 2
- Incompatible interface deprecations in Mage_Core_Model_Resource_Session
- New event: mage_installed_exception (to i.e. forward exceptions to a 3rd party error logger, such as Sentry) HOT 2
- exception during reindex product prices HOT 1
- Missing default logo for base / rwd theme HOT 2
- Bug: source model adminhtml/system_config_source_cms_wysiwyg_skin is not found HOT 1
- category product list swatches always appear in_stock HOT 2
- Refresh updated_at date on mass product updates actions
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from magento-lts.