[hibernate-dev] Consistency guarantees of second level cache

Radim Vansa rvansa at redhat.com
Wed Sep 9 11:31:56 EDT 2015


Thanks for correcting the terms, I'll try to use 'isolation'.

TX2 reading B = 1 is not READ_UNCOMMITTED - value B = 1 was committed 
long ago (it's the initial value). It's reading A = 2 what can be 
considered read uncommitted (not isolated enough), but as the cache has 
nothing to do with that entry, we can't really prevent it - it's already 
in the DB. So it's really rather a stale read of B. If my terms I wrong, 
I apologize.

"as close together as possible" is not enough - either you allow certain 
situation to happen (although you might try to minimize how often), or 
you guarantee that it does not happen. So, do I understand it correctly 
that 2LC should check ' hibernate.connection.isolation' and behave 
accordingly?

In 2LC code I am sometimes registering synchronizations but always through

SessionImplementor.getTransactionCoordinator() 
.getLocalSynchronizations().registerSynchronization(...)

- I hope this is the right way and not asking for trouble. I usually 
just need to do something when I know whether the DB has written the 
data or not - Hibernate calls the *AccessStrategy methods well enough in 
the beforeCompletion part (or I should rather say during flush()) but 
sometimes I need to delegate some work to the afterCompletion part.

Radim


On 09/09/2015 04:51 PM, Steve Ebersole wrote:
> To be precise when you talk the stale data you are really asking about 
> isolation.  TX2 reading "B->1" before TX1 commits is a question of 
> isolation and preventing READ_UNCOMMITTED access to the data.  The 
> problem is the split in the notion of "commit".  Those should be "as 
> close together as possible".  For what it is worth, Hibernate commits 
> its work via Synchronization as well.  My preference (and this is 
> based on years of fighting problems specifically between Hibernate and 
> TreeCache/JBossCache/Infinispan in regards to Synchronization 
> ordering) is that hibernate-infinispan piggyback on Hibernate's 
> transaction handling.  Actually, I thought this is why we made some of 
> the transaction changes we did in Hibernate.. so that you could have a 
> consistent view of the transaction across jdbc/jta in 
> hibernate-infinispan.  In my experience, having 
> hibernate-infinispan/Infinispan register its own Synchronization to 
> control this stuff is just asking for a lot of trouble.
>
> Anyway, this also gets into the meaning of the concurrent access 
> strategies.  Which access strategy are you talking about in 
> particular?  I assume you mean the `transactional` strategy, just 
> making sure.
>
>
>
>
> On Wed, Sep 9, 2015 at 6:58 AM Radim Vansa <rvansa at redhat.com 
> <mailto:rvansa at redhat.com>> wrote:
>
>     Hi,
>
>     I've been fixing a lot of consistency issues in Infinispan 2LC lately
>     and also trying to improve performance. When reasoning about
>     consistency
>     guarantees I've usually assumed that we don't want to provide stale
>     entries from the cache after the DB commits - that means, we have to
>     invalidate them before the DB commit. This is a useful property if
>     there
>     are some application constraints on the data (e.g. that two entities
>     have equal attributes). On the other hand, if we want the cache
>     synchronized with DB only after the commit fully finishes, we
>     could omit
>     some pre-DB-commit RPCs and improve the performance a bit.
>
>     To illustrate the difference, imagine that we wouldn't require such
>     atomicity of transactions: when we update the two entities in TX1 and
>     one of them is cached and the other is not, in TX2 we could see
>     updated
>     value of the non-cached value but we could still hit cache for the
>     other
>     entity, seeing stale value, since TX1 has committed the DB but did not
>     finish the commit yet on ORM side:
>
>     A = 1, B = 1
>     TX1: begin
>     TX1: (from flush) write A -> 2
>     TX1: (from flush) write B -> 2
>     TX1: DB (XA resource) commit
>     TX2: read A -> 2 (handled from DB)
>     TX2: read B -> 1 (cached entry)
>     TX1: cache commit (registered as synchronization) -> cache gets
>     updated
>     to B = 2
>     TX1 is completed, control flow returns to caller
>
>     Naturally, after TX1 returns from transaction commit, no stale values
>     should be provided.
>
>     Since I don't have any deep experience with DBs (I assume that they
>     behave really in the ACID way). I'd like to ask what are the
>     guarantees
>     that we want from 2LC, and if there's anything in the session caching
>     that would loosen this ACIDity. I know we have the
>     nonstrict-read-write
>     mode (that could implement the less strict way), but I imagine this as
>     something that breaks the contract a bit more, allowing even larger
>     performance gains (going the best-effort way without any guarantees).
>
>     Thanks for your insight!
>
>     Radim
>
>     --
>     Radim Vansa <rvansa at redhat.com <mailto:rvansa at redhat.com>>
>     JBoss Performance Team
>
>     _______________________________________________
>     hibernate-dev mailing list
>     hibernate-dev at lists.jboss.org <mailto:hibernate-dev at lists.jboss.org>
>     https://lists.jboss.org/mailman/listinfo/hibernate-dev
>


-- 
Radim Vansa <rvansa at redhat.com>
JBoss Performance Team



More information about the hibernate-dev mailing list