function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Andree WilleAndree Wille 

UNABLE_TO_LOCK_ROW error in parallel apex tests

Hi,

i get an UNABLE_TO_LOCK_ROW  error when running my tests in parallel. The error occurs when creating a pricebookentry in the standard pricebook. As far as i know Salesforce locks also the parent Object when inserting a object. Which would mean that in this case while inserting the pricebookentry the pricebook is locked. When now a parallel test wants to add another entry to the locked pricebook the test throws the UNABLE_TO_LOCK_ROW error.

Does anyone know how to get around this?
Sagar PareekSagar Pareek
This is very common issue . Check your code mainly triggers written on pricebook or pricebook entry may have FOR UPDATE clause included in them. Remove them and it will work fine.

Check this out

https://developer.salesforce.com/blogs/engineering/2013/01/reducing-lock-contention-by-avoiding-account-data-skews.html

https://help.salesforce.com/apex/HTViewSolution?urlname=How-can-I-avoid-getting-lock-errors-in-my-organization-1327109108393&language=en_US
Andree WilleAndree Wille
thank you for your reply Sagar, but unfortnately it doesn't seem to be related to trigger. There is no trigger operating directly on pricebook or pricebookentry. There are some trigger for other objects that creates entries on the standard pricebook but disabling those trigger doesn't fix the issue.

Thx for the links to the resources about locking.

do you have another idea?
Fredrik BurlinFredrik Burlin
Hi Andree,

I had the same issue trying to insert Pricebookentries. It worked fine when you only ran that one test class but runing multiple test classes you got the Error.

This is how I made it work by using a Custom Pricebook instead of the Standard.
// Insert a test product.
List<Product2> products = new List<Product2>();
for(Integer i = 0; i < 5; i++) {     
    Product2 product = new Product2();
    product.name='Product '+i; 
    product.Description = 'desc '+i;
    products.add(product);
} 
insert products; 
System.debug('Adding Products: ' + products);

// Get standard price book ID.
Id pricebookId = Test.getStandardPricebookId();
System.debug('Getting pricebookId: ' + pricebookId);

// Insert a price book entry for the standard price book.
List<PricebookEntry> pbes = new List<PricebookEntry>();
for(Integer i = 0; i < products.size(); i++) {
    PricebookEntry pbeUSD = new PricebookEntry();
    pbeUSD.Pricebook2Id = pricebookId;
    pbeUSD.IsActive = true;
    pbeUSD.Product2Id = products[i].Id;
    pbeUSD.UnitPrice = 12345;
    pbeUSD.CurrencyIsoCode = 'USD';
    pbes.add(pbeUSD);
}
insert pbes;
System.debug('Adding Pricebookentries: ' + pbes);

// Create a custom price book
Pricebook2 customPB = new Pricebook2(Name=PRICEBOOKNAME, isActive=true);
insert customPB;
System.debug('Adding customPB: ' + customPB);

// Insert a price book entry with a custom price.
List<PricebookEntry> customPricebookEntries = new List<PricebookEntry>();
for(Integer i = 0; i < products.size(); i++) {
    PricebookEntry pbeUSD = new PricebookEntry();
    pbeUSD.Pricebook2Id = customPB.Id;
    pbeUSD.IsActive = true;
    pbeUSD.Product2Id = products[i].Id;
    pbeUSD.UnitPrice = 0;
    pbeUSD.CurrencyIsoCode = 'USD';
    customPricebookEntries.add(pbeUSD);
}
insert customPricebookEntries;
System.debug('Adding Custom PricebookEntries: ' + customPricebookEntries);

Then using the customPricebookEntries when adding Opportunity Products or Order Lines.

I hope that helped you or someone else :)
Fredrik BurlinFredrik Burlin
But it somehow helped one test class but the problem still reamains for some other.

According to Salesforce Testing Best Practices (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_best_practices.htm) :
Best Practices for Parallel Test Execution
Tests that are started from the Salesforce user interface (including the Developer Console) run in parallel. Parallel test execution can speed up test run time. Sometimes, parallel test execution results in data contention issues, and you can turn off parallel execution in those cases. In particular, data contention issues and UNABLE_TO_LOCK_ROW errors might occur in the following cases.
  • When tests update the same records at the same time. Updating the same records typically occurs when tests don’t create their own data and turn off data isolation to access the organization’s data.
  • When a deadlock occurs in tests that are running in parallel and that try to create records with duplicate index field values. A deadlock occurs when two running tests are waiting for each other to roll back data, which happens if two tests insert records with the same unique index field values in different orders.
You can prevent receiving those errors by turning off parallel test execution in the Salesforce user interface:
  1. From Setup, enter Options... in the Quick Find box, then select Options....
  2. In the Apex Test Execution Options dialog, select Disable Parallel Apex Testing and than click OK.

But enabeling that the test runs super slow.
DebadyutiDebadyuti
The reason of this situation is pricebook entry is getting locked because of parallel access.To solve this problem all test methods that insert pricebookentry (i.e any  test cases where pricebookentry need to be inserted) should be written in single test class so that all methods which related to pricebook entry will run sequentially and will not be dependent on other test class.In this approach when you run all test class parallel it should work however the test class which has all methods related to pricebookentry will take longer time to pass all test methods.
Fredrik BurlinFredrik Burlin
Now you can select which test classes that should run in parallel by the @isTest(isParallel=true) annotation.
Indicate the test classes that can run in parallel and aren’t restricted by the default limits on the number of concurrent tests. This makes the execution of test classes more efficient, because more tests can be run in parallel. https://releasenotes.docs.salesforce.com/en-us/winter18/release-notes/rn_apex_annotation_istest_isparallel.htm
Simon Law (Quantcast)Simon Law (Quantcast)
I have filed a Idea to remove this lock: Ability to create multiple PricebookEntry objects for a Pricebook2 in parallel (https://success.salesforce.com/ideaView?id=0873A000000cRUiQAM).