FIND NO-LOCK in memory...

kolonuk

Member
Hi All,

I have recently discovered something that i think may be of interest...

I believe that FIND NO-LOCK gets the record and then stores it in memory. Then, when the actual record in the database is changed, it doesn't update the copy in memory until you do another FIND.

For example, I have a table in a database. I open a progress editor session and run this program

FIND table1 WHERE table1.item = "abc123" NO-LOCK.
PAUSE.
DISPLAY table1.

At the pause, I then go and modify one field of that record (like item?) in another session. I also then DISPLAY it to see if it has changed, and it has.

In the original sesion, I "Press space bar to continue.", and low and behold, it hasn't updated the record. If I then run the program again, it works as I'd expect it to and DISPLAYs the change.

I thought I was going mad till I found this! I have done another FIND when I need to to fix this, but hey, 3 hours well learnt!

I understand that this may be to conserve disk access, as many records may not change that often (stats & history etc.) so may be fine. Plus, memory is faster...

Can I make progress check the actual database for every field that I use after I have a NO-LOCK, and not rely on the temporary memory record?
 

sridevi.stalin

New Member
Yes, this is the drawback of NO-LOCK.
Otherwise, we can say this is “Lost Update”-problem
Once we fetch the record from DB-Table using FIND,
The FIND will move the record from db-table into RecodBuffer as u said in memory
To solve this problem, we can review the Record using FIND CURRENT statement and CURRENT-CHANGED function.

Example (Session1.p):-
FIND CustTest WHERE CustTest.cust-num = 1 NO-LOCK.
PAUSE.
FIND CURRENT custtest NO-LOCK.
/* IF CURRENT-CHANGED(custtest) THEN */
/* MESSAGE 'name has been chaged' VIEW-AS ALERT-BOX INFO BUTTONS OK. */
/* ELSE */
DISPLAY CustTest.NAME.

Example (Session2.p):-
FIND CustTest WHERE CustTest.cust-num = 1. /*here the default SHARED-LOCK will upgrad to EXCLUSIVE-LOCK*/
/* FIND CustTest WHERE CustTest.cust-num = 1 EXCLUSIVE-LOCK. */
UPDATE CustTest.Name.

Anyhow in multi-Environment, any one of the above coding get execute at the same time of multi session. So, progress will automatically handle this problem.
 

sridevi.stalin

New Member
@joey.jeremiah:-
Sir,
As per your suggestion I tried out this but it doesn’t make the changes, the same problem is occurring.
The following steps I’ve did,
In Progress-Explorer Tools,
asSPORTSbroker à Server à Advanced Fetures à for Startup Procedure –rereadnolock.
Notes:-
My Sports-Broker name is “asSPORTSbroker”.

In Session2.p have same code as showed above.
And Session1.p just I’ve commented FIND CURRENT st/- .
And I need more information, that where & how to use the –rereadnolock parameter.
Thanks in advance…….
 

Casper

ProgressTalk.com Moderator
Staff member
It's a client parameter, not a database parameter. So you have to start your client session with the -rereadnolock parameter.

Casper
 

kolonuk

Member
Doing some testing, I found that

Code:
FIND table1 NO-LOCK.
PAUSE.
FIND table1 NO-LOCK.
DISPALY table1.

I changed a field in another session from this record while this program was at the pause statement. The DISPLAY did then display the new data. I sent Progress a support email about -rereadnolock, and got a call back, and this is what I was told:

Apparently, the -rereadnolock parameter works (if used in the program above) by getting the up to date database field at the time the second FIND in run.

So why did it work without the -rereadnolock as well, does it actually do anything? Well, according to Progress, the second FIND is inherently unstable, and may either get the new data from the database, or the same record that is still in memory. It seems I am just lucky when I run my little program.

To get round this, I can use the FIND CURRENT statement. But again, that loads the record into memory, and if it changes from the time I do the FIND CURRENT NO-LOCK to my FIND EXCLUSIVE-LOCK, then I still miss the change.

Now, this is just confusing me... I understand that to cut down disk GW&T and access times that records are stored in memory. But if they are not updated when the real database is updated, whats the point? And how do I get the actual data everytime I use a field in a display statement? I don't particularly fancy doing FIND CURRENTs everytime I want the latest data, as I literally have hundereds of programs to check. Unless that is a deliberate feature of Progress?
 

Casper

ProgressTalk.com Moderator
Staff member
Hi there,

before the rereadnolock parameter was introduced (8.3B introduced) a find no-lock retrieved the record from the database, but if there already is a copy in the local bi then that copy is taken. This could sometimes have the effect that a change made in another session isn't retrieved with a no-lock statement. (So called dirty read). The rereadnolock parameter always uses the record retrieved from the database and not the one from the local bi. an therefore always gets the current record.


Regarding the display: If you do a display you do a display of the current buffer, this has got nothing to do with the retrievel of the record. If you retrieve a record yesterday and display it today then the record form yesterday is displayed. But that seems logical to me, so I don't see a problem there.

If you use -rereadnolock then every find with nolock always retrieves the current record. So use -rereadnolock as your default by adding the parameter to all your client sessions.

Regards,

casper.
 

kolonuk

Member
Regarding the display: If you do a display you do a display of the current buffer, this has got nothing to do with the retrievel of the record. If you retrieve a record yesterday and display it today then the record form yesterday is displayed. But that seems logical to me, so I don't see a problem there.

Well, a display was probably the wrong example to use, as we actually output the fields to our own non-progress VB based gui front end...

I think that until we check all our programs to make sure that we are using the FIND properly, it might be an idea to enable the rereadnolock parameter...
 

Casper

ProgressTalk.com Moderator
Staff member
Well, a display was probably the wrong example to use, as we actually output the fields to our own non-progress VB based gui front end...

The same applies here. If you display data then the data you just retrieved is used.That means that while displaying data a record could be changed by someone else (provided you use optimistic locking). For that reason you always have to check before actually commiting the data if the data has changed during the roundtrip to the client.

save-row-changes method does this automagically, but if you don't use this, you have to take care of this yourself (or not if you don't mind :)).
We do this by rereading the record in the actual transaction in a different buffer. If the buffers are different we give a warning to the customer that the data has changed during the time it was displayed on the screen.

Casper
 
Top