I have a process that first reads a custom setting value to use in a numbering scheme (can't use auto-number), it +1 that value, updates it, then does a number of DML/logic code which can take a ~2-10 seconds.

The problem I have is if two users perform that process at the overlapping times, the second user doesn't read the updated value because the first update on the numbering value hasn't committed since that occurs at the end of the transaction. From what I can see in other articles, there isn't a way to force a commit (no commit, Database.updateImmediate seems only external etc). The other logical choice would be the row lock but locking stack exchange question seems to indicate it will fail after 4-5 seconds which this process could theoretically take. This would cause bigger problems than duplicated values. Is there any advice on alternative options for roughly concurrent processes to not read the same value?

If you want to simulate reproducing the issue, open up two dev consoles (use private/incognito for the second to have two sessions) and execute the code in the first, then immediately in the second window. Event though the first has called the update, it doesn't commit until after the wait loop so the second doesn't read the updated value.

Contact con = [Select Title from Contact where id='003g000000YxzQj'];
con.Title += '1';
update con;

//need to commit this change now

Long startingTime = System.now().getTime();
Integer delayInMilliseconds = 1500; // One-second delay
while (System.now().getTime() - startingTime < delayInMilliseconds) {
   // Do nothing until desired delay has passed
  • 2
    you could use an async framework (queueable) to process at most one record at a time – cropredy Aug 30 '16 at 17:20
  • I should add that at the end of the process the user is redirect to another page similar to a wizard) so I can't fire it off asynchronously. – Kevin B Aug 30 '16 at 18:13
  • I do not believe this is best practice but I have used a flag before to indicate the page was in use and by who, refreshing it every 10 seconds. if flag is > 10 seconds old I let another user load the page. It at least allowed me to stop the page being loaded by multiple people. Not the best for busy orgs but worked well in a slow org. – Eric Aug 30 '16 at 23:49
  • 1
    can the DML/logic (most of it) be pushed off into an async (future/queueable)? – cropredy Aug 31 '16 at 0:36

Your Answer

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

Browse other questions tagged or ask your own question.