SOQL Record Locking Behavior for Update?

SOQL Record Locking Behavior for Update?

On April 22, 2025, Posted by , In Apex, With Comments Off on SOQL Record Locking Behavior for Update?
SOQL Record Locking Behavior for Update?

Question:

I am working on implementing record locking in Apex using the FOR UPDATE clause, but I encountered some confusion regarding its behavior. The official Salesforce documentation states that when a second transaction attempts to lock a record already locked by another transaction, it will throw a QueryException. However, answers from StackExchange suggest that the second thread might wait instead of throwing an exception. These sources seem to conflict, and I am struggling to understand the exact behavior.

Here are my specific questions:

  1. What happens when a second transaction tries to lock a record that’s already locked by another transaction?
    Will it fail immediately with an exception, or will it wait for a few seconds (e.g., 4-5 seconds), and then throw an exception if the lock isn’t released?
  2. In a scenario where a record is locked by one transaction and another transaction tries to access it while it’s being processed, what happens?
    If the first transaction updates a field that changes the record’s criteria (e.g., changes isValid__c to false), will the second transaction still be able to access the record, or will the query fail due to mismatching criteria?
  3. When does the lock on a record get released?
    Does the lock get released after the DML operation (e.g., update), or does it wait until the full transaction is completed?

Answer:

  1. When a second transaction tries to lock a record already locked by another transaction, it will typically wait for a period of time (around 10 seconds) before failing with a QueryException. The status code in this case would be “UNABLE_TO_LOCK_ROW.” After this waiting period, if the lock hasn’t been released, the second transaction will receive an exception.

Advance your career with CRS Info Solutions’ Salesforce training in Jaipur, featuring expert guidance, hands-on practice, and in-depth Salesforce knowledge.

2. In this case, if the first transaction is modifying the record and it changes the criteria for the query (for example, updating the isValid__c field to false), the second transaction will not retrieve the record. Either the first transaction will have already completed, and the record will no longer match the query criteria, or the second transaction will receive an error due to the inability to lock the record. The record will never be returned if it no longer matches the query after being locked.

3. The lock on a record is released after the transaction is completed, typically after the final commit occurs. Salesforce documentation clarifies that while the records are locked by a client, the locking client can still modify the record’s fields during the same transaction. However, other clients cannot access or update the locked records until the transaction is complete. The lock is not released immediately after a DML operation but rather at the conclusion of the transaction. After the final commit, the lock is released, usually within milliseconds. Post-transaction logic, such as future methods, can immediately acquire the lock again.

Additional Insight from Testing:

To better understand the behavior, I tested this with a simple Apex controller and a long-running operation. I ran a test where the first transaction locked the record, and the second transaction attempted to access it. In the test, when the second transaction tried to access the locked record, it did not get access if the first transaction had already updated the record and the query criteria no longer matched.

Here’s the test code for reference:

public with sharing class RowLockTest {
    Id accountId = [SELECT Id, Name FROM Account WHERE Name = 'Test Account' LIMIT 1].Id;

    public void updateAccount() {
        Account[] accounts = [SELECT Id FROM Account WHERE Id = :accountId AND Name = 'Test Account' FOR UPDATE];
        
        for (Integer i = 0; i < 3000000; i++) {
            // Simulating some time-consuming process
        }
        
        if (!accounts.isEmpty()) {
            accounts[0].Name = 'Updated Test Account';
            update accounts[0];
        }
    }
}

Code explanation:
The RowLockTest class demonstrates record locking in Salesforce using the FOR UPDATE clause. It queries an Account record by name and locks it for processing, ensuring no other transaction can modify it during execution. After simulating a delay with a loop, it updates the locked record’s Name field and commits the change.

This test showed that the second transaction failed with a “Record Currently Unavailable” message, proving that the lock prevents other transactions from accessing the record until the first transaction completes. When the process ran with fewer iterations, both transactions succeeded, confirming that the lock effectively excluded the locked record from the second transaction’s query.

Master Salesforce in Jaipur: Your Path to a Thriving Career

Elevate your skills with our all-encompassing Salesforce training in Jaipur. Dive deep into Admin, Developer, and AI tracks through structured modules, real-world projects, and expert-led sessions designed to prepare you for certifications, interviews, and a successful career in the tech industry.

Experience our free demo class to explore the practical, hands-on approach of our industry-oriented training. With personalized guidance from experienced instructors, you’ll master even the most complex Salesforce concepts effortlessly.Whether you’re starting fresh or advancing your career, our program equips you to tackle real-world challenges and accelerate your growth.

Take the first step today—enroll now for a free demo and unlock your potential!!!

Comments are closed.