[hibernate-dev] Consistency guarantees of second level cache

Steve Ebersole steve at hibernate.org
Wed Sep 9 12:16:04 EDT 2015


Some comments inline and then a general discussion at the end...

On Wed, Sep 9, 2015 at 10:32 AM Radim Vansa <rvansa at redhat.com> wrote:

> 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.
>

I said that "TX2 reading "B->1" before TX1 commits is a question of
isolation and preventing READ_UNCOMMITTED access to the data".  In other
words TX2 reading "B->1" in your "timeline" is in fact an example of the
cache preventing READ_UNCOMMITTED access to the data.  So we are saying the
same thing there.  But after that is where we deviate.

The issue with "isolation" is that it is always relative to "the truth of
the system".  This is a historical problem between Hibernate and every
manifestation of caching that has come from JBoss ;)  In this usage (second
level caching) the cache IS NOT the truth of the system; the database is.

So interestingly the data here *is* stale when looked at from the
perspective of the database (again the truth of the system).  And that is
fundamentally a problem.


"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?
>

Again, the problem is that you are registering your own syncs to do
things.  I understand that getting these 2 "events" as close together as
possible is just minimizing the risk.  But thats is an important
minimization.  Yes you still need to decide what to do when something
happens to occur between them.  But minimizing those cases (by shrinking
the gap) is important.

And in regards to 'hibernate.connection.isolation'.. uh, no, absolutely
not.  I never said that.  Not even sure how you go there..



> 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.
>

Well let's look at the example you gave in detail.  And for reference, this
is outlined in the EntityRegionAccessStrategy javadocs.

So for an UPDATE to an entity we'd get the following call sequence:

1) Session1 transaction begins
2) Session1 flush is triggered; we deem that both A and B have changed and
need to be written to the database.
2.a) SQL UPDATE issued for A
2.b) EntityRegionAccessStrategy#update called for A
2.c) SQL UPDATE issued for B
2.d) EntityRegionAccessStrategy#update called for B
3) Session1 transaction commits[1]
3.a) "before completion callbacks" (for this discussion, there are none)
3.b) JDBC transaction committed
3.c) "after completion callbacks"
3.c.1) EntityRegionAccessStrategy#afterUpdate called for A
3.c.2) EntityRegionAccessStrategy#afterUpdate called for B

And again, that is the flow outlined in EntityRegionAccessStrategy:
<li><b>UPDATES</b> : {@link #lockItem} -> {@link #update} -> {@link
#afterUpdate}</li>

So I am still not sure why you need to register a Synchronization.  You
already get callbacks for "after completion".  Perhaps you meant that there
are times you need to do something during "before completion"?


[1] the exact "how* in (3) will vary, but the general ordering will remain
the same.  Making this ordering consistent was one of the main drivers of
redesigning the transaction handling in 5.0


More information about the hibernate-dev mailing list