SELECT * FROM performance_schema.data_locks
WHERE OBJECT_NAME = 'orders' AND LOCK_MODE LIKE '%S%';
SHOW CREATE TABLE order_items\G

订单明细批量插入时,父表 orders 上出现大量 LOCK_S 记录锁,两个批量任务互相等待,单批耗时从 1 秒涨到 15 秒。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:往子表插入时,数据库要到父表确认对应主键存在,这个确认会给父表记录加共享锁。两个事务都持有共享锁,再各自升级去改父表,就会互相等。外键越多,涉及的父表记录越多。

「外键检查锁」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。同一份配置存在多处的,先确认改的是被加载的那一份。

处理上按这个顺序:确认插入路径上是否有事务同时更新父表;把父表更新挪到子表插入前后 别在同一个事务里交叉;高频写入的表评估去掉外键 约束放到应用层;用 data_locks 确认父表上的 LOCK_S 是否长时间不释放。

确认没问题再收工,批量插入时父表上的共享锁随语句结束立刻释放 两个任务不再互相等 单批耗时回到 1 秒左右。

作者 9823189