magento2: OOM/Timeouts when saving a category with large catalog as all product URLs are regenerated

With a catalog of many thousands of products loaded, saving a category causes long execution times and high memory usage, when it isn’t necessarily required. In a production environment, the execution fails with max_execution_time or memory_limit errors.

It appears that the system is trying to regenerate all URLs of products contained within the category and subcategories; even if the url_key is not modified.

Preconditions

  1. Magento 2.1.1
  2. max_execution_time set to 300
  3. memory_limit set to 2G
  4. Catalog of 140,000 products
  5. Top category which contains subcategories and 40,000+ products

Steps to reproduce

  1. Simply “Save” the top category without even making any changes

Expected result

  1. No errors
  2. A notice of You saved the category should appear

Actual result

  1. PHP errors for max_execution_time and/or memory_limit

A workaround is to modify /vendor/magento/module-catalog-url-rewrite/Observer/CategoryProcessUrlRewriteSavingObserver.php temporarily to return; on line 1 of the execute() function to prevent URL rewrite changes.

A suggested performance improvement would be to check if the url_key was modified before running the regeneration of URLs.

This, though, cannot be used if the url_key is updated. At that point, the process should be handled by some background task.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 5
  • Comments: 30 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Reopening as I have recently seen this happen on 2.2.7. There are a number of problems involved, one of them being that \Magento\UrlRewrite\Model\Storage\DbStorage::deleteOldUrls does not properly remove existing rewrites and allows clashes. It assumes that if there is not entity_id conflict in url_rewrite then there will be no conflict on the table but that’s not always true (as evidenced by the integrity constraint errors reported). Another is that when removing a product from a category it seems that Magento goes and updates all the other products in that category to reflect their new positions with that product removed, but then when those products are saved all of their URL rewrites are regenerated because the products are considered “changed” even though the url_key has not changed.

Any update on this?

One of my 2.1.4 merchants is experiencing this exact issue. They have a category that contains 538 children/descendent categories and those child categories contain a total of 5k+ products. Upon saving the category, the 768M native Magento memory limit is hit. Magento’s memory limit should not need to be increased to accommodate saving this category.

When the category is saved, the \Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver::updateUrlPathForChildren observer calls \Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver::updateUrlPathForChildren for all ~583 child categories. This behavior happens of regardless of whether “By Category” is set to “Anchor == Yes” or “Anchor == No”.

I profiled the category save using Xdebug and loaded the data in MacCallGrind and have included some screenshots below demonstrating how much of the processing time was used by the method mentioned above:

14-46-01 proxy php 2195x1393 -5h3sx

14-46-21 proxy php 2102x1416 -nhfi5

Our Upgraded version is 2.2.2 still having the same issue removing one product from the category and then saving category with 4k products taking 5mins to save and some time fails. can’t find this fix in new version too. checked in the file “CategoryProcessUrlRewriteSavingObserver.php” your code fix is not there. can you please verify?