openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Philip Aston <philip.as...@oracle.com>
Subject Re: Is the implementation of lock(LockModeType.READ) correct?
Date Fri, 06 Feb 2009 01:08:26 GMT


There's an error in my original test case - it can fail the assertion
due to writes of the same value being optimised away. This is why it
failed so fast. I've fixed the test case, but now it fails only very rarely.

This prompted me to write a separate test case (imaginatively titled
Test2), that doesn't rely on lucky timing. This fails every time with
OpenJPA 1.1 and 1.2, so long as the entity class is enhanced. The test
case passes using EclipseLink.

Updates attached.

Should I open a bug?

- Phil


Philip Aston wrote:
> Hello OpenJPA people,
>
> I don't think the OpenJPA implementation of lock(LockModeType.READ) is
> correct. Please tell me where I'm mistaken.
>
>
> JPA 1.0:
>
>     If transaction T1 calls lock(entity, |LockModeType.READ|
>     <http://java.sun.com/javaee/5/docs/api/javax/persistence/LockModeType.html#READ>)
>     on a versioned object, the entity manager must ensure that neither
>     of the following phenomena can occur:
>
>         ...
>
>           *P2 (Non-repeatable read): Transaction T1 reads a row.
>           Another transaction T2 then modifies or deletes that row,
>           before T1 has committed. Both transactions eventually commit
>           successfully. * 
>
>     *Lock modes must always prevent the phenomena ... P2.*
>
>
> An application should be able to read lock a row from which it only
> reads (say R1), and be sure that it will be consistent with a row it
> both reads and writes (say R2). That is, T1 will commit and R2 will be
> updated if and only if R1 has not been changed.
>
> I would expect an implementation to remember the version of R1 at the
> time the lock is acquired, then perform an additional version check
> (additional SELECT) on R1 after doing the UPDATE to R2, rolling back
> the transaction if the R1 version has changed.
>
> This is not how I observe OpenJPA 1.1 or 1.2 behaving. When the
> application calls commit() on T1, OpenJPA does the additional check,
> but does so before the UPDATE. This presents a window between the
> SELECT and the UPDATE where evil T2 can overwrite R1 and commit,
> before T1 commits and changes the value of R2. Although T1 committed
> last, its read lock has been ignored and R1 is now inconsistent with R2.
>
> Test case attached. This fails pretty quickly (usually sub-second,
> occasionally a minute or two) on my dual core machine against a local
> Oracle database. A couple of further observations:
>
>    1. There are no problems with LockModeType.WRITE. If you change the
>       test case to use that, it will run and run. I contend that
>       LockModeType.WRITE should not be required for correct behaviour
>       for this test case.
>    2. It "works" if I run with non-enhanced classes, since then there
>       is no change detection and all rows get written and version checked.
>
>
> - Phil
>
>


Mime
View raw message