magento / magento/magento2

Async order grid indexing setting can't be enabled in production mode (store config / MSI)

Open
#36,070 5 comments 0 reactions 0 assignees View on GitHub
feature request Issue: ready for confirmation Progress: ready for grooming Reported on 2.4.5
Dominant language
PHP
Stars
12.2k
Forks
9.4k
PR merge metrics
No merged PRs in 30d

Description

### Preconditions and environment

- Magento version: latest
- Production mode
- MSI enabled

### Steps to reproduce

1. enable production mode (and MSI)
2. go to store config
3. try to enable async order grid indexing under Stores > Settings > Configuration > Advanced > Developer > Grid Settings > Asynchronous indexing as described in [Devdocs](https://experienceleague.adobe.com/docs/commerce-operations/performance-best-practices/configuration.html?mt=false#asynchronous-order-data-processing)

### Expected result

The config option for async order grid indexing should be visible in production mode

Background: the reason stated for this config option in [Devdocs](https://experienceleague.adobe.com/docs/commerce-operations/performance-best-practices/configuration.html?mt=false#asynchronous-order-data-processing) is

> There can be times when intensive sales on a storefront occur at the same time that Commerce is performing intensive order processing.

It makes no sense for this config option to be visible in developer mode only. There are no intensive sales in developer mode.
However, there are intensive sales in production mode.

### Actual result

The config option for async order grid indexing is not visible in production mode

### Additional information

We have database deadlocks with sales_order_grid table because we can't enable async order grid indexing in store config

Stack trace

`SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction, query was: INSERT INTO `sales_order_grid` (`entity_id`, `status`, `store_id`, `store_name`, `customer_id`, `base_grand_total`, `base_total_paid`, `grand_total`, `total_paid`, `increment_id`, `base_currency_code`, `order_currency_code`, `shipping_name`, `billing_name`, `created_at`, `updated_at`, `billing_address`, `shipping_address`, `shipping_information`, `customer_email`, `customer_group`, `subtotal`, `shipping_and_handling`, `customer_name`, `payment_method`, `total_refunded`, `pickup_location_code`, `mailchimp_flag`) SELECT sales_order.entity_id AS `entity_id`, sales_order.status AS `status`, sales_order.store_id AS `store_id`, sales_order.store_name AS `store_name`, sales_order.customer_id AS `customer_id`, sales_order.base_grand_total AS `base_grand_total`, sales_order.base_total_paid AS `base_total_paid`, sales_order.grand_total AS `grand_total`, sales_order.total_paid AS `total_paid`, sales_order.increment_id AS `increment_id`, sales_order.base_currency_code AS `base_currency_code`, sales_order.order_currency_code AS `order_currency_code`, TRIM(CONCAT_WS(' ', IF(`sales_shipping_address`.`firstname` <> '', `sales_shipping_address`.`firstname`, NULL), IF(`sales_shipping_address`.`lastname` <> '', `sales_shipping_address`.`lastname`, NULL))) AS `shipping_name`, TRIM(CONCAT_WS(' ', IF(`sales_billing_address`.`firstname` <> '', `sales_billing_address`.`firstname`, NULL), IF(`sales_billing_address`.`lastname` <> '', `sales_billing_address`.`lastname`, NULL))) AS `billing_name`, sales_order.created_at AS `created_at`, sales_order.updated_at AS `updated_at`, TRIM(CONCAT_WS(',', IF(`sales_billing_address`.`company` <> '', `sales_billing_address`.`company`, NULL), IF(`sales_billing_address`.`street` <> '', `sales_billing_address`.`street`, NULL), IF(`sales_billing_address`.`city` <> '', `sales_billing_address`.`city`, NULL), IF(`sales_billing_address`.`region` <> '', `sales_billing_address`.`region`, NULL), IF(`sales_billing_address`.`postcode` <> '', `sales_billing_address`.`postcode`, NULL))) AS `billing_address`, TRIM(CONCAT_WS(',', IF(`sales_shipping_address`.`company` <> '', `sales_shipping_address`.`company`, NULL), IF(`sales_shipping_address`.`street` <> '', `sales_shipping_address`.`street`, NULL), IF(`sales_shipping_address`.`city` <> '', `sales_shipping_address`.`city`, NULL), IF(`sales_shipping_address`.`region` <> '', `sales_shipping_address`.`region`, NULL), IF(`sales_shipping_address`.`postcode` <> '', `sales_shipping_address`.`postcode`, NULL))) AS `shipping_address`, sales_order.shipping_description AS `shipping_information`, sales_order.customer_email AS `customer_email`, sales_order.customer_group_id AS `customer_group`, sales_order.base_subtotal AS `subtotal`, sales_order.base_shipping_amount AS `shipping_and_handling`, TRIM(CONCAT_WS(' ', IF(`sales_order`.`customer_firstname` <> '', `sales_order`.`customer_firstname`, NULL), IF(`sales_order`.`customer_lastname` <> '', `sales_order`.`customer_lastname`, NULL))) AS `customer_name`, sales_order_payment.method AS `payment_method`, sales_order.total_refunded AS `total_refunded`, inventory_pickup_location_order.pickup_location_code AS `pickup_location_code`, sales_order.mailchimp_flag AS `mailchimp_flag` FROM `sales_order`
LEFT JOIN `sales_order_address` AS `sales_shipping_address` ON sales_order.shipping_address_id = sales_shipping_address.entity_id
LEFT JOIN `sales_order_address` AS `sales_billing_address` ON sales_order.billing_address_id = sales_billing_address.entity_id
LEFT JOIN `sales_order_payment` ON sales_order.entity_id = sales_order_payment.parent_id
LEFT JOIN `inventory_pickup_location_order` ON sales_order.entity_id = inventory_pickup_location_order.order_id WHERE (sales_order.entity_id = '23370') ON DUPLICATE KEY UPDATE `entity_id` = VALUES(`entity_id`), `status` = VALUES(`status`), `store_id` = VALUES(`store_id`), `store_name` = VALUES(`store_name`), `customer_id` = VALUES(`customer_id`), `base_grand_total` = VALUES(`base_grand_total`), `base_total_paid` = VALUES(`base_total_paid`), `grand_total` = VALUES(`grand_total`), `total_paid` = VALUES(`total_paid`), `increment_id` = VALUES(`increment_id`), `base_currency_code` = VALUES(`base_currency_code`), `order_currency_code` = VALUES(`order_currency_code`), `shipping_name` = VALUES(`shipping_name`), `billing_name` = VALUES(`billing_name`), `created_at` = VALUES(`created_at`), `updated_at` = VALUES(`updated_at`), `billing_address` = VALUES(`billing_address`), `shipping_address` = VALUES(`shipping_address`), `shipping_information` = VALUES(`shipping_information`), `customer_email` = VALUES(`customer_email`), `customer_group` = VALUES(`customer_group`), `subtotal` = VALUES(`subtotal`), `shipping_and_handling` = VALUES(`shipping_and_handling`), `customer_name` = VALUES(`customer_name`), `payment_method` = VALUES(`payment_method`), `total_refunded` = VALUES(`total_refunded`), `pickup_location_code` = VALUES(`pickup_location_code`), `mailchimp_flag` = VALUES(`mailchimp_flag`) [] []
#0 /var/www/webroot/ROOT/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php(627): Magento\Framework\DB\Adapter\Pdo\Mysql->_query()
#1 /var/www/webroot/ROOT/vendor/magento/module-sales/Model/ResourceModel/Grid.php(109): Magento\Framework\DB\Adapter\Pdo\Mysql->query()
#2 /var/www/webroot/ROOT/vendor/magento/module-sales/Observer/GridSyncInsertObserver.php(64): Magento\Sales\Model\ResourceModel\Grid->refresh()
#3 /var/www/webroot/ROOT/vendor/magento/framework/Event/Invoker/InvokerDefault.php(88): Magento\Sales\Observer\GridSyncInsertObserver->execute()
#4 /var/www/webroot/ROOT/vendor/magento/framework/Event/Invoker/InvokerDefault.php(74): Magento\Framework\Event\Invoker\InvokerDefault->_callObserverMethod()
#5 /var/www/webroot/ROOT/vendor/magento/framework/Event/Manager.php(66): Magento\Framework\Event\Invoker\InvokerDefault->dispatch()
#6 /var/www/webroot/ROOT/generated/code/Magento/Framework/Event/Manager/Proxy.php(95): Magento\Framework\Event\Manager->dispatch()
#7 /var/www/webroot/ROOT/vendor/magento/framework/Model/ResourceModel/Db/VersionControl/RelationComposite.php(53): Magento\Framework\Event\Manager\Proxy->dispatch()
#8 /var/www/webroot/ROOT/vendor/magento/framework/Model/ResourceModel/Db/VersionControl/AbstractDb.php(57): Magento\Framework\Model\ResourceModel\Db\VersionControl\RelationComposite->processRelations()
#9 /var/www/webroot/ROOT/vendor/magento/framework/Model/ResourceModel/Db/AbstractDb.php(424): Magento\Framework\Model\ResourceModel\Db\VersionControl\AbstractDb->processAfterSaves()
#10 /var/www/webroot/ROOT/vendor/magento/module-sales/Model/ResourceModel/Order.php(180): Magento\Framework\Model\ResourceModel\Db\AbstractDb->save()
#11 /var/www/webroot/ROOT/generated/code/Magento/Sales/Model/ResourceModel/Order/Interceptor.php(32): Magento\Sales\Model\ResourceModel\Order->save()
#12 /var/www/webroot/ROOT/vendor/magento/module-sales/Model/OrderRepository.php(282): Magento\Sales\Model\ResourceModel\Order\Interceptor->save()
...`

### Release note

_No response_

### Triage and priority

- [X] Severity: **S0** _- Affects critical data or functionality and leaves users without workaround._
- [ ] Severity: **S1** _- Affects critical data or functionality and forces users to employ a workaround._
- [ ] Severity: **S2** _- Affects non-critical data or functionality and forces users to employ a workaround._
- [ ] Severity: **S3** _- Affects non-critical data or functionality and does not force users to employ a workaround._
- [ ] Severity: **S4** _- Affects aesthetics, professional look and feel, “quality” or “usability”._

Contributor guide

Open the contributing guide

Research direction

Start at the Stores > Settings > Configuration > Advanced > Developer > Grid Settings path and compare its visibility in production and developer modes. Read the stack-trace entry points in vendor/magento/module-sales/Observer/GridSyncInsertObserver.php and vendor/magento/module-sales/Model/ResourceModel/Grid.php, then verify the configuration option is visible in production mode and the reported synchronous grid deadlock scenario is addressed.

Written by the indexing model from the issue text.

Assessment

Tech stack
mysql, php
Domain
backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.