Async order grid indexing setting can't be enabled in production mode (store config / MSI)
- 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
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