Kbase P116890: 4GL/ABL: Application Server processes do not always re-read a record from the database.
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  12/31/2008 |
|
Status: Verified
SYMPTOM(s):
4GL/ABL: Application Server processes do not always re-read a record from the database.
Application Server processes do not always re-read a record from the database.
Application Server processes may cache records read NO-LOCK.
The cached record has been previously read with NO-LOCK by another client request which was executed by the same AppServer process.
Stateless or State-free Application Server processes.
Executing the following code on an AppServer process will cache the Customer record between different client requests that are executed later at the same AppServer process:
DEFINE VARIABLE hCustomerBuffer AS HANDLE NO-UNDO.
CREATE BUFFER hCustomerBuffer FOR TABLE "Customer".
hCustomerBuffer:FIND-FIRST('where CustNum = 10', NO-LOCK) NO-ERROR.
FACT(s) (Environment):
Progress 9.x
OpenEdge 10.x
All Supported Operating Systems
CAUSE:
This is an expected and documented behavior. Stateless and State-free Application Server processes may cache records that are found NO-LOCK between different client requests.
FIX:
To resolve this server-server currency conflicts, use one of the following approaches:
1. Read the current record. For example, to ensure that a subsequent client request does not use a cached copy of the record, one may execute code similar to:
FIND Customer EXCLUSIVE-LOCK WHERE Customer.CustNum = 10.
FIND CURRENT Customer NO-LOCK.
2. Release the record. For example, the above code may be modified to release the record after it is no longer needed. This will ensure that the record will not be stored in the executing AppServer Process buffer:
DEFINE VARIABLE hCustomerBuffer AS HANDLE NO-UNDO.
CREATE BUFFER hCustomerBuffer FOR TABLE "Customer".
hCustomerBuffer:FIND-FIRST('where CustNum = 10', NO-LOCK) NO-ERROR.
hCustomerBuffer:BUFFER-RELEASE().
3. Create the record buffer in a named WIDGET-POOL and delete both the dynamic record buffer and its widget pool. For example:
DEFINE VARIABLE hCustomerBuffer AS HANDLE NO-UNDO.
CREATE WIDGET-POOL "myWidgetPool".
CREATE BUFFER hCustomerBuffer FOR TABLE "Customer" IN WIDGET-POOL "myWidgetPool".
hCustomerBuffer:FIND-FIRST('where CustNum = 10', NO-LOCK) NO-ERROR.
DELETE WIDGET hCustomerBuffer.
hCustomerBuffer = ?.
DELETE WIDGET-POOL "myWidgetPool".
4. Set the -rereadnolock parameter.
5. Another good technique is to limit the scope of any given buffer to one procedure or function function ONLY. For example:
PROCEDURE SetSomeInvoiceFlag:
DEF INPUT PARAM ipCustnum LIKE customer.custnum NO-UNDO.
/* This limits the scope of the customer buffer customer to this internal procedure */
DEFINE BUFFER customer FOR customer.
FIND customer NO-LOCK WHERE customer.custnum = ipCustnum.
FIND invoice EXCLUSIVE OF customer WHERE [...]
[...]
END PROCEDURE