[jboss-user] [JBoss Cache: Core Edition] - on child insert parent, child collection updated in DB but N
dukehoops
do-not-reply at jboss.com
Tue Mar 3 01:54:41 EST 2009
In abtract
I am load testing a Hibernate/JBC3 web application and am seeing that about 7% of the time inserting a child entity into a previously-empty collection results in update (INSERT) into DB but local cache remains unchanged:
-collection Node is still empty
-there is no child Entity node
This does not appear to be a race condition, as from that point on in any TX parent.getChildren() will return an empty collection from cache (even though DB state is non-empty).
This seems vaguely similar to https://jira.jboss.org/jira/browse/JBCACHE-1481 but that issue's marked resolved.
In detail
App Config
Single Tomcat 6 NIO
Hibernate 3.3.1.GA
JBossCache 3.0.3.GA - Local Cache only; using default Locking (MVCC); READ_COMMITTED isolation
BTM JTA transaction manager
Load Test
JMeter load test where each of userCount users loop over the following scenario of HTTP requests:
for(I iterations)
| {
| login();
| thinkTime //sleep;
| getRestrictedData(); //requires being logged in
| thinkTime //sleep;
| logout();
| thinkTime //sleep;
| }
|
App Pseudo Code
Domain Model
-Transactional entity caches User, UserSession; collection cache User.sessions
| class User{
| private long id;
| private Set<UserSession> sessions; //1-to-[0,1] modeled as one-to-many with unique constraint
|
| public boolean isLoggedIn()
| {
| return !getSessions().isEmpty();
| }
|
| public void addSession(UserSession us)
| {
| us.setUser(this);
| sessions.add(us);
| }
|
| public Set<UserSessions> getSessions()
| {
| return sessions;
| }
| }
|
|
|
| class UserSession
| {
| private User user;
|
| void setUser(User usr)
| {
| this.user = usr;
| }
|
| }
Service Methods
//insert new UserSession if credentials check out
| //throw exception otherwise
| public void login(id, credentials)
| {
| User usr = dao.getUser(id);
| if(credentials == bad)
| {
| throw new AuthenticationException();
| }
| usr.add(new UserSession());
| }
|
| //return data only if a userSession is present
| //throw exception otherwise
| public String getRestrictedData(id)
| {
| User usr = dao.getUser(id);
| if(! usr.isLoggedIn())
| {
| throw new AuthorizationException("not logged in");
| }
| return data;
| }
|
| public void logout()
| {
| //clear userSessions
| }
| }
|
Problem Observed
When userCount==1, no requests fail, regardless of thinkTime (varied latter between 0 and 2000ms)
| When userCount is > 30, about 10-20% of users eventually (and most of the time on the very 1st iteration), fail like so:
| -login() //success
| -getRestrictedData() //fail: user not logged in
|
| My load test terminates on 1st failure. Inspecting states of DB and JBoss Cache (via JMX) reveal:
| -DB does have record of UserSession in question
| -In Collection cache: User.sessions Node contains an empty PersistentSet
| -In entity cache: User node references above (empty) collection; no node for UserSession that is in DB;
| -hibernateVersion of User (parent) is updated in DB but not in Cache node
|
| Musings
|
| Though I am unable to repro this problem with 1 user, it is not possible for user A to affect state of user B in my app. So I am not quite clear on what's going on here. Since I don't (yet) understand the internals of MVCC (and jbc in general), I'd appreciate any thoughts and answers to the following questions that'll help me narrow down the problem:
|
| 1. In MVCC, how many threads participate in login() method? Is it the case that one thread does the read and writes a versioned update, but another thread merges the updated data *after* TX commit?
|
| 2. A somewhat dated http://www.jboss.org/community/docs/DOC-10266 wiki says there exists a faulty assumption about consistent ordering of synchronizations in Hibernate/JBC (problem #5). Has that been addressed? If not, could that be causing given problem?
|
| 3. Same wiki's problem #7:
| anonymous wrote : Hibernate should either retry or JBossCache should fail silently on this. (Nikita: not sure what 'this' refers to) As long as the data is stored in the db correctly, failure putting the data in the cache could fail silently. Next time someone requests the entity, it'd be retrieved from db and put in the cache.
|
| This paragraph seems to imply that it is normal that cache is not updated on insert of new UserSession during login(). However, it also expects subsequent User.getSessions() to result in a DB read (and a put into cache). But what I am seeing that User.getSessions() in getRestrictedData() results in a cache hit on a (stale) node containing empty set user.sessions. Should addSession() in login() result in User.sessions collection node being invalidated (to be populated during subsequent reads) or being updated with a new reference to UserSession node? Similarly, should addSession() result in put into UserSession entity cache, or is that put expected to occur only on subsequent read?
|
| 4. Finally, turning up debugging shows multitude of these 2 types of messages. These are emitted seemingly in failing and succeeding requests:
|
| anonymous wrote : [3/2/09 16:27:38:268] DEBUG [d585d9d4-cc59-4b35-b717-d26c97db8f89,ltester-100000] org.jboss.cache.interceptors.InvocationContextInterceptor - FAIL_SILENTLY Option is present - suspending any ongoing transaction.
| | [3/2/09 16:27:38:269] DEBUG [76225fe7-1541-4960-9c2d-cdbe1330f5c5,ltester-100001] org.jboss.cache.invocation.CacheInvocationDelegate - putForExternalRead() called with Fqn /com/doppelganger/domain/User/userSessions/COLL/com.doppelganger.domain.User.userSessions#183 and this node already exists. This method is hence a no op.
| |
|
| Does the latter say that a collections cache node will not be updated because one already exists. What if existing node contains an empty collection but the candidate node contains a non-empty collection?
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4214380#4214380
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4214380
More information about the jboss-user
mailing list