[SalesForce] Can anybody explain the UNABLE_TO_LOCK_ROW error

Error Message:

Developer script exception from Nicomatic : quotepotential :
quotepotential: execution of AfterUpdate caused by:
System.DmlException: Update failed. First exception on row 0 with id
a0Q90000005PoxtEAC; first error: UNABLE_TO_LOCK_ROW, unable to obtain
exclusive access to this record: [] Trigger.quotepotential: line 14,
column 1

Apex script unhandled trigger exception by user/organization:
00590000001A6jh/00D90000000bovq

quotepotential: execution of AfterUpdate

caused by: System.DmlException: Update failed. First exception on row
0 with id a0Q90000005PoxtEAC; first error: UNABLE_TO_LOCK_ROW, unable
to obtain exclusive access to this record: []

Trigger.quotepotential: line 14, column 1

these mails are getting to my mail……….

trigger quotepotential on Quote_Line_Item__c (after insert,after update) {
    Set<Id> quoteIds = new Set<Id>();
    List<Quote__c> quotes = new List<Quote__c>();
    for (Quote_Line_Item__c record: Trigger.new) {
        if (record.Quote1__c != null){
            quoteIds.add(record.Quote1__c);
        }
    }
    for(AggregateResult ar:[
                SELECT 
                    Quote1__c, 
                    SUM(Max_Batch__c)sumMax 
                FROM Quote_Line_Item__c 
                WHERE Quote1__c=:quoteIds 
                GROUP BY Quote1__c
                ]) {
         quotes.add(new Quote__c(
             Id=(Id) ar.get('Quote1__c'),
             Potential__c = (Decimal) ar.get('sumMax')
             ));
    }
    if (quotes.isempty() == false) {
        update quotes;
    }
}

Best Answer

Salesforce platform has a feature ROW LEVEL Security. This feature ensures that sharing and visibility set by salesforce administrators for the records have to be maintained. As a part of this feature, there are sharing calculations that the platform has to perform when the record ownership is changed or child records are created/modified.

Assume that a company’s salespeople are adding new contacts into an account. When they click Save, the database automatically locks the parent account when it begins the DML operation and before it actually inserts the Contact. The database releases the lock after executing the triggers and standard save operations. This scenario illustrates the locking that can occur in parent-child relationships.

The next thing to understand is a side-effect known as parent implicit sharing. In a private sharing model, something else occurs when the Salesforce platform creates contact. The built-in implicit sharing feature provides record accessibility, and its parent implicit sharing provides read access to an account for users who have access to standard child objects, such as Contacts, Cases, and Opportunities.

So when salespeople create a Contact, sharing calculations determine during the save operation if a parent implicit share to the Account should be created. In this example, the calculations happen quickly. Assume that the salespeople have been very active and have created 300,000 child objects under a single generic account. They now have a skewed account.

If another salesperson tries to add a new contact for the same account while the sharing calculations are occurring, that request will wait for the Salesforce platform to release the lock on the account, resulting in lock contention and reduced database concurrency.

A record can also go into a Locked State if it is a parent and part of master-detail relationships and child records are getting saved/updated.

You can read how apex can prevent such locks using the link here

Using FOR UPDATE keyword in SOQL helps to achieve a lock on a client end to prevent these locking issues.

Account [] accts = [SELECT Id FROM Account LIMIT 2 FOR UPDATE];

Here are some helpful articles on how to design your sharing model to avoid granular locking

https://help.salesforce.com/apex/HTViewSolution?urlname=How-can-I-avoid-getting-lock-errors-in-my-organization-1327109108393&language=en_US

http://blogs.developerforce.com/engineering/2013/01/reducing-lock-contention-by-avoiding-account-data-skews.html

You can prevent using the below techniques

  • Make sure you have an optimized data model with no Data Skews (No more than 10K child records for a parent record)
  • Make sure you do not have Ownership skews(No single owner owning lots of records when the private sharing model is turned on).
  • Ask support if they can enable granular locking
Related Topic