On 12 Dec 2011, at 11:16, Galder Zamarreño wrote:
On Dec 9, 2011, at 4:51 PM, Manik Surtani wrote:
>
> On 6 Dec 2011, at 11:46, Galder Zamarreño wrote:
>
>> Hi,
>>
>> Re:
https://github.com/infinispan/infinispan/pull/697#r272846
>>
>> When in place, I'd like to use the ability to provide a version externally
with Hibernate in order get versions to come from Hibernate.
>>
>> As indicated by
http://community.jboss.org/wiki/VersioningDesignDocument, this
would enable other Hibernate Cache concurrency strategies to be supported which are not
necessarily transactional/
>>
>> So, opening the debate, would it make sense for versioning to work also with non
transactional environments?
>
> Well, in a non-transactional environment, is there any meaning in maintaining
versions? What happens when a put() fails? How to you ensure the database write
isn't then carried out?
The put call comes from Hibernate, so Hibernate needs to deal with it somehow, otherwise
how is it gonna deal with read/write and nonstrict read/write cache concurrency modes?
I don't know how Hibernate deals with these. :) A corresponding cache.remove() if
the db write fails? But then there is a window where a concurrent thread sees stale data
from the cache …
If we take the case of inserting an entity (as opposed to reading a
entity from db and putting it in the cache), Hibernate provides with two callbacks:
EntityRegionAccessStrategy.insert and EntityRegionAccessStrategy.afterInsert
The first call happens within the Hibernate transaction, and the second after the
Hibernate transaction has completed.
If the cache is transactional, like Infinispan is now, it's at insert time that we do
the cache.put call so we participate of the transaction…etc.
If the cache is read/write or non-strict read/write, you do nothing at insert time cos
the cache is not transactional. Instead, you do the work in afterInsert. If there's
any exceptions at afterInsert, it doesn't really matter because the transaction is
complete and even if the cache.put() didn't work, the entity can get loaded next time
around via a PFER into the cache.
Isn't this risky? Couldn't you see stale data in the cache if:
T1: Write V1 to DB ---- Commit tx
------------------------------------------------------------------------ Write V1 to
Cache
T2: -------------------------------------------Write V2 to DB ---- Commit tx -- Write V2
to Cache
How does Hibernate guard against this?
With an entity update however, I don't see Hibernate doing
anything if the equivalent afterUpdate() call throws an exception. It only seems to log
it. This could lead to the cache containing stale data and being retrieved by mistake by
another tx unless the cache is cleared upon a failure to in afterUpdate().
So essentially using any 2LC implementation with Hibernate that isn't transactional is
dangerous?
Cheers
Manik
--
Manik Surtani
manik(a)jboss.org
twitter.com/maniksurtani
Lead, Infinispan
http://www.infinispan.org