-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Clone method to Txn to create an independent copy of a transaction #26
Conversation
@feldgendler thanks for the PR! Can you share a bit more about what you are trying to achieve with this? iradix and memdb by extension are inherently single-writer systems. You can't have a copy-on-write radix tree that can be independently modified by multiple writers without totally changing the design to be lock free etc. It could be possible to safely clone a read-only transaction in MemDB, but iradix has no notion of read-only transactions since transactions are only ever used for mutations. So I'm not sure this method is ever going to be correct. It would be possible to add a Clone method to memdb transactions provided that it always returned a read-only transaction (even if called on a read-write transaction) and so only ever preserved the snapshot of the current transation and not any of it's mutable state. That means you'd never need to clone internal iradix transactions to build it. |
We are already using forked This is our memdb fork: https://github.com/ridge/go-memdb What we need is indeed what you say: a But I don't see a way to implement |
Got it. The part I was missing is that the RO clone of a RW transaction still needs to see the writes that have already taken place in that transaction so far. I was assuming since the MemDB would be read only it wouldn't need a write set or any table-level transactions at all, just the old memdb root. I think that's OK and this implementation is good but would you be able to update the Clone function docs to make this design more explicit - it seems important that users would need to understand the semantics. |
Actually, I'm not sure it is OK. Currently iradix assumes that any radix nodes it has already written (in the LRU cache) in the transaction are not yet visible to any other thread and so mutates them in place. Once you add this clone method even if the other thread never attempts to mutate (which isn't prevented by the API) it can still race since the writing thread modifies the new radix nodes in place and so a reader following the root node might hit a node bing mutated in another thread. The only way to do this safely would be effectively to Commit the transaction and get a root pointer for the new snapshot including current writes, share that as the "read-only" copy, and then reset the write transaction (clear LRU of modified nodes, reset Have you tried running your fork concurrently with |
Not sure what I should write there. The cloned
That's why I clear
Yes, our fork is a central part of a project that's tested extensively with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bearing with me through a few context switches... you're right this does reset the LRU cache which means that it's only copy ing pointers to radix tress which won't be mutated further by either transaction.
I have a suggestion for the doc comment - if you agree I'll add that before merge.
Co-Authored-By: Paul Banks <[email protected]>
Thanks a lot! I'll now submit a PR for |
Updated PR hashicorp/go-memdb#66, ready to merge. |
This PR adds a
Clone
method toTxn
.A subsequent PR will add similar functionality to
Txn
inmemdb
(txn.Snapshot
returning a read-only transaction), dependent on this one.