Hi David,

EL does an update for each read lock at commit time, setting its version
column to the same value. See my other post - I agree that SELECT FOR UPDATE
is not appropriate for read locks, and I instead suggest a third approach;
that is to do the optimistic lock checks for read locks after the INSERT,
DELETE, and UPDATES for the transaction.

- Phil



dezzio wrote:
> 
> Hi Philip,
> 
> But why does EclipseLink pass the test?
> 
> Clearly the implementation could use SELECT FOR UPDATE when it checks 
> the READ lock's state prior to commit.  If it did that, then both 
> transactions would not succeed, and in fact, due to the likelihood of 
> deadlock in our example case, they both might fail.
> 
> These kind of issues do not get sorted by argument.  They are settled by 
> test cases in the TCK.  For this issue, there is no TCK test case, and 
> thus, ipso facto, OpenJPA complies with the spec.  You can still argue 
> that it doesn't comply with the spec in the best way, and you may be 
> right.  I could be persuaded by understanding the behavior of competing 
> implementations.
> 
> Cheers,
> 
> David
> 
> Philip Aston wrote:
>> Hi David,
>> 
>> Thanks for confirming this. So to summarise where we are, we have:
>> 
>>  1. A reasonable use case that can fail with some unlucky timing.
>> 
>>  2. A technical test case demonstrating the problem that does not rely
>> on unlucky timing.
>> 
>>  3. A disagreement in our readings of whether 1 and 2 are spec.
>> compliant. Personally, I don't share your reading of the spec. In my
>> reading, read locks are safe and provide a concrete guarantee that if
>> locked entity is changed by another transaction, the locking transaction
>> will not complete.
>> 
>> (This is a different QoS compared to a write lock - if a write lock is
>> obtained and the pc flushed, the transaction knows that it will not fail
>> due to another transaction updating the locked entity. Read locks are
>> "more optimistic" and can support higher concurrency if there is minimal
>> contention - many transactions can hold read locks, only one can hold
>> right locks.).
>> 
>> 
>> How can I convince you to change your interpretation of the spec? Anyone
>> else have an opinion?
>> 
>> FWIW, EclipseLink passes the test case.
>> 
>> - Phil
>> 
>> dezzio (via Nabble) wrote:
>>> Hi Philip,
>>>
>>> Let's take a closer look.
>>>
>>> We have two bank accounts, Account[1] and Account[2], shared
>>> jointly by customers Innocent[1] and Innocent[2]. The bank's
>>> business rule is that no withdrawal can be made the draws
>>> the combined total of the accounts below zero. This rule is
>>> enforced in the server side Java application that customer's
>>> use.
>>>
>>> At the start of the banking day, the accounts stand at:
>>>
>>>      Account[1] balance 100.
>>>      Account[2] balance 50.
>>>
>>> Innocent[1] wants to draw out all the money, and asks the
>>> application to take 150 from Account[1]. Innocent[2] also
>>> wants to draw out all the money, and asks the application to
>>> take 150 from Account[2]. By itself, either transaction
>>> would conform to the bank's business rule.
>>>
>>> The application implements the withdrawal logic by doing the
>>> following for each transaction.
>>>
>>> For Innocent[1], read Account[1] and Account[2]. Obtain a
>>> read lock on Account[2]. Refresh Account[2]. Deduct 150 from
>>> Account[1]. Verify business rule, result, sum of balances =
>>> 0. Call JPA commit.
>>>
>>> For Innocent[2], read Account[1] and Account[2]. Obtain a
>>> read lock on Account[1]. Refresh Account[1]. Deduct 150 from
>>> Account[2]. Verify business rule, result, sum of balances =
>>> 0. Call JPA commit.
>>>
>>> Within JPA commit, as seen over the JDBC connections, the
>>> following time sequence occurs. (Other time sequences can
>>> yield the same result.)
>>>
>>> Innocent[1]: Check version of Account[2]: passes.
>>>
>>> Innocent[2]: Check version of Account[1]: passes.
>>> Innocent[2]: Update balance of Account[2], withdraw 150,
>>>                  setting balance to -100: does not block.
>>> Innocent[2]: commit: successful
>>> Innocent[2]: Receives 150.
>>>
>>> Innocent[1]: Update balance of Account[1], withdraw 150,
>>>                  setting balance to -50: does not block.
>>> Innocent[1]: commit: successful.
>>> Innocent[1]: Receives 150.
>>>
>>> After the two transactions:
>>>
>>> Account[1]: balance -50
>>> Account[2]: balance -100
>>>
>>> Clearly the bank would not be happy. What's a developer to
>>> do?
>>>
>>> I think the developer needs an education about what is meant
>>> by the JPA spec. What JPA is guaranteeing is that when JPA
>>> commit is called, the objects with read locks will have
>>> their versions checked. The objects with write locks will
>>> have their versions checked and changed. The objects that
>>> have been modified will have their versions checked, their
>>> information updated, and their versions changed. Clearly all
>>> of these rules were enforced in the above example.
>>>
>>> If the developer had used write locks, both transactions
>>> would not have succeeded. In fact, for the above example and
>>> a similar time sequence, if write locks had been used in
>>> place of read locks, there would have been deadlock.
>>>
>>> Now, if in fact, I'm wrong about my interpretation of the
>>> JPA spec (and it wouldn't be the first time) then you have a
>>> case. I'd be curious to know whether other JPA
>>> implementations pass your elegant test case, and what they
>>> are doing differently that makes it so.
>>>
>>> Also, if I am wrong about my interpretation, then the JPA
>>> TCK needs a test case that will snag this failure, because
>>> OpenJPA passes the current JPA TCK.
>>>
>>> Cheers,
>>>
>>> David
>>>
>>> Philip Aston wrote:
>>>
>>>> Oh yeah - my bad. Try this one instead:
>>>>
>>>> Suppose there are a set of Accounts, and a business rule that says
>>>> that the net balance must be positive.
>>>>
>>>> Innocent wants to draw down on Account 1 as far as possible. It read
>>>> locks the of Accounts, sums up the value, and and subtracts the
>>>> positive total from Account 1. Innocent begins its commit, and its
>>>> read locks are validated.
>>>>
>>>> Meanwhile InnocentToo does the same for Account 2, and commits.
>>>>
>>>> Innocent updates Account 1 and finishes its commit.
>>>>
>>>> The total in account summary is now negative, violating the business
>>>> rule. If read locks worked as I think they should, Innocent would have
>>>> received an OptimisticLockException.
>>>>
>>>>
>>>>
>>>> dezzio wrote:
>>>>> Hi Philip,
>>>>>
>>>>> When two transactions read the same version of AccountSummary, both
>>>>> cannot successfully update its sum.  Only one will successfully
>>>>> commit.
>>>>>
>>>>> David
>> 
>> 
> 
> 

-- 
View this message in context: 
http://n2.nabble.com/Is-the-implementation-of-lock%28LockModeType.READ%29-correct--tp2272546p2329205.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Reply via email to