Question Following the way of changing a value

Hi guys,

With the help of manie I know how to acces a data properly in the purpose of commit a new value.
Like this:
Code:
DEFINE BUFFER bCustomer FOR CUSTOMER.

DO FOR bCustomer TRANSACTION:
    FIND bCustomer WHERE ROWID( bCustomer ) = ROWID( CUSTOMER ) EXCLUSIVE-LOCK NO-ERROR.
    IF AVAILABLE bCustomer THEN DO:
        bCustomer.value = new-value.
    END.
end.

Now I would like to acces it for reading only. As of today I just write querry like this:
Code:
FIND FIRST customer WHERE customer.Id = 55 NO-LOCK NO-ERROR.

IF NOT AVAILABLE customer THEN
    RETURN.
It works perfectly at the begining of a procedure. But when I did already a bit of data acquisition and other operation what is the best way to consult data when another user can changed it with an "EXCLUSIVE-LOCK".

So I need your help :)

Have a nice day
 

Cringer

ProgressTalk.com Moderator
Staff member
Don't use FIRST. That's not a solution to your problem, but a principle. In particular in your example above. You would only expect a single result as you're looking on what seems to be a unique key. In fact, if your query returns more then one result you want to know about it, and FIRST would hide that.
I'm not sure if I understand the question. Do you mean the process flow is like this:

User 1: find record and waits
User 2 do some updates
User 1: Use the record we found ages ago

Or is the process flow more like

User 1: Find a record
User 2: do some updates
User 1: find old records again and do something
 
Maybe more like your first case, like this:
User 1: find record and do some update
User 2: Want to access the same record as user 1 will the updating process is runing.
User 1: as finished the update process.
 

TomBascom

Curmudgeon
If you have a record in your session's buffers your COPY of it will not be impacted by another user's actions. You can continue to use that copy for as long as you would like.

If the other user changes something you will never know - unless you re-read the record at some point.

There is no notification between sessions of changes to data by other sessions. The only way to see such things is to constantly poll the database looking for changes.

At first glance that might sound terrible. Chaos is sure to ensue. Users will be confused never knowing if the data they are looking at is valid and never being sure if their changes are still changed etc.

But that is not the reality. There is no chaos and users are not confused (at least not because of this issue ;) )

The typical business application has a read to write ratio of 500:1 or more. Data actually changes very slowly. There is also a lot of "locality of reference". Data is is used, and reused, in "working sets" of logically inter-related bits and the odds are very, very low that someone else is going to change your data while you are working with it.

Keeping transaction blocks very small and tightly scoped goes a long ways towards preventing problems because it means that data changes are immediately visible to anyone that cares about them.

You could, in theory, go to a great deal of trouble writing code to try to detect and react to changes coming from other sessions. This will be a very expensive development effort and it will be hugely expensive from a performance perspective -- among other things you will have to read everything a lot more often (500:1 may become 5,000:1).

IMHO you are much better off with a little bit of error handling code and maybe some business logic to protect any parts of the application that are especially prone to conflict; perhaps you could, for instance, ensure that only one user is allowed to update an order and all child tables at a time -- but do that via application-level business logic rather than a db level record-locking scheme.
 

tamhas

ProgressTalk.com Sponsor
If it matters that you have the absolute latest value at some point in your code, then read it again.

In particular, if you are updating a record, read it no-lock, do any UI, read it again, check whether the original is different from the current, if the same, then commit your changes, if not the same, decide if the differences matter, if they don't, then merge and commit, if they do, then go back to the user for correction. There are nice features in temp-tables for managing this with little code.
 

Cecil

19+ years progress programming and still learning.
Just chucking in my 2 cents.
Something else to consider when using an EXCLUSIVE-LOCK on a find statement is WebSpeed. By default, WebSpeed has "lockwait timeout" of only 10 seconds and then it raises a STOP condition if it's unable to get an record lock.

So, in some conditions where your code is running in a batch mode .i.e. WebSpeed, AppServer etc. you might want to consider having a NO-WAIT option in combination with testing if the record is LOCKED and handle the situation appropriately.

Use the NO-WAIT option wisely.
 

TomBascom

Curmudgeon
0) You should always use the -rereadnolock parameter. I cannot think of a use case for not using it.

1) I pretty much always code FIND ... EXCLUSIVE-LOCK NO-WAIT NO-ERROR. There are not many cases where I would want to get in a queue and wait for the lock.

2) With a FIND ... EXCLUSIVE-LOCK NO-WAIT NO-ERROR the following IF AVAILABLE needs to handle two possible scenarios: no record satisfies the WHERE clause (with FIND by RECID or ROWID perhaps the record got deleted by someone else) and the record exists, but is locked. You do not always need to care which scenario it is -- often it is adequate to simply retry the operation. Or skip it and move on.
 

Cecil

19+ years progress programming and still learning.
Thank you @TomBascom and @tamhas .

It's good to know @Cecil.

I'm sorry to be this blind, but I don't know what you are talking about with webspeed and AppServer, can you explain ?


AppServer and WebSpeed are products of Progress Software. If you are not sure of what they are I'm guessing that you are not using them? Which if that's the case, you don't need to worry about them at this stage.
 

Rob Fitzpatrick

ProgressTalk.com Sponsor
I would add that if you are not using them now, you probably shouldn't use them in future. In short, they are headless database clients that allow you to run ABL application code on a server. Both feature some limited scalability features.

They are mature products that are probably close to end of life. Both would be replaced by Progress Application Server for OpenEdge, or PASOE. (It is sometimes known by its former name, "Pacific" Application Server for OpenEdge.)

What is PASOE?
 

TomBascom

Curmudgeon
For completeness... the default lock wait timeout for non-webspeed clients is 30 minutes. The startup parameter is "-lkwtmo".

30 minutes is an eternity. IMHO the default should be 10 seconds everywhere and the minimum should be measured in milliseconds but the documented minimum for non-webspeed connections is 60 seconds and the units are in whole seconds.
 
I would add that if you are not using them now, you probably shouldn't use them in future. In short, they are headless database clients that allow you to run ABL application code on a server. Both feature some limited scalability features.

They are mature products that are probably close to end of life. Both would be replaced by Progress Application Server for OpenEdge, or PASOE. (It is sometimes known by its former name, "Pacific" Application Server for OpenEdge.)

What is PASOE?
Yes I heard about it a bit go when browsing on the news section of progress websit. But I'm afraid that I can't put this strategy up.

For completeness... the default lock wait timeout for non-webspeed clients is 30 minutes. The startup parameter is "-lkwtmo".

30 minutes is an eternity. IMHO the default should be 10 seconds everywhere and the minimum should be measured in milliseconds but the documented minimum for non-webspeed connections is 60 seconds and the units are in whole seconds.
Thank you for this crucial information .
 
Top