后台导入 10 万行价格,跑了 47 秒,期间订单接口 P99 冲到 60 秒,日志里出现 1205 Lock wait timeout exceeded,导完立刻恢复。乍看像缓存或者权限的锅,追下去往往不是。

for batch in chunks(rows, 1000):
    session.execute(insert(Customer), batch)
    session.commit()

追下去是这么回事:整个文件放在一个事务里,插入持有的行锁和间隙锁要到提交才释放。批量 insert 的范围越大,锁住的索引区间越宽,线上更新只能排队。

「导入大事务锁表」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。

具体做法是,按 1000 行一批提交 缩短单次持锁时间;导入走单独的连接和低优先级账号 限制并发;放到低峰执行 并提前看 innodb_trx 确认没有长事务。

验收就看一点,同样 10 万行导入分成 100 批,单批持锁不到 0.5 秒,导入期间订单接口 P99 维持在 80ms 以内。

作者 9823189