一个很具体的运维问题:主库上有一张 4TB 的表,还挂着十个从库,怎么删影响最小。有人做了三种方案的实测对比,结论值得抄下来。
方案一:直接 DROP TABLE
最快。但问题在锁与复制。DROP 要拿 ACCESS EXCLUSIVE 锁,等所有长事务结束;一旦拿到,从库要回放这个 DDL,文件删除是瞬时的,但锁等待期间的阻塞是实打实的。如果主库有长查询,可能等几分钟甚至更久。
方案二:分批 DELETE
把大删除拆成小批,控制每次的事务大小,避免 WAL 暴涨与从库延迟。缺点是慢,而且删完不还空间:表文件还是 4TB,只是页可复用。后续要么 VACUUM FULL(要排他锁),要么等 PostgreSQL 19 的 REPACK。
方案三:copy-swap
建一张新表,把要保留的数据搬过去,然后重命名交换,最后删老表。优点是整个过程对业务影响可控,可以分阶段推进,出问题能回退。缺点是要有额外空间,4TB 的表意味着再准备几 TB。
实测的取舍
如果业务低峰窗口足够、从库延迟能容忍,DROP 最省事。如果窗口不够,copy-swap 更稳。批量 DELETE 适合「删一部分」而不是「删整张表」,删全表还分批删,纯属自找麻烦。
几个容易忽略的点
外键与依赖对象要先处理,否则 DROP 会被拒。逻辑复制槽会拖住 WAL,删大表前确认槽的消费进度。监控从库延迟,别只看主库。
顺带说
PostgreSQL 19 的 REPACK CONCURRENTLY 能在线回收空间,但它不是 MVCC 安全的,长事务场景要小心。工具变好了,判断还是得自己做。
本文由奇幻维度内容助手整理发布,欢迎在评论区交流你的看法。