SQLite 不为人知的故事

2022年8月16日 286点热度 0人点赞 0条评论

《形形色色的数据库》里,向大家提到过 SQLite 小型嵌入式数据库。它是现在人们使用最多的数据库。在浏览器、手机、汽车、ATM机、飞机……各类设备上都有广泛部署。
SQLite 数据库以一个独立的文件存在,不占用操作系统进程。其它关系型数据库,一般是客户端/服务端大型的技术架构,需要安装、启动服务,占用端口。
受益于整个数据库(包括结构定义、表、索引、数据本身)都在一个文件里,SQLite 很容易跨平台使用。麻雀虽小,五脏俱全,关系型数据库的关键特性(如事务),它都能良好支持。性能也很出色,同时它做到了 100% 的测试覆盖,稳定性和安全都有保障。
正是因为以上特点,它成为了移动设备中数据库的第一选择。

2022 年 7 月初,SQLite 的作者 Richard 参与了一期播客节目,讲述了 SQLite 是如何诞生和发展的。
这篇文章整理了博客节目的关键内容。看完后也许能理解,为什么我们没有这样的程序员,为什么我们做不出世界级的基础设施软件。

SQLite 如何诞生

Richard 早先是个外包程序员,所在团队承接了一个军工项目,开发军方战舰上使用的故障管理系统。
该系统使用了 IBM 的 Informix 数据库,可能是服务器方面的原因,数据库一直不是很稳定。只要数据库服务器挂掉,他们开发的系统就会无法正常运行,弹出提示:“无法连接到数据库”。
甲方大佬看到他们的系统产生了错误提示,也不关心具体背后是谁出了错,就把锅扣在了他们身上。
国内外的外包程序员都是伤不起啊,遇到这种情况,一般程序员都是选择换个环境,或者祈祷分到一个好侍侯的甲方项目中。
战舰故障管理系统的使用频率比较高,外包团队又没有数据库服务器的管控运维权限,怎么解决无法连接数据库的问题呢?
Richard 有了一个灵感:“为什么一定要从数据库引擎中取数据,而不能从硬盘中直接读?”
只要操作系统和硬盘没问题,程序能正常运行,就可以读取本地文件,而不必依赖数据库引擎的服务正常。
“功能越多,越不稳定。”我记得八十年代的时候,父母看一些工业产品时,就经常说这句话。奥卡姆剃刀原则“若无必要,勿增实体”在产品设计中是一条重要的指导原则:1、系统越简单,故障率越低;2、用户认知负担降低;3、带来了简洁的使用体验;4、成本降低。
他们在市面上找了许久,发现没有现成的 SQL 数据库引擎可以做到这一点。团队其它成员就鼓励 Richard 写一个出来。
查了一下资料,同类型数据库 Microsoft Access 1.1 在 1992 年就有了,但应该不能在 Linux 平台下使用。SQLite 是 2000 年才开始开发。
Richard 并没有立即开始,直到因为政策原因外包项目合同中断,Richard 失业了数月,才正式动手编写 SQLite。
可能也有拖延症。
当时是 2000 年,还没有维基百科,上网也是电话拨号,美国只有 1% 的家庭拥有 ADSL 宽带网络。
在 Google 上几乎搜不到构建一个本地文件型数据库的有用信息。
Richard 有开发编译器的经验,于是他把这项经验应用到了开发数据库上。
他把每条 SQL 语句(DDL 创建库表结构和 DML 读写操作数据,都是SQL语句)看作是一个程序,只要这个程序能执行成功,那就达到了最初的目的。
于是,问题变成了把程序编译成某种可执行代码,这就用到了他开发编译器的经验,他写了一个字节码引擎来运行一个查询。
SQLite 核心原理是通过一个编译器将 SQL 翻译成字节码,就这样,SQLite 诞生了。
面对生活中、工作中的痛苦时,我们习惯咬牙忍受,常常采取迁就、回避、的态度,长期下去就变得麻木,这是我们不擅长创新的重要原因之一。

SQLite 如何发展壮大

SQLite 被发布到网上。
Richard 很激动地宣布,他在掌上电脑中跑起一个 SQL 数据库。就是下面这台 Palm Pilot 掌上电脑。
图片
Palm Pilot 掌上电脑
作为 80 后,我对掌上电脑印象深刻,曾梦寐以求想拥有一台,结果是拥有了电子词典。
SQLite 一发布就受到很多人关注,这让 Richard 大受鼓舞,不断迭代升级他的产品。
一两年后的某天,他接到了摩托罗拉公司的电话。摩托罗拉正在开发新版本的手机操作系统,有些功能适合用 SQLite,希望能把 SQLite 内嵌进去,并让 Richard 提供技术支持。
Richard 很激动,但对方问起价格时,他一时不知道该怎么答复。
放下电话,Richard 对产品定价仍没有头绪,他没有想过系统化地运作这个项目,也没有可参考的定价方式。
最后几乎是一拍脑袋,定了 8 万美金,当时折算人民币近 60 万。这就是 SQLite 的第一笔收入。Richard 又找了三个人,和他一起完成了这个项目。
2001、2002 年时,摩托罗拉公司的体量十分庞大,比今天国内的小米、华为等公司大很多。这样一个巨头,肯为一个小软件的作者致电并付费,这样的商业环境,对知识产权的重视,真是令人羡慕。可以想象,现在某些公司遇到这样的情况时,还是会给某部门的程序员下达一个任务:加班两周抄一个出来!
继摩托罗拉之后,又一笔生意找上门来,这次是 AOL(今天的美国在线,曾被 44 亿美元收购,又和雅虎打包一起 50 亿美元卖出)。
AOL 当时有邮寄 CD 的业务,他们想在CD中使用 SQLite 数据库的一些增强功能,为此 AOL 每月向 Richard 支付 10 美元。
不知道是不是每张CD 每月支付10 美元,原文没有说。如果是,这一下子就可以实现财富自由了。所以,完成从一个消费方到生产方的身份转换很重要,生产一个有价值的东西(无论是实体的,还是虚拟的),即使可能是小众的产品,也会产生回报。
紧接着,Symbian OS(塞班手机操作系统,后被诺基亚收购)和诺基亚分别和 Richard 签订了合同,这时 Richard 已经需要频繁飞往国外和这些公司谈合作了。
Symbian 在数据库选型期间,一共测试了 10 款产品,其中 2 款开源,7 款商业产品,还有 1 款就是 SQLite。考虑到商业公司相对更有保障,Symbian 给了商业产品多次优化调整的机会,但最终还是 SQLite 胜出。
成立 SQLite 联盟是里程碑事件,联盟目的是为项目提供更多的资金并让更多的协作者参与维护项目,以保证产品可以长期使用。
像一直等着生意上门一样,成立联盟这件事也不是 Richard 主动推动的,而是由管理 Mozilla 基金会的一位女士一手推动促成。Mozilla、Symbian 和 Adobe 三家大公司成为了联盟的创始成员,他们和其它联盟成员共同赞助 SQLite 发展,而产品的决策权仍在 Richard 手中。
有人说 Richard 做了个错误的决定,但事实证明,后面 SQLite 一直发展的很好。
再后来,2005年的时候,Google 联系了 Richard,向他展示了安卓的原型机。他们又在安卓系统上展开了 SQLite 的合作。这正是智能手机诞生的前夜。
Richard 回忆当时的一幕,他们正在使用 SQLite 调试适配手机上的一些应用,这时来了电话,电话被接通——Richard 意识到,这不再仅仅是手机。智能手机的时代要来临了,而摩托罗拉、Symbian 、诺基亚都没有意识到这点。
Richard 和 Google 签署了保密协议。他不能告诉摩托罗拉们,时代要变了。

SQLite 如何保持稳定

Richard 一度对 SQLite 很自信,他认为SQLite 绝对没有严重的错误,事实上好像也是如此。但安卓证明了这不是真的。当 SQLite 随着安卓系统在数百万台设备上部署时,出现了很多错误。
Richard 学习了航空电子设备制造商的一些经验。在安全至关重要的航空产品的质量标准里,有一套 DO-178B 标准。其中一个关键是要求对产品 100% 的测试覆盖率。
Richard 把这个理念应用到了 SQLite 的开发中,他决定编写测试代码以使 SQLite 达到 100% 的质量。
在软件开发中,达到 90% 或 95% 的测试覆盖率是比较容易的。想达到最后 5% 非常非常困难,他们花了大概一年的时间才达到了100%的测试覆盖率,测试用例惊人地达到了10万个,在多种芯片、多种操作系统中完整测试一遍将会产生 10 亿次测试。这件事做完,就再也没有收到来自安卓的错误报告。
这一举措发挥了重要的作用,在接下来的八九年里,SQLite 真的没有发生任何错误。
第三方测试平台对各类数据库做了极限测试,除了 SQLite,只有 PostgreSQL 能达到同样的水平。
PostgreSQL 要做到这一点,比 SQLite 更不容易。因为PostgreSQL 正是文章一开始提到的客户端/服务器复杂架构,而且是原生分布式数据库,分布式会引入更多错误的机会。而 SQLite 只有一个文件。
其它数据库,包括 Oracle、DB2 等,都会在这项极限测试中崩溃。

伟大程序员的一些独特理念

毫无疑问,Richard 是一个伟大的程序员,他发明的 SQLite 嵌入式数据库是众多移动设备、移动应用能高效稳定运行的基础设施之一。难以想象,如果有一天 SQLite 不能用了,我们的生活将会受到多么大的影响。
他在播客中也提到了一些理念。

从第一性原理出发

Richard 准备开发 SQLite 时,和普通人一样,先去互联网上搜索了很多资料。遗憾的幸运的是,他什么都没有搜到。
很多计算机核心技术理论,都来自于麻省理工大学、哈佛大学或伯克利大学,他也没有办法从这些大学里得到帮助。
他只能动脑子用原创的方法来实现新的数据库。
奇怪的是,等回过头来再看 PostgreSQL 使用的火山模型和 SQLite 曾经的字节码模型,二者在顶层设计时有着不同的路线,但在同一技术领域中,两条独立的发展路线都给出了同样稳定的结果。
Richard 认为这是运用第一性原理后的结果。

“一点就透”

Richard 讲了一件很有意思的事情。有一次在德国召开一个 PHP 的会议,邀请 Richard 做演讲嘉宾(PHP 已经将 SQLite 集成了进去),另外还有一位演讲嘉宾是 MySQL 早期开发者。
这位开发者讲了 MySQL 一个关键性能实现方案。Richard 听了心想,“哇,这真是一个聪明的主意。” 于是就在回去的飞机上,打开电脑为 SQLite 实现了这一特性。
真正的领域专家,有时候只需要一点点启发,就能立即明白其中的关键,并把它实现出来。如果你怎么都没办法向别人说清楚一件事的时候,不要怀疑自己的能力,要怀疑对方的知识储备。

没有依赖的自由

庄子说御风而行的列子“此虽免乎行,犹有所待者也。”
Richard 可能没读过庄子,但他似乎更明白不依赖于他人的自由之可贵。
SQLite 除了依赖 C 编译器和 libc 中的一些东西,没有依赖任何“轮子”,需要到的“轮子”,全部都自己发明了一遍。
Richard 说,假如当时选择使用 Berkeley DB 作为 SQLite 第二版的存储引擎, 起初它是开源的,但后来就被卖给了Oracle,变成了双源模式,不付许可费就看不到源代码,那肯定会出问题。
SQLite 中的解析器也是作者多年前自己编写的,没有使用现成的 Yak 或 Bison 等产品。
当 SQLite 需要版本控制的时候,同样没有使用 CVS 或Linux之父开发的 Git ,而是自己开发了一套 Fossil 版本控制软件。
Richard 甚至计划自己开发一个邮件服务去替换 Gmail,他不希望邮件内容被厂商记录和控制。
自己做,不依赖第三方,就能掌握自己的命运,就会拥有更多的自由。

SQLite 作者的一点建议

“构建一个没有服务器的数据库引擎,直接与硬盘文件交互,忽略数据类型,这在当时绝对是一个疯狂的想法。”
“如果去问专家,他们都会说:‘那是不可能的,永远也行不通。这个想法太愚蠢了。’”
“幸运的是,我不认识任何专家,我就去做了,事情就做成了。我认为,不要过多地听专家的话,做自己认为有意义的事,就有希望能做成。”
83550SQLite 不为人知的故事

这个人很懒,什么都没留下

文章评论