0

we have a scenario where User role is changes we have to update Account field then Account's trigger will update 5 related objects so their triggers also fire :) . Earlier we have used process builder at Account level but we are hitting CPU limit so we are switching to Asynchronous (via trigger) .

As I am going through the cheat sheet and understood that if I am modifying a child record and in the same time my Account is getting updated from User trigger it will get locked. so my trigger update may failed because it is already locked.

http://resources.docs.salesforce.com/194/0/en-us/sfdc/pdf/record_locking_cheatsheet.pdf

So is there only one way I can live batch at non working hours? and asking users to wait for the update till tomorrow :(

1

A lock occurs for the entire transaction. For example, the following code does not produce a deadlock:

Account a = [SELECT Id FROM Account LIMIT 1 FOR UPDATE];
Account b = [SELECT Id FROM Account WHERE Id = :a.Id FOR UPDATE];

This is true regardless of if this happens immediately (as demonstrated above), or even several recursive trigger contexts deep; the lock is tied to the same transaction.

Typically speaking, if a user gets a "row locked" error, they can usually immediately try again and things will be okay.

In general, you should use FOR UPDATE in a query to obtain exclusive access before attempting to update a record. This will cause a lock delay while the system waits to obtain exclusive access to the record.

If the lock delay isn't long enough, you might also consider using a spin lock in your asynchronous code while you wait for any pending updates:

SObject[] records;
while(records == null) {
    try {
        records = [SELECT ... FOR UPDATE];
    } catch(QueryException e) {
    }
}

This will allow you to wait up to about 9 minutes while waiting to acquire the lock. Using this in your asynchronous code should allow at least semi-real-time updates.

  • curious -- what exception is thrown after 9 minutes? "Too many SOQL queries"? – cropredy Oct 2 '17 at 22:11
  • @cropredy Locks don't have a "precise" amount of time before they time out (the docs suggest they do, but in practice, I've found it inconsistent), but 9 minutes is just about the maximum amount of time you'd have before either a "too many SOQL queries" error or the maximum transaction time would be right around the corner (10 minutes). – sfdcfox Oct 2 '17 at 22:22
  • thanks @sfdcfox - the statement If the lock isn’t released within 10 seconds, you will get a QueryException. Similarly, if you attempt to update a record currently locked by another client and the lock isn’t released within 10 seconds, you will get a DmlException. -- is this going to be happen if I lock the Account and try to modify the Opportunity record!! then how to handle that? – user7601 Oct 3 '17 at 7:40
  • @Uday By locking the parent first (and always doing so consistently), there won't be a problem. If you have two clients, A and B, and B gets the Account lock first, then A will have to wait for the Account (and therefore any of the Account's Cases, Contacts, or Opportunities). You only need to get a lock on the parent. – sfdcfox Oct 3 '17 at 9:18

Your Answer

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