[JAVA-2967] Dirty reads outside the transaction Created: 10/Sep/18 Updated: 11/Sep/19 Resolved: 11/Sep/18 |
|
| Status: | Closed |
| Project: | Java Driver |
| Component/s: | Transaction Management |
| Affects Version/s: | 3.8.1 |
| Fix Version/s: | None |
| Type: | Task | Priority: | Major - P3 |
| Reporter: | Arun Kumar Jain | Assignee: | Unassigned |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Docker for Mac. |
||
| Issue Links: |
|
||||||||
| Description |
|
I am using mongodb 4.0 with latest drivers version 3.8.1 Within a transaction, when a value is changed and is not committed yet, outside the transaction we expect to not see that change. This expectation is not happening. I have written a simple test case to demonstrate this. Here is the link to the entire project containing integration test to demonstrate this. It is running mongodb in a docker container, so depends on docker being installed. |
| Comments |
| Comment by Jeffrey Yemin [ 14/Sep/18 ] | |
|
The sample code here has no explicit abort because each attempt to run the transaction uses a different ClientSession, and closing the ClientSession automatically aborts any uncommitted transaction. If you are trying to re-use the ClientSession for each attempt, you will have to explicitly abort. | |
| Comment by Arun Kumar Jain [ 14/Sep/18 ] | |
|
One thing I observed is that when using java driver, when gettig a Transient Transaction error and retrying the transaction, we have to explicitly abort it. Otherwise we get a 'IllegalStateException - transaction already in progress' when we start it on retry. If we dont explicitly abort and dont start as well when retrying, we get transaction aborted on server error. This is not in sync with the javascript examples given at https://docs.mongodb.com/master/reference/method/Session.startTransaction/#Session.startTransaction. I can demonstrate this with a test case if you need. Please let me know. | |
| Comment by Arun Kumar Jain [ 14/Sep/18 ] | |
|
Thanks Jeff. It is definitely enlightening and cleared a lot of questions for me. | |
| Comment by Jeffrey Yemin [ 11/Sep/18 ] | |
|
Hi Arun, Transactions in MongoDB use snapshot isolation, which don't prevent stale reads. This is not specific to MongoDB. Most modern databases work this way. Here's a part of a presentation which talks about conflicts, specifically around reads: https://www.youtube.com/watch?v=3x_Pf9rQGCo&t=905s. You may find it illuminating. We think though that we can do a better job explaining this in our online documentation, so I'm going to close this ticket now, as the driver and server are working as designed, but please let us know if we can be of further assistance. Thanks for the feedback. | |
| Comment by Arun Kumar Jain [ 11/Sep/18 ] | |
|
Thanks Jeff. I have updated the code with another test case which checks for stale read inside transaction which will lead to a dirty write. Currently this test case is not passing.
| |
| Comment by Jeffrey Yemin [ 10/Sep/18 ] | |
|
Yes, that's correct: all operations within the transaction should be passed the ClientSession instance on which the transaction is started. This is documented in the manual, which is linked to from the What's New section of the Java driver documentation.
| |
| Comment by Arun Kumar Jain [ 10/Sep/18 ] | |
|
Hi Jeff, Yes doing that solves the problem for me. I feel this should be documented better at http://mongodb.github.io/mongo-java-driver/3.8/driver/ So, all the collection operations which have to be included in the transaction similarly need session object? | |
| Comment by Jeffrey Yemin [ 10/Sep/18 ] | |
|
Hi arunkjn The update operation doesn't happen within the transaction unless you pass the ClientSession to the replaceOne call here, as in:
|