|
The use of cached queries through second level cache could lead to situations where stale data is returned if data is changed concurrently to query.
Please find attached an example project that reproduces the problem (entry point is QueryCacheTest class).
The test reproduce consistently the problem by controlling the concurrent execution of the query and the updates through an event interceptor, so it is a good base for a regression test.
It inserts two contacts, then it executes on a separate thread a cached query on them. The cached query is blocked through the interceptor after the query is executed but before it is inserted in cache. While the query is blocked the contacts are changed so that next same query should return different results. Eventually the query is unblocked and a new query is executed.
What happens is that the first query puts in cache the data it fetched attaching to it a timestamp which is later than the timestamp of the last modification of the data, even though the data was actually fetched before data was amended. The second query then returns same data because it believes that the cache contains up-to-date data.
A trivial fix would be to get the timestamp for the query cache before executing statements and not after as in current implementation (see put method in https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/cache/internal/StandardQueryCache.java).
|