归档任务执行 insert into archive select ... from orders where create_time < '2025-01-01',执行 90 秒,这期间 orders 的写入全部排队。乍看像缓存或者权限的锅,追下去往往不是。

CREATE TABLE tmp_orders AS
SELECT * FROM orders WHERE create_time < '2025-01-01';
INSERT INTO archive SELECT * FROM tmp_orders;

追下去是这么回事:insert ... select 在读取源表时给扫描到的记录加共享锁,语句不结束锁就不放。源表和目标表是同一张时,读和写还在一个语句里互相牵制。数据量越大,持锁时间越长。

「insert select 加锁」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。

能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。报错里带路径的,先去看那个路径在不在、权限对不对。

同一份配置存在多处的,先确认改的是被加载的那一份。

具体做法是,拆成先 select 到临时表 再分批 insert;按主键范围分批 每批几千行提交一次;归档改到从库或离线库上做;确认隔离级别是 RC 时锁范围会小一些。

验收就看一点,归档期间 orders 的写入不再排队 归档总耗时变长但业务无感。

作者 9823189