-
1. Re: concurrency & transactions question
Manik Surtani Aug 9, 2010 7:36 AM (in response to Konstantin Sobolev)Are you using this for a JPA application? If so, you probably want to use Hibernate since Hibernate's 2nd-level-cache integration with Infinispan handles this.
-
2. Re: concurrency & transactions question
Konstantin Sobolev Aug 9, 2010 11:40 AM (in response to Manik Surtani)No, I'm using my own persistence layer.
Could you give me any details on how Hibernate+Infinispan handles this? Versioning?
It actually looks very similar to write-skews described in JBossCache docs:
http://docs.jboss.org/jbosscache/3.2.1.GA/userguide_en/html/transactions.html
Section 11.1.1.2.2. Concurrent Writers and Write-Skews
-
3. Re: concurrency & transactions question
Johan Andries Aug 10, 2010 4:44 AM (in response to Konstantin Sobolev)You could probably start a transaction in T2 (which you commit after the put of V1), and do
cache.getAdvancedCache().lock(K);
before you do the c.get(K) operation. That way the put of V2 in T1 (or at least the commit if you do not configure eager locking) will block until the transaction of T2 has finished. See SyncReplLockingTest for an example.
Important remark voor 4.1 RC2: this explicit locking does not seem to work in distributed mode, only local and replicated mode. I should probably modify SyncReplLockingTest to run in distributed mode and submit it as a defect.
Johan.
-
4. Re: concurrency & transactions question
Manik Surtani Aug 10, 2010 6:11 AM (in response to Konstantin Sobolev)You can have a look at the source code of the Infinispan 2nd level cache adapter in the Hibernate src tree. It makes use of putForExternalRead(), but also makes use of its own versioning.
To simplify this further there is a JIRA on the roadmap to make internal entry versioning explicit and externally accessible.
-
5. Re: concurrency & transactions question
Manik Surtani Aug 10, 2010 6:15 AM (in response to Johan Andries)Important remark voor 4.1 RC2: this explicit locking does not seem to work in distributed mode, only local and replicated mode. I should probably modify SyncReplLockingTest to run in distributed mode and submit it as a defect.
Yes, please do clone and update the test, and if it still is a defect please report it using JIRA.
-
7. Re: concurrency & transactions question
Konstantin Sobolev Aug 10, 2010 7:37 PM (in response to Manik Surtani)I've reviewed it, and as I understand it most of the logic is in the http://fisheye.jboss.org/browse/Hibernate/core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/PutFromLoadValidator.java?r=HEAD
My scenario would be translated to:
- T1: tx.begin()
- T2: cache.get(K) --> miss; causes PutFromLoadValidator.registerPendingPut(K)
- T2: V1 = DB.read(); old state
- T1: DB.write(V2)
- T1: cache.invalidate(K) => PutFromLoadValidator.invalidateKey(K); invalidates T2's pending put
- T1: tx.commit()
- T2: attempt to putFromLoad, but PutFromLoadValidator.acquirePutFromLoadLock returns false
result: cache.get(K) == null
Could you confirm I got it right?
-
8. Re: concurrency & transactions question
Manik Surtani Aug 11, 2010 6:49 AM (in response to Konstantin Sobolev)Yep.
-
9. Re: concurrency & transactions question
Konstantin Sobolev Aug 11, 2010 11:27 AM (in response to Manik Surtani)Thanks. How about this race then, is it possible?
- T1: tx.begin()
- T1: DB.write(V2)
- T1: cache.invalidate(K)
- T2: cache.get(K) - miss
- T2: V1 = DB.read(); old state (isolation!)
- T2: cache.putFromLoad(K, V1)
- T1: tx.commit()
IMHO invalidate() must block not only previous pending puts, but all future puts as well, untill current tx commits.
In the other words it must ensure that cache.get(K) is null right after tx has ended.
-
10. Re: concurrency & transactions question
Manik Surtani Aug 11, 2010 12:11 PM (in response to Konstantin Sobolev)Yes, it will hold on to the write lock until the tx completes.