When populating second-level-cache by concurrent threads and several threads read the same entities annotated with it comes to a locking-nightmare. This scenario is described in ticket https://hibernate.atlassian.net/browse/HHH-16726. One of the reasons for the bad performance, is that when verifying if the shared cache already contains the key for the natural-id resolution, the current code calls
in order to prevent identical re-cachings (NaturalIdResolutionsImpl.java line 251) This is suboptimal and an overshoot for multiple reasons:
- fromSharedCache call does not only verify if the shared cache contains the cacheKey,
it also tests if the item is readable by comparing session timestamps. If the item is found but considered ‘unreadable', then identical re-caching isn’t prevented. Even more bad: the re-caching attempted is done in vain: NaturaId items aren’t versioned so existing entries get never overriden.
2. fromSharedCache call does return the item if found and 'readable', but we just need the information if the key is cached or not 3. fromSharedCache call does produce unnecessary read-locks in NaturalId-region and as conseguence of the useless re-caching attempts (point 1) also useless write-locks are done with putFromLoad All this contributes to a huge amount of useless locks in NaturalId cache when it’s get populated. It can avoided by simply calling cacheAccess.contains(cacheKey), see linked PR. |