There are no clear-cut methods for figuring out what method or procedure has locked a record. This Article provides a few suggestions to either gaining some insight to or avoiding locked record conditions.
The code below demonstrates these suggestions using the sports2000 database's
Customer table.
Create a Stack Trace:The following code demonstrates how to create a stack trace. The stack trace may provide further insight to what other method locked the record.
Either use the client startup parameter
-errorstack or set the session attribute
ERROR-STACK-TRACE to true
SESSION:ERROR-STACK-TRACE = true.
DO ON STOP UNDO, RETRY:
RUN findfirst.
END.
DO ON STOP UNDO, RETRY:
RUN findlast.
END.
PROCEDURE findfirst:
FIND FIRST Customer WHERE CustNum = 100.
END.
PROCEDURE findlast:
FIND LAST Customer WHERE CustNum = 100.
END.
CATCH esyserror AS Progress.Lang.SysError :
MESSAGE "In the catch block" SKIP
"Error" esyserror:GetMessage(1) SKIP
"Number of messages " esyserror:NumMessages SKIP
esyserror:CallStack VIEW-AS ALERT-BOX.
END CATCH.
Avoid the record locked error 2624:Method 1: Keep trying until the record is unlocked.
FIND Customer EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
IF NOT AVAILABLE Customer THEN DO:
IF LOCKED Customer THEN
DO WHILE LOCKED Customer:
FIND Customer EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
END.
END.
Method 2: Allow the process to continue executing, then return.
- Use a TEMP-TABLE to store a reference to a locked record for later use.
- Place locked record's ROWID into a TEMP-TABLE.
- Go do other work.
- Return later and attempt to process the records in the TEMP-TABLE, assuming that the records in the TEMP-TABLE have since become unlocked.
- Use the stored ROWID for attempting to access the records.
- The other process that had the record locked may have deleted the record.
DEFINE TEMP-TABLE ttRowId
FIELD myRecToSave AS ROWID.
FIND Customer WHERE Customer.CustNum = 1
EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
IF NOT AVAILABLE Customer THEN DO:
/* record does not exist */
IF LOCKED Customer THEN DO:
/* refind the record but with no lock */
FIND Customer WHERE Customer.CustNum = 1 NO-LOCK NO-ERROR.
/* record is locked */
CREATE ttRowId.
ASSIGN ttRowId.myRecToSave = ROWID(Customer).
END.
/* Since record was not available, if it was locked, the
ROWID is stored away. The code would return and not further
process the record.
*/
END.
/*
Process the record if not locked.
*/
/* Some place later go through the TEMP-TABLE of saved records and
try processing them.
*/
FOR EACH ttRowId:
FIND Customer WHERE ROWID(Customer) = ttRowId.myRecToSave EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
IF NOT AVAILABLE Customer THEN DO:
IF LOCKED Customer THEN
MESSAGE "Record for is currently locked" VIEW-AS ALERT-BOX.
ELSE
MESSAGE "Record not found" VIEW-AS ALERT-BOX.
/* proceed to next record */
NEXT.
END. /* end of if for record not available */
/* process record */
DISPLAY Customer.CustNum Customer.Name Customer.Phone.
END. /* end of loop through TEMP-TABLE */
Application design should aim to reduce record contention by keeping the amount of time records are locked as short as possible. See the references below for further information on this subject.