March 9, 2015

Concurrent access and race condition in Salesforce on insert operation

Assume you have some VisualForce page with complex logic which also has to create some custom object record if it does not exist for current user and current month or even for current day. Is there any possibility to prevent concurrent record insertion like race condition in Salesforce?

First thought that comes to mind is just to check if record does not exist just before record insertion so it should prevent from any duplication happening. However, in a real world situation it may not help if the same user opens the same page in two tabs or browsers and it happens that in both cases record does not exist just before insert\upsert operation, so a duplicate record is still created like it is shown on this picture

RaceConditionConcurrentInsert

Salesforce provides built-in keyword ‘for update’ if you want to make thread-safe update operation. If Salesforce locks records when update operation happen, so you may see error like “UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record”. I have seen this error many times during tests execution, it happens when some unit test tries to touch some record which is locked by another unit test or user. However, this does not really help in insert or upsert operation when your goal is to prevent duplicate record insertion.

There is still a solution.

You need to create some new unique text field on the custom object you want to prevent from duplicated record insertion or you can mark as unique some of the existing text field which should be unique and would uniquely identify the record.

For my case I have created Unique Key field

1
2
3
4
5
6
7
8
9
10
11
12
13
<fields>
    <fullName>Unique_Key__c</fullName>
    <caseSensitive>false</caseSensitive>
    <description>Unique Key to prevent duplication of records on 
concurrent insert\race condition</description>
    <externalId>false</externalId>
    <label>Unique Key</label>
    <length>255</length>
    <required>false</required>
    <trackFeedHistory>false</trackFeedHistory>
    <trackHistory>false</trackHistory>
    <type>Text</type>
    <unique>true</unique>
</fields>

on both custom object definitions where I wanted to prevent duplicated records insertion.
Also I had to create trigger on both of my custom objects and introduce new method which would populate Unique Key field and would be called from before insert trigger

1
2
3
trigger MyCustomObjectTrigger on My_Custom_Object__c (before insert) {
    MyCustomObjectServices.populateUniqueKey( Trigger.new );
}
1
2
3
4
5
6
7
public static void populateUniqueKey(List<My_Custom_Object__c> objects){
    for ( My_Custom_Object__c o: objects) {
        Date day = o.My_Custom_Date_Field__c;
        
        o.Unique_Key__c = day.day() + '_' + day.month() + '_' + day.year() + '_' + ts.My_Custom_Lookup_To_User_Field__c;
    }
}

Both of My_Custom_Date_Field__c and My_Custom_Lookup_To_User_Field__c should be marked as required to be able to populate Unique Key field in before insert trigger.

Also I had to change implementation of my page controller extension so show appropriate error message for users who do not understand what is concurrent access and race condition

1
2
3
4
5
6
7
8
9
10
try {
     upsert myCustomObjectList;
} catch ( Dmlexception dmle ){
    String errorMessage = dmle.getDmlMessage( 0 );
    if ( StatusCode.DUPLICATE_VALUE == dmle.getDmlType( 0 ) ) {
        errorMessage = 'Looks like you are trying to perform this logic from multiple tabs or browsers simultaneously. Operation failed.';
    }
    ApexPages.addMessage( new ApexPages.Message( ApexPages.Severity.ERROR, errorMessage ) );
    return;
}

I hope you enjoyed reading this post and found something useful and learned something new.

You may click like to let me know that you did really enjoy 🙂

Tags

Technical

Share


Recent Articles

SAFE: Winning the Digital Transformation at the speed of startups and the scale of enterprise

June 20, 2019 | Kostiantyn Polosukhin, VP Strategic Accounts, IT Services Competence Platform, Account Management Director, CoreValue

Working with the Clients from various industries, we’ve observed certain challenges; a central item in their top list of business improvements. Is there a program, process or anything else that can make their organization work towards a better value that is delivered quickly, but aligned with all sections of the involved parts? Something, which would […]

Hot and Trendy: Google Teams up with Looker

June 10, 2019

The IT world is stirred up with the latest plans of Google to acquire Looker, a data analytics platform. Google LLC announced its agreement with Looker to join forces in the development of a comprehensive data analytics solution for customers.   Looker, a business analytics and data intelligence platform, empowers organizations to draw insights from […]

Contact Us

By submitting this form you acknowledge that you agreed to our Cookies and Privacy Policy.