Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Optimistic Lock Problem

agustin_cusse
Explorer
0 Kudos

Hello,

I have a problem concerning optimistic locks.

The process is the following:

Process A(Lock-Read-Update-Release):

1-Set optimistic lock.

2-Load data

3-a)Check if lock is still present

b)Read loaded data

4-Promote to exclusive lock

5-Update data

6-Release lock.

Process B (Lock-Read-Release):

1-Set optimistic lock.

2-Load data

3-a)Check if lock is still present

b)Read loaded data

4-Release Lock.

The problem is with item 3-a. How can I check if the lock is still valid if both processes are running in parallel with the same user?

Item 4 of process A promotes its own lock to exclusive, deleting all other locks, then releases the lock.

Process B has to detect if its own lock is still present before reading loaded data to ensure consistency, but I don't know how to do this.

Hope the problem is clear.

Thanks.

10 REPLIES 10

Sandra_Rossi
Active Contributor
0 Kudos

> b)Read loaded data

In your scenario, I don't understand what you mean by "read loaded data". You don't need to read data twice. If someone has changed the data, you'll see that by the fact that you can't promote the optimistic lock to exclusive.

> How can I check if the lock is still valid if both processes are running in parallel with the same user?

You check it's valid when you try to promote the optimistic lock to exclusive (when you call the enqueue function module with 'R' mode). The call fails if it's not valid. See [sap library|http://help.sap.com/saphelp_nw70/helpdata/en/9a/49d91d498b4e489eef193e949db3f7/frameset.htm] for more information.

0 Kudos

Load data ->select from database table into internal table

Read loaded data->read from internal table.

The thing is:

-Process A promotes the lock to exclusive, updates DB and then releases the lock.

*At this point there are no locks on the record(s), and data loaded in process B is inconsistent with data in DB.

-Process B reads the data (I don't promote to exclusive when I read, just when I update).

*At this point it would be useful to check if my optimistic lock for this process still exists or it was overrun by a promotion in another process, for example process A. If I can check this, then I can assure consistency when reading data without the need of setting exclusive locks.

Then my idea is to promote to exclusive only when I update DB.

0 Kudos

> I don't promote to exclusive when I read, just when I update

> \[...\]

> Then my idea is to promote to exclusive only when I update DB

I don't understand what you was trying to achieve previously.

What you say now is exactly the principle of how one's should work with optimistic locks (as explained in the sap library).

So go for it!

0 Kudos

I think I'm missing something in the process, and SAP doesn't specify how to proceed in this case!

The issue is specifically how to determine if my own optimistic lock for a specific process exists without actually having to set an ENQUEUE in 'R' mode..

0 Kudos

>

> I think I'm missing something in the process, and SAP doesn't specify how to proceed in this case!

> The issue is specifically how to determine if my own optimistic lock for a specific process exists without actually having to set an ENQUEUE in 'R' mode..

I'm missing something too

Why do you need to check if the optimistic lock still exists or not, before the user does the update?

It's only when the user saves the data that you must promote the lock to exclusive, and this way you also check if the optimistic lock still exists, both at the same time. If it fails, then you send an error message "sorry somebody has loaded the data, please press "button" to reload data" (or whatever you want). Otherwise you save.

Edit 1 minute later: If you think that the updates can be frequent, then use pessimistic locks in lieu of optimistic locks.

0 Kudos

If I understand you correctly you're actually trying to reload data for a user if some other user changed it in another session (and thus possibly don't want to promote your lock to an exclusive lock). You can do this easily by calling the function module ENQUEUE_READ: All you need to do is check if any optimistic lock (GMODE = 'O') for the object you locked still exists. If yes, you know that in the meantime no exclusive lock was set, so the data must not have changed...

In a way it sounds to me that you're attempting to recognize object/document versions. I.e. instead of locks one could also imagine that you have an additional field in the table with a timestamp or version number, reflecting when the object/document was last updated. So when you read the data you can check later if the information you have is still up-to-date by comparing it to the current timestamp.

Anyhow, my comments might be off, because I probably don't understand what you're trying to do. However, note that your locking approach does not solve the problem if the data was actually updated or not. I.e. somebody might have acquired and exclusive lock (thus invalidating all other optimistic locks), but then not done any update.

Another problem might be that with the screen processing (depending on your solution) the user might not get any update if he/she just reads the data (and thus doesn't trigger any screen processing events)....

Cheers, harald

0 Kudos

Sandra:

The lock is only promoted to exclusive when the data is saved. The problem here is in many cases data is not updated at all, thus there is no need to promote the lock, and therefore no way of assuring the data you're reading is up to date.

The particular case is when another session promotes, saves and releases

Initial Theorical Approach:

1-Load-Lock(O)--


(is locked by me?)->No-.>Load-Lock-Read-Unlock

2-Load-Lock(O)-(is locked by me?)->Yes->Read-Promote(E)-Update-Save---Unlock

-the (is locked by me?) part is the problem. Or we could call it "is my lock still valid?"

Timeline Case 1 (2 sessions same User):

1-Load-Lock(O)--


Read-Unlock

2-Load-Lock(O)-Read-Promote(E)-Update-Save---Unlock

Timeline Case 2 (3 Sessions same User):

1-Load-Lock(O)--


Read-Unlock

2-Load-Lock(O)-Read-Promote(E)-Update-Save---Unlock

3--


Load-Lock(O)-Read--Unlock

Harald:

My approach in the last few day was to try to use the FM ENQUEUE_READ..the problem resides in the way of identifying what lock corresponds to what session. I tried (and almost succeded) recreating the lock owner using the timestamp, WP, sy-host, microsec, etc.. but the time values I get from the GET TIMESTAMP after I execute the ENQUEUE FM are not the same as the ones in the lock. Anyway, discarding the time values, I can recreate part of the lock owner without the TIME stamp and identify a lock in most of "Cases 1", but most probably this will fail in "Case 2".

Covering all of the cases would be the best, but it seems unlikely to this point (at least using O-locks).

Thanks to you both..

0 Kudos

<div style="text-align:left">The lock is only promoted to exclusive when the data is saved. The problem here is in many cases data is not updated at all, thus there is no need to promote the lock, and therefore no way of assuring the data you're reading is up to date.</div>

I'm assuming that you don't do any updates without locking, so I suspect you essentially mean that the user can change data while having the optimistic lock and only when she/he hits save, the lock is promoted. So it sounds like you're defining database data as outdated, if you have uncommitted changes for the data. Since uncommitted changes might never make it back into the database I don't see how that flies.

Or are you trying to model some collaborative process where several people are updating a document and everybody is supposed to see changes others make in real time?

<div style="text-align:left">My approach in the last few day was to try to use the FM ENQUEUE_READ..the problem resides in the way of identifying what lock corresponds to what session.</div>

As I posted above, my assumption was that changed data corresponds to a promoted lock. In that case there should be absolutely no need to identify which lock corresponds to which session. As long as you have optimistic locks, you know that nobody promoted the lock. As soon as somebody does, all the optimistic locks get deleted.

0 Kudos

As I posted above, my assumption was that changed data corresponds to a promoted lock. In that case there should be absolutely no need to identify which lock corresponds to which session. As long as you have optimistic locks, you know that nobody promoted the lock. As soon as somebody does, all the optimistic locks get deleted.

That solves Case 1 indeed. Case 2 is still unsolved since a new optimistic lock has been created after saving. So in Enqueue_read I'll get that the record is locked. This is probably solved using the WP in the key, still not %100 consistency.

Or are you trying to model some collaborative process where several people are updating a document and everybody is supposed to see changes others make in real time?

Kind of...its a process where every time a SO is posted, for every item a quantity is deduced (or not) from a line in a Z table, with thousands of salesorders beeing created, the consistency is a problem here..since the quantity itself is a very important factor determining if it will be updated or not.

Thank you both for your help. I'll be trying a new approach using Shared Memory Objects. Anyway the post will remain open since it was not solved.

Anyway my doubt is still open, I think the most intuitive way is to return the lock argument when you set the lock using the EZ_ENQUEUE... so then you can identify the lock using the ENQUEUE_READ.

0 Kudos

<div style="text-align:left">That solves Case 1 indeed. Case 2 is still unsolved since a new optimistic lock has been created after saving. So in Enqueue_read I'll get that the record is locked. This is probably solved using the WP in the key, still not %100 consistency.</div>

You're right, my solution wasn't thought through and doesn't solve case 2. So I took another look at the available data, but I'm not really convinced that I'd rely on anything there to identify my own lock. The work process number is probably not sufficient, because due to roll-out and roll-in the work process ID might change (I'm assuming that the lock entry contains the reference to the work process number originally setting the lock).

<div style="text-align:left">Anyway my doubt is still open, I think the most intuitive way is to return the lock argument when you set the lock using the EZ_ENQUEUE... so then you can identify the lock using the ENQUEUE_READ.</div>

I guess that doesn't exist (at least it looks like that to me), because you know exactly what you're locking and usually don't need any knowledge about the lock ID (though for optimistic locks that would really be helpful). I agree though that in your case it seems to prevent usage of the optimistic locks.

<div style="text-align:left">I'll be trying a new approach using Shared Memory Objects.</div>

That sounds like a tough approach. Note that shared memory objects are specific to each application server, but based on your scenario I'd assume you need to share data across all application servers.

Based on the little information we have, I keep coming back to the versioning I suggested earlier (i.e. have a version or timestamp associated with the data, so that you can easily see if it changed). Once you have a version/timestamp, you can work with pessimistic locks (i.e. exclusive locks) only and just need to check before you acquire it (and whenever necessary), if the version/timestamp changed (and thus you have to re-read the data). This way you'd also avoid setting many locks that you just need for checking if your session data is still up-to-date.

In principle though it seems that a nice solution would be one that actively informs about updates. In other languages an event framework (doesn't seem to work here, because as far as I know we don't have any "global" events in SAP, except for workflow/job control, but they trigger stuff in separate sessions) or message framework would probably do the trick. In ABAP though our choices seem much more limited (or maybe I have some creative block and I'm missing something obvious)...