You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django QuerySet中带order_by的delete实现(规避死锁)

如何通过Django ORM实现带order_by的delete操作?

在多数场景下避免死锁,建议对涉及同一数据段的delete、update等操作定义固定执行逻辑——MySQL中常用order by来统一锁的获取顺序,比如用以下原生SQL按id排序删除数据:

DELETE from Table where ... order by id

但直接使用Django ORM的Table.objects.filter(...).order_by('id').delete()时,order_by会被ORM忽略,无法达到预期效果。

除原生SQL外的解决方案

核心思路是先按指定顺序获取待删除记录的主键,再基于主键执行删除,以此间接保证锁的获取顺序与排序一致:

  1. 获取排序后的主键列表
    先通过排序的QuerySet提取待删除记录的主键:

    ids_to_delete = Table.objects.filter(你的过滤条件).order_by('id').values_list('id', flat=True)
    

    这里values_list('id', flat=True)会返回一个按id升序排列的主键迭代器。

  2. 基于主键执行删除

    • 追求效率的批量删除:
      Table.objects.filter(pk__in=ids_to_delete).delete()
      
    • 完全保证锁顺序的逐个删除(适合数据量不大的场景):
      from django.db import transaction
      
      with transaction.atomic():
          for pk in ids_to_delete:
              Table.objects.filter(pk=pk).delete()
      
      用事务包裹操作,既保证原子性,又严格按id顺序获取锁,避免死锁。

补充:死锁场景示例

若锁的获取顺序随机,以下两个事务可能引发死锁:

# 事务1
select * from Table where id > 100 for update;
# 事务2
delete from Table where id > 101 and id < 110;

内容的提问来源于stack exchange,提问作者motam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 14:11:13