读者反馈了一个死锁案例,比较有意思,我分析总结了一篇文章。
需要一些基础,下面是我在掘金上写的另外五篇调试源码分析锁的文章,可以顺便看看:
下面开始真正的内容:
建表语句:
CREATE TABLE `tenant_config` (
`id` bigint(21) NOT NULL AUTO_INCREMENT,
`tenant_id` int(11) NOT NULL,
`open_card_point` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uidx_tenant` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
复制代码
表中有一条初始化语句:
INSERT INTO `tenant_config` (`tenant_id`, `open_card_point`) VALUES (123,0);
复制代码
数据库隔离级别:RC
第一种情况:两条 insert,两条 update
事务 1 和事务 2 语句一毛一样,都是下面这样:
INSERT INTO `tenant_config` ( `tenant_id`, `open_card_point`) VALUES (123,111111);
UPDATE tenant_config SET open_card_point = 0 where tenant_id = 123;
复制代码
代码的逻辑大概如下,先插入,如果有冲突则更新
try {
insert();
} catch (DuplicateKeyException e) {
update()
}
复制代码
死锁条件的过程如下
事务 1:
INSERT INTO `tenant_config` ( `tenant_id`, `open_card_point`) VALUES (123,111111);