Git as a NoSQL datastore
github.com
github.com
- Atomic -
Yep, but done with a global lock. - Consistency -
Yep. Since it's NoSQL, there's no referential checks, so this is easy. Git itself probably wants index / commit tree has to be readable, and all attributes.json files be valid. I don't see any reason it wouldn't be. - Isolated -
Sure, works fine, due to that global lock. - Durable -
Check. Once it's written, it's written.So, git doesn't get you any of this for free, and getting Atomic / Isolated is done by introducing a big ugly global lock. I guess I don't see the appeal of using git (or even a model like git) because it doesn't get you any interesting necessary features for free. I see the backup and history thing as a secondary feature -- neat, but not worth sacrificing ACID for.
That said, cool idea -- there's not a lot of code you need to get to a reasonably small codebase.
Also, you're not taking into account the things that Git does give you that typical databases don't, like branching and merges
There's no automatically fixing a conflict so the second transaction fails. Since there's full isolation that's pretty standard optimistic locking: http://en.wikipedia.org/wiki/Optimistic_locking
In most cases the transaction would succeed if it was automatically retried.
It's a tiny, rock-solid executable that stores data in a single binary file and supports sql access. Access to the file is globally locked. It's good enough for testing out a project on a single developer's machine but the global lock makes it hard to use in a multi-user production scenario.
In a similar vein I could see git as a widely available, rock-solid, "quick and dirty" way for a project to store and retrieve documents.
Is there something else I'm missing?
You could get around some of the limitations by creating a branch for every session (though probably not on a high volume site), but then you will have lots of interesting problems once a session ends and you have to merge all changes back into master.
I think it's easily fixed with a merge, as I described here: http://news.ycombinator.com/item?id=1929691
> Since it's NoSQL, there's no referential checks, so this is easy.
Consistency is quite easily achieved by putting the consistency checks into appropriate Git hooks. That way, Git would not allow any commit/pull of inconsistent data. A "rollback" is then trivial, as this only has to be done in the local working directory. So regarding consistency, Git provides everything that SQL databases provide, not just the limited NoSQL interpretation of "consistency".
Also note that this already happens in the traditional use of Git: There, consistency checks are called "building the application and running the test suite". It is a vital part of continuous integration systems. So consistency checks are not only theoretically possible, but already actively practiced with Git.
My idea was that if there are concurrent transactions, then you just need a merge when the second one commits.
This is "optimistic locking": since they're probably updating different subdirectories it would be a trivial merge. If they update the same attribute of the same entity (i.e. they both change the same line of the same attributes.json file) then there's a conflict and the second commit fails.
This still requires a lock but only a tiny one, just at the moment of actually updating refs/heads/<branchname> (whereas right now it's around the whole transaction which obviously sucks).
Are there any flaws in that?
The reason I haven't done it yet even though it sounds pretty trivial is that with Grit (the Ruby Git library) the merge will need to use the working directory and that's a problem for concurrency (and also because I want the working directory to be useable by a human). I was thinking that with a bit of extra work I could make it happen in memory somehow.
Paul
I expect to see a lot more 'interesting' projects that create NoSQL datastores in creative ways.
My intent was to use it in a document system using Operational Transforms, which side-stepped the issue of concurrent access; only the canonical representation of client data would need to be written, so it was serial writing
having history might not be a big deal, but having branches IS!.
It is great for stuff like testing some new set of pages on a staging server and then 'adding' them to the currently running production server which kept changing while you were working on the stage. Try that with SQL!
Bup: Git based backups - https://github.com/apenwarr/bup
http://eigenclass.org/hiki/gibak-backup-system-introduction
http://eigenclass.org/hiki/gibak-0.3.0
https://github.com/pangloss/gibak for an improved fork (last commit in 2008, but still...)
"Even when a backup is incremental, you don't have to worry about restoring the full backup, then each of the incrementals in turn; an incremental backup acts as if it's a full backup, it just takes less disk space"
.... nice!
It's good for prototyping, though. (And I hear it's good at managing changes for source code!)
YECCH
So, uh, can't we just make an efficient, well-designed, C library for accessing those data structures, write BSD-licensed wrappers as consenting adults, and get on with our lives? I'm speechless.
Is writing an append-only log data-structure system really that hard? Ok, then.
At the same time, we're also funding work on libgit2, which is an efficient, well-designed C library for accessing those data structures. There's also wrappers for consenting adults. http://libgit2.github.com
I have a library for managing distributed graphs on top of an append-only log file, but it's got different design trade-offs than git does - It's for a specific C/Lua project, and the semantics of the data don't match git's.
this gives me some ideas, good stuff.