Repository navigation
fix(cleanup): Sort IDs before bulk deletion to prevent deadlocks - #128136
sentry[bot] wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit af31763. Configure here.
af31763 to
bb46d99
Compare
| ) -> bool: | ||
| qs = model.objects.filter(**filters).values_list("id")[:limit] | ||
| # Sort IDs first to ensure consistent lock ordering across concurrent workers, preventing deadlocks. | ||
| ids = sorted(model.objects.filter(**filters).values_list("id", flat=True)[:limit]) |
There was a problem hiding this comment.
@sentry another clanker said this python sorting may not guarantee deletion lock order b/c when processing the SQL IN, postgres could ultimately scan in a different order than the sorted input. Can you confirm or deny? Is there a better approach to use here?
…dlocks Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com>
|
@sentry here's additional feedback from another clanker: Production PostgreSQL logs at 2026-10-19 07:30:22 UTC show the competing process, PID 2408941, executing: edit: |

Problem
When running
cleanupwith concurrency > 1, multiple worker processes concurrently deleting child relations (e.g.sentry_groupemailthread) hit PostgreSQL deadlocks (OperationalError: deadlock detected).The root cause was that
bulk_delete_objectsgenerated a self-referencing subquery DELETE:This two-phase lock acquisition (reading rows via the subquery, then acquiring exclusive delete locks) causes circular waits when multiple workers touch overlapping or interleaved rows.
Solution
SELECT ... ORDER BY idquery, breaking the self-join pattern.DeleteQuery, keeping the raw single-query DELETE with no ORM cascading or signal overhead.test_bulk_delete_single_queryto reflect the 2-query pattern (SELECT + DELETE).Legal Boilerplate
Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
Fixes SENTRY-5XCB
@sentry <feedback>: Autofix iterates on these changes@sentry stop iterating: Autofix stops iterating on this run