问题描述

在生产中有一条批量删除的 SQL,当并发量达到一定量后经常出现死锁问题。
本文首先在本地还原场景,然后简化模型,在简化模型上测试和验证,从而分析 MySQL 的机制以及问题出现的根因。最终得到解决方案,并在原场景中得到验证。

场景还原

DDL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CREATE TABLE `store_sku_stock` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `parent_store_id` varchar(64) NOT NULL COMMENT '父门店编号',
  `store_id` varchar(64) NOT NULL COMMENT '门店编号',
  `sku` varchar(64) NOT NULL COMMENT '商品sku',
  `avail_qty` int(11) DEFAULT '0' COMMENT '库存数量',
  `source_qty` int(11) DEFAULT '0' COMMENT 'DP下发库存',
  `safety_qty` int(11) DEFAULT '0' COMMENT '安全库存',
  `type` tinyint(4) NOT NULL COMMENT '1:当日库存,2.隔日库存',
  `avail_date` datetime DEFAULT NULL COMMENT '有效时间',
  `dp_uuid` varchar(64) DEFAULT NULL COMMENT 'uuid',
  `create_date` datetime DEFAULT NULL COMMENT '创建时间',
  `update_date` datetime DEFAULT NULL COMMENT '修改时间',
  `create_user` varchar(16) DEFAULT NULL COMMENT '创建人',
  `update_user` varchar(16) DEFAULT NULL COMMENT '修改人',
  `stock_status` tinyint(4) DEFAULT '0' COMMENT '库存状态(0:售罄,1:库存紧张,2:库存充足)',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_store_id_sku` (`store_id`,`sku`,`type`,`avail_date`) USING BTREE,
  KEY `idx_sku` (`sku`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=292839494 DEFAULT CHARSET=utf8 COMMENT='门店商品库存';

create unique index idx_store_id_sku on store_sku_stock(store_id, sku, type, avail_date) using btree;

还原现场用的测试数据:需要多条数据,预计10000条。然后随机选择两次批量删除的

验证方案

验证死锁原因

测试数据:只需要演示两条数据 sku a,b、门店都是1、日期同一天2020-01-01、类型相同1.

1
2
3
4
5
6
7
insert into store_sku_stock values (
1, '1', '1', 'a', 1, 1, 1, 1, '2020-01-01 00:00:00', '1', '2020-01-01 00:00:00', '2020-01-01 00:00:00', '1', '1', 1
);

insert into store_sku_stock values (
2, '1', '1', 'b', 1, 1, 1, 1, '2020-01-01 00:00:00', '1', '2020-01-01 00:00:00', '2020-01-01 00:00:00', '1', '1', 1
);

测试解决方案

如何应用到本次的场景中

参考资料