表结构:
CREATE TABLE `extend_0` (
`id` bigint(20) NOT NULL,
`code` varchar(30) NOT NULL,
`data_key` varchar(50) NOT NULL,
`data_value` varchar(200) NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`yn` tinyint(3) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`,`create_time`),
UNIQUE KEY `idx_unq_code_data_key` (`code`,`data_key`,`create_time`) USING BTREE,
KEY `idx_code` (`code`) USING BTREE
) ENGINE=InnoDB;当两个事务同时删除和插入相同的数据时,有时会发生死锁。tx_isolation为RR。
例如:
DELETE FROM extend_0 WHERE code = '00226915986' AND yn = 1;
INSERT INTO extend_0 (id, code, data_key, data_value, create_time) VALUES (1133296779049299970, '00226915986', 'consignWare', 'food', '2019-05-28 16:59:42.418'), (1133296779049299971, '00226915986', 'productType', '0001,0006', '2019-05-28 16:59:42.418'); 死锁日志:
------------------------------------------------------------------------------
2019-05-30 14:48:07 0x7fbb7872c700
*** (1) TRANSACTION:
TRANSACTION 125554670, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 5148727, OS thread handle 140443189679872, query id 6111057236 192.168.162.16 waybill updating
DELETE FROM extend_0 WHERE code = '00226915986' AND yn = 1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 77 page no 3145 n bits 360 index idx_unq_code_data_key of table `waybill_0`.`extend_0` trx id 125554670 lock_mode X waiting
Record lock, heap no 285 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc 00226915986;;
1: len 11; hex 636f6e7369676e57617265; asc consignWare;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf000; asc ;;
*** (2) TRANSACTION:
TRANSACTION 125554668, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 3
MySQL thread id 5148728, OS thread handle 140443156399872, query id 6111057237 192.168.162.16 waybill update
INSERT INTO extend_0 (id, code, data_key, data_value, create_time) VALUES (i-1, '00226915986', 'consignWare', 'food', '2019-05-28 16:59:42.418'), (i, '00226915986', 'productType', '0001,0006', '2019-05-28 16:59:42.418')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 77 page no 3145 n bits 360 index idx_unq_code_data_key of table `waybill_0`.`extend_0` trx id 125554668 lock_mode X
Record lock, heap no 285 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc 00226915986;;
1: len 11; hex 636f6e7369676e57617265; asc consignWare;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf000; asc ;;
Record lock, heap no 287 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc 00226915986;;
1: len 11; hex 70726f6475637454797065; asc productType;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf020; asc ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 77 page no 3145 n bits 360 index idx_unq_waybill_code_data_key of table `waybill_0`.`extend_0` trx id 125554668 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 285 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc JDVC00226915986;;
1: len 11; hex 636f6e7369676e57617265; asc consignWare;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf000; asc ;;
*** WE ROLL BACK TRANSACTION (1)
------------------------------------------------------------------------------ transaction2已经有lock_mode X了。为什么"lock_mode X锁定空白在rec插入意图等待“发生?
但是,当我们逐一执行事务时,不会出现死锁。例如:
step1: tx1 begin; delete.....;
step2: tx2 begin; delete.....;
step3: tx1 insert....;
step4: tx2 insert....;
step5: tx1 commit;死锁只有在并发性高的情况下才会发生,死锁似乎是由tx1's delete和tx2's插入的并发造成的。
发布于 2019-05-31 05:24:16
您正在删除与插入的记录完全相同的记录(通过code)。这就是服务器死锁的原因,因为mysql现在可以知道应该采取哪种操作。您需要使用基于业务案例的适当操作来处理应用程序中的此错误。
没有魔法可以避免这种情况。索引已经在code上了
发布于 2019-05-31 13:30:20
这个问题看起来和我的变体非常相似。据我所知,在delete语句中有一个问题是完全扫描的。您没有索引和delete语句试图对表进行完全扫描,富尔扫描在表中的所有行上应用锁,甚至对插入中未提交的行也是如此。
MySQL/innodb试图从并行事务锁定未提交的行,结果导致死锁
尝试为代码和yn文件创建索引。索引可以减少死锁事件。确保删除使用索引而不是完全扫描。
https://dba.stackexchange.com/questions/239516
复制相似问题