Subject Re: [IBO] Re: Transaction isolcation confusion
Author Helen Borrie
At 11:06 AM 26/08/2003 +0000, you wrote:

>If App2 changes the data, posts and commits. I take it that App1 can
>see the data if it does a refresh (whilst still in a transaction).

If App1 is in a ReadCommitted transaction, it immediately is working with
the latest committed version. But that's not the same as what the user
sees in the buffer, until the buffer has been resynchronised with the
transaction's view.

>
>Can I take it that even if App1 has change some data (but not posted
>& committed) a refresh will also see App2's changed data?

No way. A refresh can *only* see committed work.


>For "potshot" editing of records, it seems that I have a choice
>between:
>
>ReadCommitted: Where I need to know if I'm over-writing a newer
>record before committing. Ether I can do a refresh and compare the
>data,

You can't do a Refresh while the row buffer is in dssEdit.

The plain fact is that ReadCommitted cannot protect that window between
taking the row into edit and posting. If the post succeeds, the update
commits. That IS what ReadCommitted isolation is for. It is the lowest
level of isolation. You *can* use Pess.Locking so that, as soon as one
transac takes a particular row into Edit, no other transac can do so.

>or use a trigger incremented `generation Id' as part of the PK,
>in which case the update will fail.

This tells me that you don't understand how pess.locking works. The pess.
lock effectively *does* create a "generation id" in that it creates a new
record version on the server as soon as a row buffer goes into dssEdit - it
actually POSTS a dummy update and locks the row *on the server*. It's a
total lock-and-block in tiConcurrency; in tiCommitted, it's a
lock-and-block as long as RecVersion and Lockwait are false. You just
have to keep your triggers tidy so that they know not to fire on dummy
updates. If you want to store a switch flag that just gets set for the
dummy update and unset by the real trigger, you can write your trigger to
detect the dummy update and just exit. The LockSQL property is there for
you to customise Pess.Locking for something like this.

>Or, an update trigger on the
>table could signal an event which would cause the dialog to refresh
>the row.

Errrm - that mechanism is called DMLCaching. It is already present in IBO.


>Concurrency: Forget about refreshing, just post and commit the
>changes and catch any exception should a newer record exist and offer
>to show the user the new data or overwrite with their data.

Not quite, but heading in the right direction. While a transaction is
running, it can't see anything done by another transaction. So you will
have to
1) trap the lock conflict exception
2) save the Fields[] array of the current row buffer to a convenient
structure, e.g. a TIB_Row
3) roll back the transaction
4) query for the new view of the row.

Then you can show the user her previous changes (ex the saved row buffer)
and ask if she wants to have another go.

>I think I need to experiment a little.

Yup. It's the best thing to do.

Helen