Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Do apex methods execute atomically? Is this method acceptable as-is or could multiple users cause a race condition?

    public static Integer transactionID(){
        TradeCount__c t=[SELECT Total__c FROM TradeCount__c];
        t.Total__c++;
        update t;
        return t.Total__c;
  }

Assuming the transactions do execute atomically, what about if a different method contained identical code, could a race condition exist then?

Do I need to lock the record like this?

How can I synchronize processing in Apex?

share|improve this question

1 Answer 1

up vote 8 down vote accepted

No, they don't execute atomically.

Marking the method with @future and calling it multiple times is a fairly easy way to demonstrate the concurrency issue. Multiple users calling the same method at the same time would also cause unexpected Total__c values.

You need to use FOR UPDATE in the SOQL query to indicate that you want exclusive access to that record. See Locking Statements.

It is important that any code that is going to update the TradeCount_c.Total_c field uses FOR UPDATE in the SOQL query. Otherwise they can still do a dirty read and potentially write that value back. Reference from above link:

If a client attempts to modify a locked record, the update operation might succeed if the lock gets released within a short amount of time after the update call was made. In this case, it is possible that the updates will overwrite those made by the locking client if the second client obtained an old copy of the record. To prevent this from happening, the second client must lock the record first. The locking process returns a fresh copy of the record from the database through the SELECT statement. The second client can use this copy to make new updates.

As a side note, update your SOQL to get either a single TradeCount__c or select one by Id. You should also consider the case where there are no matches.

E.g.

List<TradeCount__c> ts = [Select Total__c FROM TradeCount__c LIMIT 1];
TradeCount__c t = ts[0];

I haven't seen any other concurrency controls beyond FOR UPDATE.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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