-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Fri Nov 27, 2015 1:27 am 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
Hi,

I am using Hibernate 5.0.4, Ehcache 2.10.1 with Derby DB 10.12.1.1. I have an entity named Forest which has simple fields id, name and version.I have configured Ehcache as my SLC. When I fetch the forest entity for the first time I do see this Forest entity getting cached in the SLC. Then I acquire an optimistic lock and commit the transaction. No changes made to the entity. Subsequently when I create a new hibernate session and load the same forest entity it is resulting in a DB hit. I was expecting it to read the entity from SLC instead of hitting the DB.I have tried with both Optimistic* locks and Pessismistic* lock as well as both NON_STRICT_READ_WRITE and READ_WRITE cache concurrency strategies and the behavior is same.

Is this the right behavior and if I want to make sure that the entity is read from SLC is there any configuration that I am missing.

By the way, If I don't perform that optimistic lock I do see the entity getting read from SLC as expected.

Code:
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.getTransaction().begin();
        Forest forest = (Forest) session.get(Forest.class, 5);
        System.out.println("Locking forest");
      //If this below line is removed then the entity is fetched from SLC the next time
        session.buildLockRequest(new LockOptions().setLockMode(LockMode.OPTIMISTIC)).lock(forest);
        session.getTransaction().commit();
       
        session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.getTransaction().begin();
        System.out.println("Reading again ");
      //This results in a DB hit
        forest = (Forest) session.get(Forest.class, 5);


And below is the output with SLC statistic enabled

Quote:
Reading 1298380324
Hibernate: select forest0_.id as id1_0_0_, forest0_.name as name2_0_0_, forest0_.version as version3_0_0_ from Forest forest0_ where forest0_.id=?
Locking forest
Locked
Hibernate: select version from Forest where id =?
Nov 27, 2015 11:03:11 AM org.hibernate.engine.internal.StatisticalLoggingSessionEventListener end
INFO: Session Metrics {
32874 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
2661940 nanoseconds spent preparing 2 JDBC statements;
1836812 nanoseconds spent executing 2 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
18020072 nanoseconds spent performing 1 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
691167 nanoseconds spent performing 1 L2C misses;
6224204 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
Reading again 1103132232
Hibernate: select forest0_.id as id1_0_0_, forest0_.name as name2_0_0_, forest0_.version as version3_0_0_ from Forest forest0_ where forest0_.id=?
SessionStatistics[entity count=1,collection count=0]
Forest ID :5 Name :Forest-One- Version :5

Done
Nov 27, 2015 11:03:15 AM org.hibernate.engine.internal.StatisticalLoggingSessionEventListener end
INFO: Session Metrics {
11095 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
541181 nanoseconds spent preparing 1 JDBC statements;
503787 nanoseconds spent executing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
332023 nanoseconds spent performing 1 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
69856 nanoseconds spent performing 1 L2C misses;
94101 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}


Top
 Profile  
 
 Post subject: Re: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Sat Dec 05, 2015 4:57 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
When you lock an Entity, Hibernate will propagate the lock request to the 2nd level cache too.
If you use READ_WRITE, the cache entry will "locked", meaning that a guard entry will be placed to instruct all other concurrent Sessions to fetch the entry from the db.

To avoid this behavior, you need to switch to NONSTRICT_READ_WRITE.


Top
 Profile  
 
 Post subject: Re: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Sat Dec 05, 2015 5:43 am 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
Hi Vlad,

In fact, I am seeing this behavior with both NONSTRICT_READ_WRITE and READ_WRITE Cache Concurrency Strategy.

Also the most important thing is these sessions are not concurrent. I am acquiring the lock in first session and after closing this session I am opening the second session and trying to load the same object and in the same thread.

-Madhu.


Top
 Profile  
 
 Post subject: Re: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Sat Dec 05, 2015 7:38 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Hi,

I replicated the issue.

It seems that the NonStrictReadWriteEhcacheEntityRegionAccessStrategy doesn this when unlocking the entry:

Code:
@Override
public void unlockItem(SessionImplementor session, Object key, SoftLock lock) throws CacheException {
   region().remove( key );
}


which explains why the entry is removed from the cache.
The second cache entry removal is for ensuring consistency of modifying operations.

A solution is to use the TRANSACTIONAL cache strategy which doesn't do anything on both lock and unlock.

Vlad


Top
 Profile  
 
 Post subject: Re: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Sat Dec 05, 2015 10:07 am 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
Thanks Vlad.

The testOptimisticLocking() test case is the one that I am interested in and exactly replicates the issue.

In the context of testOptimisticLocking() could you help me understand the below points -

1. Are you noticing the same behavior even with READ_WRITE cache concurrency strategy?

2. You have indicated that during the unlock(...) the entity is getting removed from the second level cache. But I am wondering when exactly it is getting called during testOptimisticLocking() method? Is that getting called when the session/transaction ends?

-Madhu.


Top
 Profile  
 
 Post subject: Re: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Sat Dec 05, 2015 11:22 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
1. It behaves the same way for READ_WRITE because the unlock simply puts a new Lock with an expiry timestamp to avoid any concurrent thread from reading inconsistent values.
This is because the cache doesn't know if the database was updated successfully or not, and, to be on the safe side, it chooses consistency over performance. You can find a READ_WRITE test in the same package on the GitHub repo.

2. Those two blog posts that I sent you feature two sequence diagrams that explain this behavior.


Top
 Profile  
 
 Post subject: Re: Optmistic*/Pessismistic* lock causing SLC miss subsequently
PostPosted: Sat Dec 05, 2015 11:51 am 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
Thanks Vlad, that helps.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.