同事新上线的一个每天跑数统计然后覆盖原来数据的功能,出现了死锁。大概的业务流是以实体A(对应表中的一个列)为维度,每天跑数据,实体A在表中建有唯一索引,对于唯一索引冲突的情况,使用了REPLACE INTO语句进行操作。 通过show engine innodb status打印出死锁日志,替换敏感信息后的日志如下(生产事务隔离级别:RC, 数据库版本:5.1x)。
LATEST DETECTED DEADLOCK
------------------------
2022-04-18 21:49:55 0x70000edf9000
*** (1) TRANSACTION:
TRANSACTION 11134, ACTIVE 18 sec updating or deleting
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 4
MySQL thread id 17, OS thread handle 123145563348992, query id 339 localhost root update
replace into t_uk(uk, name) values(uuid, "A"),values(uuid, "A"),values(uuid, "A")....
*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 29 page no 5 n bits 80 index uk_uk of table `iths`.`t_uk` trx id 11134 lock_mode X
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 80000014; asc ;;
1: len 4; hex 8000000e; asc ;;
Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 8000000f; asc ;;
1:

本文记录了一次生产环境中因REPLACE INTO语句引发的死锁问题,分析了REPLACE INTO的加锁逻辑,通过日志发现事务在唯一索引上互相等待。解决方案是将批量REPLACE INTO按排序执行,避免交叉锁导致的死锁。

2837

被折叠的 条评论
为什么被折叠?



