hazelcast / hazelcast-hibernate

A distributed second-level cache for Hibernate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

QueryCache not working after insert into table

BuriyMedved opened this issue · comments

hibernate 5.2.10
hazelcast 3.8.3
hibernate.cfg.xml cache config part
com.hazelcast.hibernate.HazelcastLocalCacheRegionFactory

    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.use_query_cache">true</property>
    <property name="hibernate.cache.auto_evict_collection_cache">true</property>

Description: cache not working after insert (or delete, not tested on update) into table, for an amount of time equal to cache region timeout (default to one hour).

Source of problem (hibernate code at org.hibernate.cache.spi.UpdateTimestampsCache): Hibernate cache update process consist of two parts. First is preInvalidate, at this step it updates timestamp cache with value equals to region.nextTimestamp() + region.getTimeout(). After transaction completes it calls invalidate and updates timestamp cache with value equals to region.nextTimestamp(). So the second update set timestamp to a value less then it were on first step. The problem is in com.hazelcast.hibernate.local.TimestampsRegionCache, it's maybeInvalidate(...) method does not allow update timestamp to a value less than current. So the query cache timestamp remains in future, not allowing to read from it until the timeout run off.

Same problem on update.

commented

+1

I've faced with this problem too but with query-cache entries.

After several tests, I've found that HazelcastLocalCacheRegionFactory doesn't override nextTimestamp method so use SimpleTimestamper that return a incremental value that tells hibernate that query is not up-to-date

org.hibernate.cache.internal.TimestampsCacheEnabledImpl |[Msisdn] last update timestamp: 6472881205669888, result set timestamp: 6472880983699456 org.hibernate.cache.internal.QueryResultsCacheImpl |Cached query results were not up-to-date

In addition to that: maybeInvalidate call
cache.putIfAbsent(key, new Value(null, nextTimestamp(), ts.getTimestamp())
using the timestamp from the other machine, that can has other time! Even with a very close difference, first load after invalidation is not loaded.

Discussed on #79 & fixed by #140 and will be released in the next version.