来自:blog.csdn.net/daidaineteasy/article/details/109266083
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = ;
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = ;
*** (1) TRANSACTION:
TRANSACTION 791913819, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999
mysql tables in use 3, locked 3
LOCK WAIT 4 lock struct(s), heap size 1184, 3 row lock(s)
MySQL thread id 462005230, OS thread handle 0x7f55d5da3700, query id 2621313306 x.x.x.x test_user Searching rows for update
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = ;
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913819 lock_mode X waiting
Record lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
*** (2) TRANSACTION:
TRANSACTION 791913818, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999
mysql tables in use 3, locked 3
5 lock struct(s), heap size 1184, 4 row lock(s)
MySQL thread id 462005231, OS thread handle 0x7f55cee63700, query id 2621313305 x.x.x.x test_user Searching rows for update
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = ;
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913818 lock_mode X
Record lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 110 page no 41569 n bits 88 index `PRIMARY` of table `test`.`test_table` trx id 791913818 lock_mode X locks rec but not gap waiting
Record lock, heap no 14 PHYSICAL RECORD: n_fields 30; compact format; info bits 0
*** WE ROLL BACK TRANSACTION (1)
CREATE TABLE `test_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trans_id` varchar(21) NOT NULL,
`status` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_trans_id` (`trans_id`) USING BTREE,
KEY `idx_status` (`status`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

uniq_trans_id 索引,又用到了 idx_status 索引,Using intersect(uniq_trans_id,idx_status)的意思是通过两个索引获取交集。index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。UPDATE test_table SET `status` = 1 WHERE `trans_id` = '38' AND `status` = ;
trans_id = ‘38’这个条件,利用 uniq_trans_id 索引找到叶子节点中保存的id值;同时会根据 status = 0这个条件,利用 idx_status 索引找到叶子节点中保存的id值;然后将找到的两组id值取交集,最终通过交集后的id回表,也就是通过 PRIMARY 索引找到叶子节点中保存的行数据。uniq_trans_id 已经是一个唯一索引了,通过这个索引最终只能找到最多一条数据,那MySQL优化器为啥还要用两个索引取交集,再回表进行查询呢,这样不是多了一次 idx_status 索引查找的过程么。我们来分析一下这两种情况执行过程。trans_id = ‘38’查询条件,利用uniq_trans_id 索引找到叶子节点中保存的id值;status = 0 条件对找到的行数据进行过滤。Using intersect(uniq_trans_id,idx_status):trans_id = ‘38’ 查询条件,利用 uniq_trans_id 索引找到叶子节点中保存的id值;status = 0 查询条件,利用 idx_status 索引找到叶子节点中保存的id值;status = 0 的数据非常少,这也是优化器考虑用第二种情况的原因之一)。index_merge 就死锁了
idx_status 索引和 PRIMARY (聚簇索引) 上都存在重合交叉的部分,这样就为死锁造成了条件。
trans_id ,将数据查询出来后,在代码层面判断 status 状态是否为0;force index(uniq_trans_id) 强制查询语句使用 uniq_trans_id 索引;idx_status 索引或者建一个包含这俩列的联合索引;index merge优化关闭。来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/94268/viewspace-3141255/ ,如需转载,请注明出处,否则将追究法律责任。