I am helping my company to delete millions of records from object 'Case' in one of our sandboxes. Now matter how big or small the batch size I set, i always receive the 'unable to lock row' error. After doing tons of research online, I now adjust my query to have sort by fields, still doesn't work.

The case object in our company is close to 10 million records, and it has a lot of lookup fields. I have disabled all the look up filter, and using the query with sort by some or all lookup fields, still this situation is not improved.

anyone who knows what else that I should do? This has been driving me crazy....

  • Possibilities - do you have after delete triggers or flows that are doing DML? are you using parallel bulk API (which can create contention)? Does it work with a batch size of 1?
    – cropredy
    Jun 4, 2022 at 3:50
  • @cropredy yes, we do have a trigger placed on 'Case', however that trigger is from an managed package which we can't remove or disable. Because this object is so big (over 8 millions), so I hope that I can use the parallel bulk mode to expedite the deletion, however 90% of the processed records would fail due to the lock row issue. Even when I use serial mode to delete, more than half of the records would fail due to the same reason.
    – Kay
    Jun 4, 2022 at 6:26

2 Answers 2


As noted in the other answer, DML operations will automatically lock related records in various scenarios (as covered in the record locking cheatsheet). It's very likely you have some mix of:

  • Master Detail lookups
  • Standard lookups with a deletion constraint

To resolve the issues you only have a few options:

  1. Change the lookup (at least temporarily) to avoid master detail and deletion constraints.
  2. Update your code to use an "allOrNone" false deletion, capture the failures and retry.
  3. Update your code to do deletions in really small chunks (or chunks that are aligned, via ORDER BY, with the related record(s) that cause the locking failure).

The first may or may not be possible.

The second requires you to keep track of the failures and to perform the re-tries in an async process. This is quite doable using a Queueable or Batchable that accepts the list of failures. Alternatively, if you are using a Batchable to perform the mass deletion, simply ensure that it performs a COUNT aggregate query in finish against the original selection criteria and if the count is non-zero simply chains itself (probably with a delay to avoid burning all async executions for the 24 hour period; System.scheduleBatch is good for this).

The last requires you to investigate the ID of the locking failure to identify the object type and determine the related record lookup that gives rise to this ID. You probably want to mix this with the second option as well.


When you are doing Insert / Update / Delete operations on case object, related objects Account, Contact get highly effected with record lock.

Refer the SF_Record-Locking-Cheatsheet

There are different scenarios for record locking explained clearly on the help article

  • This doesn't really help answer the question.
    – Phil W
    Jun 4, 2022 at 9:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .