Q1: I am bit confused about what will happen ? Will it fail(throw exception) or will it wait for 4-5 seconds and then if it doesn't get access it will throw an exception?
You will get somewhere around ten seconds before it will exclusively fail. The user will be advised to try their save again. The status code will be "UNABLE_TO_LOCK_ROW".
Q2 : In the above case will the second thread get access to the record ? or the query will not return any record ?
Either the prior transaction has already completed, so it would not appear in the results, or you'll get an error because the row can't be locked. There's never a scenario where it would be returned with non-matching criteria.
Q3 : When does the lock gets released ? the Salesforce doc doesn't seems to provide much insight into it. does the lock get released after a DML ? or it waits for full transaction to complete ?
The documentation clearly states:
While the records are locked by a client, the locking client can modify their field values in the database in the same transaction. Other clients have to wait until the transaction completes and the records are no longer locked before being able to update the same records. Other clients can still query the same records while they’re locked.
(Emphasis mine)
Clarification The lock isn't released until sometime after the final commit occurs, usually within a few milliseconds, although post-transaction logic can re-acquire the lock immediately, such as future methods.
So, I decided to test this with some code to get a more definitive answer.
First, I set code that ran around (but less than) 10 seconds, like this:
Controller
public with sharing class rowlock {
Id accountId = [SELECT Id, name FROM Account where name = 'test' LIMIT 1].Id;
public void updateAccount() {
Account[] a = [SELECT Id FROM Account WHERE Id = :accountId and name = 'test' FOR UPDATE];
for(integer i = 0; i < 3000000; i++) {
// Do nothing, haha!
}
if(!a.isempty()) {
a[0].name = 'test2';
update a[0];
}
system.debug(logginglevel.error, a.isempty());
}
}
Page
<apex:page controller="rowlock">
<apex:form id="form">
<script>
addEventListener("load", function() {
updateAccount();
updateAccount();
}, true);
</script>
<apex:actionFunction name="updateAccount" action="{!updateAccount}" reRender="form"/>
</apex:form>
</apex:page>
During this trial run, the page bombed out on the second transaction with "Record Currently Unavailable..."
Changing 3,000,000 to 100,000, both transactions passed. However, the first transaction (the one with the first lock) returned 1 row, while the second transaction returned 0 rows, thus proving that the lock actually resulted in the query results being modified to exclude the locked record since it no longer met the criteria.
Edit: Fixed the status code to current terminology, cleaned up the multiple strke-throughs, which were distracting.
On doing some research on my own I found that Option 1 of my questions should be the way to unlock and lock the records as it will avoid hitting the governor limit. The option 2 will definitely hit the governor limit as it is checking the each record whether it is locked or not and then making it unlock. It consumes 1 DML to unlock or lock a record.
I choose below method to unlock the records.
public static List<Approval.UnlockResult> unlock(List<SObject> recordsToUnlock, Boolean allOrNothing)
Best Answer
This is the default behavior. System Admins (i.e. users with permission of Modify All/Modify All Data) can edit the locked records. Here is the link which states the same. You can go through this article which mentions what permissions are needed to edit the locked records.
If you are not seeing the lock/unlock button in the page layout, you need to check following points.
And if the user has Modify All/Modify All Data permission or is assigned as currently assigned approver, then that user will be able to edit the record without having to click on Unlock button. Lock/Unlock button is just to lock/unlock the record. System Admins (Modify All/Modify All Data) can directly click on edit button and edit the record.