7

I have 2 Batch classes working on different child objects of a common master object. Batch Batches are started parallel to speed up this long running cleansing operation.

It depends on the underlying data structure which batch finishes first. But when both are finished the master object needs to be marked as cleaned.

Do do this both batches add and remove put their job id to a text field in the master object. If it is empty the master record is clean.

My problem now is that both batches sometimes try to write to the master at the same time and I receive a UNABLE_TO_LOCK_ROW exception.

I thought I could simply retry the update operation as long as it fails and my Limits are not consumed. Would that work and be a feasable solution or are there better ways?

public void modify() {
    CustomObject__c record = query();

    //...

    try {
        update record;
    }
    catch(DMLException ex) {
        if(ex.getMessage().contains('UNABLE_TO_LOCK_ROW')) {
            modify();
        }
    }
}
  • Just to confirm, are you using the new parallel processing features in SF? – crmprogdev Jul 2 '14 at 14:12
  • @crmprogdev: What feature is this?! Never heard of it. Is this a pilot? – Robert Sösemann Jul 2 '14 at 14:15
  • Its actually primarily related to Bulk Data Loads. See General Guidelines for Data Loads for more info. – crmprogdev Jul 2 '14 at 14:36
7

If you use the FOR UPDATE keyword in your query, the database will wait up to about 5 seconds before declaring that it cannot acquire the lock (this should normally be plenty of time). This event can be captured, and you can attempt to retry, assuming you have any SOQL queries/rows remaining. I've found that, in practice, it's rarely necessary to retry a query, however, assuming your transaction time is small (as well it should be).

  • 1
    Very cool. Nobody ever wrote about this 5 sec delay. – Robert Sösemann Jul 2 '14 at 14:23
  • Actually, there was a question on this that I answered. See salesforce.stackexchange.com/questions/22636/… – sfdcfox Jul 2 '14 at 15:00
  • After I read you answer to the referenced question I am a bit confused. After your initial answer I added an FOR UPDATE to the SOQL queries in each batch and it seems to work. But...from reading the old thread it seems to be not a good solution if all "threads" that want to write do a FOR UPDATE. – Robert Sösemann Jul 2 '14 at 18:57
1

Another solution might be to create a cleaned checkbox field on the children. After cleaning, the batch job will set that checkbox on the child.

Then create a rollup summary field on the parent that counts all children with cleaned to false.

Then you can filter on all master records that have > 0 uncleaned children?

  • Except that you still need to acquire a record lock to set that field. Would that really change anything? – Adrian Larson Feb 22 '17 at 15:07
  • 1
    No you don't, because quote "I have 2 Batch classes working on different child objects of a common master object." which I suppose means that the Batches will not have conflicts on the child records? – Willem Mulder Feb 23 '17 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.