[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