I have a transaction occurring on data in a few maps in the same partition. Immediately after this, I have a query on an IMap. I can't use a transactional context for the query because I need PagingPredicate and PartitionPredicate--neither of which TransactionalMap supports. The IMap query is returning old data for the query; Now that I have the results, I then follow this up with a sanity check by accessing the data I expected through the TransactionalMap--and I get different results. The two maps share a parent-child relationship.
I'm calling TransactionalMap.getForUpdate() on the parent, then the child, while a second thread calls TransactionalMap.getForUpdate() on only the parent, and thus stalls. In the first thread I'm making changes to the child, putting both parent and child back into the map, and committing. The second thread now continues and immediately queries the child map through IMap and gets the old child data. Then I call getForUpdate() and get the new child data, detect something's wrong, and retry the transaction. So given threads T1 and T2, keys P and C in the parent and child map, and P_old, P_new, C_old, C_new for the before/after data:
T1: (begin transaction)
T1: Parent.getForUpdate(P) -> P_old
T1: Child.getForUpdate(C) -> C_old
T2: (begin transaction)
T2: getForUpdate(P) ... stalls ...
T1: Child.put(C, C_new)
T1: Parent.put(P, P_new)
T1: (commit)
T2: -> P_new; from prior getForUpdate(P)
T2: Child(IMap).entrySet() -> C_old !!!
T2: Child.getForUpdate(C) -> C_new !!!
I'm currently working on a proof-of-concept test that reproduces the issue. Here are some other vitals:
- Single node member
- Two-phase commit
- Parent in-memory format is BINARY but child in-memory format is OBJECT
- I'm not locking the child for the Predicate query in T2 (because I can't) but I lock it afterwards for that sanity check
Thanks,
Scott