Django对接Postgres数据库偶发delete删除操作性能异常问题求助
可能原因
- 行锁阻塞:要删除的行被其他未提交的长事务持有排他锁,delete操作会持续等待锁释放,就会出现偶发的长时间卡顿。常见场景是并发请求同时命中同一条过期缓存,同时触发删除操作,或者其他读取缓存的逻辑开启了长事务未及时提交。
- 无索引外键校验:如果缓存表存在关联其他表的外键,且关联表的外键字段未建索引,删除缓存表行时Postgres会全表扫描关联表校验关联数据,即使缓存表本身数据量小,关联表数据量大时也会导致删除耗时飙升。
- 表/TOAST表膨胀:缓存场景频繁执行delete+insert操作会产生大量死元组,如果autovacuum未及时清理,即使逻辑上只有100条数据,表的物理存储文件也会远大于实际数据量,删除时扫描物理块耗时变长;另外response这类大字段会存在TOAST表中,TOAST表膨胀也会导致删除变慢。
- 服务器资源峰值:即使是独立专用服务器,出现定时备份、大查询、操作系统磁盘刷写等IO/CPU占用高的场景时,小的删除操作也会被资源抢占导致耗时变长。
解决方法
- 排查锁冲突:开启Postgres锁日志,出现慢删除时查询
pg_locks视图定位阻塞事务。如果是并发删除同一条缓存导致的冲突,给删除逻辑加分布式锁,或者使用DELETE ... WHERE ... NOWAIT语法避免长时间阻塞,捕获锁冲突错误后直接让先拿到锁的请求完成缓存更新即可。 - 检查外键配置:执行
\d 你的缓存表名查看是否有外键约束,若有则确认关联表的对应字段是否已建索引,无索引则补充索引,无业务关联需求可以直接删除不必要的外键。 - 优化 vacuum 策略:针对缓存表调整autovacuum触发阈值,例如设置
autovacuum_vacuum_scale_factor = 0.01,死元组占比达到1%就自动触发清理,也可以定期手动执行VACUUM ANALYZE 你的缓存表名清理死元组。 - 补充查询索引:给用于判断过期的创建日期字段建立索引,减少删除时的行扫描范围,降低锁冲突概率。
- 替换缓存存储方案:这类短生命周期的API缓存更适合用Redis这类专门的缓存中间件存储,天生支持自动过期淘汰,完全避免Postgres的delete阻塞问题。
内容的提问来源于stack exchange,提问作者fsulser
相关产品推荐
相关产品推荐

