Replies: 2 comments 4 replies
-
In this approach, are both the server updates and the local mutation log just SQL (or some representation that can be reconstituted and applied as SQL)? Basically what you want is a mechanism to snapshot the database at some point, apply some local write transactions, and later restore the snapshot, is that correct? If yes, then I think this can be done with a VFS. As you say, this is similar to a WAL and coincidentally I just implemented WAL within a VFS so there's an existence proof for a big chunk of your idea. You do need to be careful that your database can recover from a crash while writing your WAL (and your local mutation log). Since this VFS is more about behavior than platform, I would probably try to write it as a shim VFS in C that uses another VFS to do the actual reading and writing.
SQLite doesn't guarantee this, but it is currently mostly true. The exceptions are:
The only tricky part I foresee is making sure that SQLite page cache isn't confused upon restoring a snapshot. SQLite uses a counter (offset 24 in the file header) to know when another connection has modified the database and invalidated its cache. It checks whether that counter is different; I'm not sure if it checks that it is larger. If it does then you would need to patch that value to be greater than in any page 1 in the WAL. You will need some side channel to tell your VFS when to snapshot and begin diverting writes and when to restore the snapshot. You could use xFileControl() for this, either with a custom op or you could define a custom PRAGMA with SQLITE_FCNTL_PRAGMA. |
Beta Was this translation helpful? Give feedback.
-
Yes. The server will receive mutations from the client and do whatever it wants with them (apply them, reject them, change them) but, once it is done, it'll send back to the client:
Exactly.
Hmm. Yes, I suppose the tricky part here is that the mutation log could get out of sync with the WAL during a crash.
This is helpful, thanks. |
Beta Was this translation helpful? Give feedback.
-
As you know I maintain an extension that allows multi-writer SQLite. The approach I've taken is one that is pretty complicated and requires all nodes to run the same algorithm.
There are other, simpler, approaches which (in a client-server setup) allow the server to be mostly agnostic to how conflict resolution happens. In these approaches the user can use anything they'd like on the backend (postgres, sqlite, mongo, etc.).
One of those simpler models is the idea of "rebasing" changes on a client.
At a high level:
When the server sends data to the client, the client throws away the file from (2), effectively re-setting its database state to what it was before the client made any local changes.
Then the client applies the changes sent by the server to its state, modifying the actual DB file.
Finally, the client re-plays the mutation log from (1) to get to the new server + local state. If any client-side mutations were incorporated in the update sent by server, the client starts at that position in the log rather than the start of the log.
I'm thinking it should be possible to write a VFS that re-directs xRead and xWrite requests. xWrite would send all local writes to a custom file rather than the main db file. xRead would be updated to read from the local write file if the requested range was updated locally, from the normal file if not.
Does hooking in at the VFS layer sound at all reasonable to you to implement this? I've never ventured into VFS territory so I don't know what gotchas may be lurking there. My assumption is that
xRead
andxWrite
are always reading and writing full pages.Beta Was this translation helpful? Give feedback.
All reactions