0

我正在尝试帮助客户解决 MySql DB 死锁。这些死锁似乎导致 API 调用需要 10-30 秒。我对 API 调用的重试逻辑至少尝试了 3 次。然而,我的应用程序在 3 次 API 调用后仍然失败,大部分时间是由于死锁。

我打印了“显示引擎 innodb 状态”。我改进了一些似乎困扰着这个 Magento 安装的 magento 查询。我仍然有这个似乎大部分时间都在状态中弹出的状态。我清除了缓存,截断了日志表,并删除了超过 60 天的 sales_flat_quote。

我会指出,这个 MySql 版本是 5.1。我正在考虑告诉客户他们应该升级到 5.5,这会解决大部分问题吗?

我注意到这个死锁是锁没有意义。第二笔交易不应该与该指数有问题(在我看来)。

这是 Magento Enterprise 1.12.1。

=====================================
140317 14:02:19 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 3 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 126213527, signal count 95958876
Mutex spin waits 0, rounds 23717002258, OS waits 75872845
RW-shared spins 28395611, OS waits 6711740; RW-excl spins 47024915, OS waits 2065225
------------------------
LATEST FOREIGN KEY ERROR
------------------------
140317 12:00:01  Cannot truncate table `testcom_testcom_migration`.`catalogsearch_query` by DROP+CREATE
InnoDB: because it is referenced by `testcom_testcom_migration`.`bss_cms_result`
------------------------
LATEST DETECTED DEADLOCK
------------------------
140317 14:02:07
*** (1) TRANSACTION:
TRANSACTION 0 496858972, ACTIVE 1 sec, process no 6717, OS thread id 139831325689600 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 23 lock struct(s), heap size 3024, 12 row lock(s), undo log entries 10
MySQL thread id 1260454, query id 109805416 localhost testcom_new updating
DELETE FROM `catalogrule_product_price` WHERE (product_id='12216')
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 846908 n bits 1272 index `IDX_CATALOGRULE_PRODUCT_PRICE_PRODUCT_ID` of table `testcom_testcom_migration`.`catalogrule_product_price` trx id 0 496858972 lock_mode X waiting
Record lock, heap no 252 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 00002fb8; asc   / ;; 1: len 4; hex 001abcde; asc     ;;

*** (2) TRANSACTION:
TRANSACTION 0 496858674, ACTIVE 8 sec, process no 6717, OS thread id 139831333410560 starting index read, thread declared inside InnoDB 500
mysql tables in use 1, locked 1
11259 lock struct(s), heap size 1013744, 561072 row lock(s), undo log entries 48
MySQL thread id 1260440, query id 109805651 localhost testcom_new Updating
UPDATE `index_process` SET `status` = 'require_reindex' WHERE (process_id='9')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 846908 n bits 1272 index `IDX_CATALOGRULE_PRODUCT_PRICE_PRODUCT_ID` of table `testcom_testcom_migration`.`catalogrule_product_price` trx id 0 496858674 lock mode S
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 00002df7; asc   - ;; 1: len 4; hex 001abbf7; asc     ;;

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 00002df7; asc   - ;; 1: len 4; hex 001abbf8; asc     ;;
....
....
....
etc....

附加信息

显示创建表 index_process

CREATE TABLE `index_process` (
 `process_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Process Id',
 `indexer_code` varchar(32) NOT NULL COMMENT 'Indexer Code',
 `status` varchar(15) NOT NULL DEFAULT 'pending' COMMENT 'Status',
 `started_at` timestamp NULL DEFAULT NULL COMMENT 'Started At',
 `ended_at` timestamp NULL DEFAULT NULL COMMENT 'Ended At',
 `mode` varchar(9) NOT NULL DEFAULT 'real_time' COMMENT 'Mode',
 PRIMARY KEY (`process_id`),
 UNIQUE KEY `UNQ_INDEX_PROCESS_INDEXER_CODE` (`indexer_code`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='Index Process'

显示创建表目录rule_product_price

CREATE TABLE `catalogrule_product_price` (
 `rule_product_price_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Rule Product PriceId',
 `rule_date` date NOT NULL DEFAULT '0000-00-00' COMMENT 'Rule Date',
 `customer_group_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Customer Group Id',
 `product_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Product Id',
 `rule_price` decimal(12,4) NOT NULL DEFAULT '0.0000' COMMENT 'Rule Price',
 `website_id` smallint(5) unsigned NOT NULL COMMENT 'Website Id',
 `latest_start_date` date DEFAULT NULL COMMENT 'Latest StartDate',
 `earliest_end_date` date DEFAULT NULL COMMENT 'Earliest EndDate',
 PRIMARY KEY (`rule_product_price_id`),
 UNIQUE KEY `UNQ_CATRULE_PRD_PRICE_RULE_DATE_WS_ID_CSTR_GROUP_ID_PRD_ID` (`rule_date`,`website_id`,`customer_group_id`,`product_id`),
 KEY `IDX_CATALOGRULE_PRODUCT_PRICE_CUSTOMER_GROUP_ID` (`customer_group_id`),
 KEY `IDX_CATALOGRULE_PRODUCT_PRICE_WEBSITE_ID` (`website_id`),
 KEY `IDX_CATALOGRULE_PRODUCT_PRICE_PRODUCT_ID` (`product_id`),
 CONSTRAINT `FK_CATALOGRULE_PRODUCT_PRICE_WEBSITE_ID_CORE_WEBSITE_WEBSITE_ID` FOREIGN KEY (`website_id`) REFERENCES `core_website` (`website_id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `FK_CATRULE_PRD_PRICE_CSTR_GROUP_ID_CSTR_GROUP_CSTR_GROUP_ID` FOREIGN KEY (`customer_group_id`) REFERENCES `customer_group` (`customer_group_id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `FK_CATRULE_PRD_PRICE_PRD_ID_CAT_PRD_ENTT_ENTT_ID` FOREIGN KEY (`product_id`) REFERENCES `catalog_product_entity` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1805881 DEFAULT CHARSET=utf8 COMMENT='CatalogRule Product Price'
4

1 回答 1

1

不是查询,而是事务(!)确实发生冲突。事务 2 在 上持有共享锁catalogrule_product_price。事务 1 尝试更新catalogrule_product_price并为此需要一个排他锁。这锁定。
由于您删除了日志事务 2 的下部,我们无法看到更多细节以及最终导致死锁的原因。请提供完整的日志。

顺便说一下,事务 2 运行时间相当长。它已经激活了 8 秒,并锁定了相同的时间。这对应用程序不利。您可能想阅读应对死锁的技巧,它基本上说应该尝试通过更改查询执行来避免死锁。

列出的另一个提示是使用较低的隔离级别,提到READ COMMITTED,但我认为这在这里没有帮助(但你应该试一试!)。

您应该仔细查看长时间运行的事务(和相应的脚本)在做什么。搜索此更新查询的代码

UPDATE `index_process` SET `status` = 'require_reindex' WHERE (process_id='9')

并分析相应的脚本做了什么。

您的主要问题是该脚本长时间锁定行(产品价格行),这可能在您的应用程序中广泛使用。为了避免这种情况,您可以通过将事务隔离级别设置为来避免它获取的共享锁READ UNCOMMITTED,但要了解设置此事务级别的含义。该脚本可能会使用旧数据。如果你能负担得起这个缺点,这可能会解决你的问题。

更新MySQL 很可能无法解决您的问题。死锁不依赖于版本。(但您可能仍想更新,因为从 5.1 到 5.5 有一些严重的执行改进。例如,关于优化器。)

于 2014-03-21T13:21:35.680 回答