-
Notifications
You must be signed in to change notification settings - Fork 3
Implement True Snapshot Isolation for LevelDB #49
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
Comments
We often have dual operations one that is The reason is that currently However with this transaction concept, it may be possible to do async function doX (t?: Transaction) {
const f = async (t) => {
t.put();
t.del();
};
if (t == null) {
const t = await this.db.transaction();
f(t);
await t.commit();
} else {
f(t);
}
}
async function transact (t, f) {
if (t == null) {
const t = await this.db.transaction();
const r = f(t);
await t.commit();
return r;
} else {
return f(t);
}
}
async function doY (a: number, b: number, t?: Transaction) {
await this.transact(t, async () => {
// ... do stuff with t
});
} This should mean if you pass a transaction, it applies the operations against the transaction. If you don't it creates its own transaction and commits to the database. You may need to use try catch above. This would again cut down on the number of code we have and simplify it quite a bit. |
So you'd need to:
The first one is the toughest to eventually merge into leveldown. It would be a fork of leveldown supporting this feature, and we would have to create our own "forked" bundle that bundles the forked leveldown supporting snapshots. |
A proper MVCC system would also include lock management centralised at the DB class which would then coordinate multiple transactions together. This would be similar to how we are currently using async-mutex to synchronise operations. You then have concurrency control introduced. It would generalise the entire special casing of async mutexes that we are dealing with right now. |
In the process of solving #47 we have created our own makeshift transaction/snapshot system. It operates with read-committed isolation level. The
However as a further extension, it may be possible to also incorporate:
To create an in-memory snapshot. |
This issue is more relevant to js-db now instead of EFS. EFS makes use of DB transactions. |
Issue moved to MatrixAI/js-db #4 via ZenHub |
Is your feature request related to a problem? Please describe.
Proper MVCC transactions make use of a snapshot that represent the state of the database. As mutations (put & delete) build up, they apply to the snapshot. This makes it easier to build up a transaction by composing procedures/functions that mutate a transaction object. It means you get read-after-write consistency within the snapshot. Where you may have an operation that depends on the state of the database. Like let's say a counter increment. But if the prior mutation to the transaction already incremented the same counter, it would be incoherent for the subsequent mutation to plus 1 to the counter thinking the counter hasn't already been incremented.
Right now leveldb already supports snapshots natively. However it's not exposed via the JS wrapper. There are pre-existing issues.
If we could have snapshot isolated transactions, it would simplify some of our algorithms here for inodes especially since we have counter increment operations that result from linking and unlinking the inodes.
Describe the solution you'd like
Have a snapshot ability for the leveldb that we can expose through our
DB
abstraction. Similar to the python library of leveldb: https://plyvel.readthedocs.io/en/latest/api.html#snapshotNote that a snapshot by itself is not sufficient to provide snapshot-isolated transactions. A combination of a "mutating" snapshot and the batching object which can overlay changes on top of the leveldb database can produce snapshot-isolated transactions.
This would mean an API like:
In fact I suspect it would be possible to just extend the
Batch
object to have this.Additional context
The text was updated successfully, but these errors were encountered: