Note that there are some explanatory texts on larger screens.

plurals
  1. POHibernate 2nd level cache ObjectNotFoundException with a high number of concurrent transactions
    text
    copied!<p>We have a Java application that uses MySQL, Hibernate (3.5.1-Final) and EHcache(1.2.3) for our 2nd level cache.</p> <p>Our hibernate.properties isolation level is Read-committed isolation = 2</p> <pre><code># 2-Read committed isolation hibernate.connection.isolation=2 </code></pre> <p>Under a high number of concurrent transactions, we're seeing an issue where certain collections (DB associations) when loaded will throw an ObjectNotFoundException and it appears that the 2nd level cache is returning an old copy of that collection.</p> <p>We have many different types of transactions that access this collection (only reading) and only a couple that will add/delete items from it.</p> <p>We don't see this issue under single transaction load or even moderate transaction load (10 - 20 concurrent connections).</p> <p>For example we have a Character entity:</p> <pre><code>@Entity @Table(name = "CHARACTERS") @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) public class Character extends AbstractCharacter implements Serializable { ... @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @OneToMany(mappedBy = "character", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private Set&lt;CharacterItem&gt; items; </code></pre> <p>We are properly maintaining the object graph when deleting entities by removing them from the collection that they're contained in and calling session.delete().</p> <pre><code> character.getItems().remove(characterItem); session.delete(characterItem); </code></pre> <p>We've tried changing the Set items; CacheConcurrencyStrategy from:</p> <pre><code>@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) private Set&lt;CharacterItem&gt; items; </code></pre> <p>To</p> <pre><code>@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) private Set&lt;CharacterItem&gt; items; </code></pre> <p>With no luck.</p> <p>We don't use database locks instead we use <a href="http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/transactions.html#transactions-optimistic" rel="noreferrer">optimistic concurrency control</a> to catch and retry conflicting transactions.</p> <p>The only 2 solutions we can see at this point is to:</p> <ol> <li><p>Try to catch the <em>ObjectNotFoundException</em> and try to intelligently evict the collection (although there doesn't seem to be enough context in the exception) </p></li> <li><p>Use the <em><a href="http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/NotFoundAction.html" rel="noreferrer">@NotFound(action=NotFoundAction.IGNORE)</a></em> annotation on the items collection, which will ignore and not throw the ObjectNotFoundException (but we have concerns as to how this works with the 2nd level cache and ensure that it's looking at the proper data). </p></li> </ol> <p>I wish there was a @NotFound(action=NotFoundAction.EVICT_2ND_LEVEL_CACHE_RELOAD) where it would evict that object from the cache and attempt to reload the collection.</p> <p>We could also try changing the FetchyType from LAZY to EAGER but I want to try to understand the problem and choose the best solution that will provide that data in our transactions are consistent under high concurrency.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload