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外的解决方案
核心思路是先按指定顺序获取待删除记录的主键,再基于主键执行删除,以此间接保证锁的获取顺序与排序一致:
获取排序后的主键列表
先通过排序的QuerySet提取待删除记录的主键:ids_to_delete = Table.objects.filter(你的过滤条件).order_by('id').values_list('id', flat=True)这里
values_list('id', flat=True)会返回一个按id升序排列的主键迭代器。基于主键执行删除
- 追求效率的批量删除:
Table.objects.filter(pk__in=ids_to_delete).delete() - 完全保证锁顺序的逐个删除(适合数据量不大的场景):
用事务包裹操作,既保证原子性,又严格按id顺序获取锁,避免死锁。from django.db import transaction with transaction.atomic(): for pk in ids_to_delete: Table.objects.filter(pk=pk).delete()
- 追求效率的批量删除:
补充:死锁场景示例
若锁的获取顺序随机,以下两个事务可能引发死锁:
# 事务1 select * from Table where id > 100 for update; # 事务2 delete from Table where id > 101 and id < 110;
内容的提问来源于stack exchange,提问作者motam
相关产品推荐
相关产品推荐

