我看了布莱恩·坎特里尔(Bryan Cantrill)的演讲“Platform as a Reflect of Values:Joyent,Node.js and Beyond”,我想他能把我一段时间以来一直感觉到的话说出来:如果没有一款软件能反映你的价值观,那么你是时候构建那个软件了。
我有点同意他的说法,因为这已经发生在我身上了。我渴望一个具有某一组值的数据库,几年来,我一直在等待有人最终编写它。看完他的演讲后,布莱恩对我说:“是时候停止等待了,开始自己写吧。”
因此,让我试着给出一个这样的数据库的概述,并检查一下它的价值。
我想要一个数据库,它允许我创建可以同步数据的分散的客户端应用程序。
让我们逐一复习一下我所说的每一个方面的意思。
我认为服务器端数据库环境是多样化和成熟的,可以满足各种需求(尽管我最终大部分时间都选择SQLite),我更喜欢的是一个嵌入到客户端应用程序本身的数据库,可以是桌面应用程序、浏览器应用程序、移动应用程序等等。
这样的数据库的目的不是为了在失去连接的情况下保留一些本地数据缓存:我们已经有了很好的解决方案。它应该作为真理的来源,并允许应用程序在其上工作。
SQLite就是一个很好的例子:它是一个功能非常强大的关系数据库,几乎可以在任何地方运行。我错过了SQLite没有提供的在浏览器上运行它的能力:即使您可以将其编译成WebAssembly,它也假定必须模拟一个POSIX文件系统。
PouchDB是另一个很好的例子:它是针对JavaScript环境(主要是浏览器和Node.js)的CouchDB的完全重新实现。然而,我想要一个可以部署在任何地方的工具,而不是将它的应用程序限制在已经有JavaScript运行时环境的地方,或者强迫开发人员将JavaScript运行时环境与他们的应用程序捆绑在一起。对于GTK+应用程序、命令行程序、Android应用程序等都是如此。
Mentat是一个有趣的项目,但是它对SQLiteme的依赖使得它继承了SQLite本身的大部分缺点(也继承了它的优点)。
拥有这样的需求会强加一种不同的存储方法:我们必须将有关存储复杂性的知识从存储本身的使用中分离出来,这样模块(比如查询处理)就可以通过API访问存储,而不需要知道它的实现。这允许数据库面向POSIX文件系统存储API和IndexedDB storageAPI,并使其余代码与存储无关。PouchDB就有这样的机制(称为适配器),Datomic也有这样的机制(称为存储服务)。
这将允许数据库适应其嵌入的位置:当以浏览器为目标时,IndexedDB存储API将提供数据库所需的持久层,类似地,当以POSIX系统(如台式机、移动设备等)为目标时,POSIX文件系统存储API将提供持久层。
但是,嵌入还有一个额外的限制:它需要提供可嵌入的工件,最有可能是一个二进制的库对象,它公开一个与C兼容的FFI,类似于SQLite的做法。捆绑完整的运行时环境是可能的,但并不能使其成为引人注目的嵌入式解决方案。这就排除了大多数语言,给我们留下了C、Rust、Zig和类似的选项,它们可以针对POSIX系统和WebAssembly。
不可变意味着只添加新信息,不会进行任何就地更新,也不会删除任何内容。
拥有一个不可变的数据库会给我们带来持久化数据结构中类似的权衡,比如读取时缺乏协调,缓存总是连贯的,以及更多的空间使用。
DATOMIC就是这样的一个转到数据库的例子:它只会添加信息(数据),并允许您以多种方式查询它们。StuartHalloway称其为“仅累加”,而不是“仅附加”2:
它是仅累加的,而不是仅附加的。所以,大多数人在说他们是在暗示所发生的事情是身体上的东西时,这只是附加的。
此外,通过清理“陈旧”数据,数据库可以是仅附加的,并用新信息覆盖现有信息。我更喜欢采用“只累加”的命名和方式。
Git是另一个例子:新的提交总是添加在以前的数据之上,并且它通过添加提交而不是替换现有的提交来增长。
Git存储库只能在大小上增长,这不仅是一个可以接受的条件,也是使用它的原因之一。
所有这些都意味着数据不会发生就地更新,与写入磁盘的速度相比,数据库更关心存储数据的紧凑程度和效率。嵌入后,存储限制要么是a)设备有多少存储空间,要么是b)应用程序要消耗多少存储空间。因此,尽管理论上数据库可以操作数百TB,但浏览器页面或移动应用程序不会访问这么大的存储空间。SQLite甚至说它支持大约280TB的数据,但这些限制未经测试。
保留所有内容的好处是您可以拥有数据的历史视图,这是非常强大的。这也意味着应用程序应该在不相关时将其关闭3。
然后,您需要一个冲突解决策略来处理不同应用程序实例不一致的所有情况。这些应用程序实例可以是同一应用程序的桌面和浏览器版本,也可以是不同设备中的同一移动应用程序。
三向合并似乎是最好的方法,在此基础上,您可以添加特定于应用程序的冲突解决功能,例如:
当本地数据库成为应用程序的真实来源时,它必须提供一致性保证,使应用程序能够依赖它。
数据库应该支持应用程序以任何它想要的方式分割数据。
因为我找不到任何符合这些要求的数据库,所以我最终不得不自己去做了。
我可能需要几年时间才能做到这一点,使其在POSIX和IndexedDB之间可移植可能是最大的挑战。我有几本关于数据库的书要开始读。
↩时间12:28在DATMIC的信息模型上播放“DATMIC之日(下)”视频。(完)。
你对这篇课文有何评论?直接给我发电子邮件,或者在我的公共收件箱中开始讨论,或者查看现有的讨论。