SQLite 中的文件格式更改

SQLite 数据库的底层文件格式不会以不兼容的方式改变。实际上有数千亿,也许数万亿个 SQLite 数据库文件在流通,SQLite 开发人员承诺在未来几十年内支持这些文件。

本文档描述了 2004 年之前在 SQLite 中发生的不兼容性。自 2004 年以来,SQLite 得到了增强,因此较旧版本的 SQLite 库无法读取较新的数据库文件。但是最新版本的 SQLite 库应该能够毫无问题地读写任何旧的 SQLite 数据库文件。

换句话说,自 2004 年以来,所有 SQLite 版本都向后兼容,但不一定向前兼容。

下表总结了自 1.0.0 版本以来发生的 SQLite 文件格式变化:

版本变更 日期 文件格式变更说明
1.0.32 至 2.0.0 2001-09-20 SQLite 的 1.0.X 版使用 GDBM 库作为其到磁盘的后端接口。从 2.0.0 版开始,GDBM 被专门为 SQLite 编写的自定义 B-Tree 库所取代。新的 B-Tree 后端速度是 GDBM 的两倍,支持原子提交和回滚,并将整个数据库存储在单个磁盘文件中,而不是像 GDBM 那样为每个表使用单独的文件。这两种文件格式甚至一点都不相似。
2.0.8 至 2.1.0 2001-10-12 使用相同的基本 B-Tree 格式,但更改了索引键的详细信息以提供更好的查询优化机会。为了将行的最大大小从 64KB 增加到 24MB,还更改了一些标头。

此更改是上述版本号规则的一个例外,因为它既不向前也不向后兼容。需要完全重新加载数据库。这是唯一的例外。

2.1.7 至 2.2.0 2001-12-21 从 2.2.0 版本开始,SQLite 不再为 INTEGER PRIMARY KEY 列建立索引。相反,它使用该列作为主表的实际 B-Tree 键。

2.2.0 版及更高版本的库将自动检测何时读取 2.1.x 数据库并将禁用新的 INTEGER PRIMARY KEY 功能。换句话说,版本 2.2.x 向后兼容版本 2.1.x。但是版本 2.1.x 不向前兼容版本 2.2.x。如果您尝试使用较旧的 2.1.x 库打开 2.2.x 数据库并且该数据库包含一个 INTEGER PRIMARY KEY,您可能会得到一个核心转储。如果数据库模式不包含任何 INTEGER PRIMARY KEY,则 2.1.x 版和 2.2.x 版数据库文件将完全相同并且可以完全互换。

2.2.5 至 2.3.0 2002-01-30 从版本 2.3.0 开始,SQLite 在存储在 SQLITE_MASTER 表中的 CREATE TABLE 和 CREATE INDEX 语句中支持一些附加语法(“ON CONFLICT”子句)。如果您创建包含此新语法的数据库,然后尝试使用 2.2.5 或更早版本读取该数据库,解析器将无法理解新语法,您将收到错误消息。否则,2.2.x 和 2.3.x 的数据库可以互换。
2.3.3 至 2.4.0 2002-03-10 从 2.4.0 版开始,SQLite 添加了对视图的支持。有关视图的信息存储在 SQLITE_MASTER 表中。如果旧版本的 SQLite 试图读取包含 SQLITE_MASTER 表中 VIEW 信息的数据库,解析器将无法理解新语法并且初始化将失败。此外,SQLite 跟踪数据库文件中未使用的磁盘块的方式也略有变化。如果旧版本的 SQLite 试图写入以前由 2.4.0 或更高版本写入的数据库,则它可能会泄漏磁盘块。
2.4.12 至 2.5.0 2002-06-17 从 2.5.0 版本开始,SQLite 添加了对触发器的支持。有关触发器的信息存储在 SQLITE_MASTER 表中。如果旧版本的 SQLite 试图读取 SQLITE_MASTER 表中包含 CREATE TRIGGER 的数据库,解析器将无法理解新语法并且初始化将失败。
2.5.6 至 2.6.0 2002-07-17 索引布局中的设计缺陷需要更改文件格式才能更正。此更改出现在版本 2.6.0 中。

如果您使用 2.6.0 或更高版本的库打开最初由 2.5.6 或更早版本创建的数据库文件,将自动尝试将数据库重建为新格式。对于大型数据库,这可能需要一些时间。(在 Unix 下每兆字节数据库允许 1 或 2 秒 - 在 Windows 下更长。)这种格式转换是不可逆的。强烈建议您在使用 2.6.0 或更高版本的库打开旧数据库文件之前备份它们,以防格式转换逻辑出错

2.6.0 或更高版本的库无法打开 2.5.6 或更早版本的只读数据库文件,因为只读文件无法升级到新格式。

2.6.3 至 2.7.0 2002-08-13

从 2.7.0 版开始,SQLite 支持两种不同的数据类型:文本和数字。文本数据按 memcmp() 顺序排序。如果数字数据看起来像数字,则按数字顺序排序,否则按 memcmp() 顺序排序。

当 SQLite 2.7.0 或更高版本打开 2.6.3 或更早版本的数据库时,它假定所有表的所有列都具有“数字”类型。对于 2.7.0 及更高版本的数据库,如果列的数据类型字符串包含子字符串“char”或“clob”或“blob”或“text”,则列的类型为“text”。否则它们是“数字”类型。

因为“文本”列与数字列的排序顺序不同,所以“文本”列上的索引对于版本 2.7.0 和更高版本的数据库以不同的顺序出现。因此,SQLite 2.6.3 及更早版本将无法读取 2.7.0 或更高版本的数据库。但 SQLite 2.7.0 及更高版本将读取更早的数据库。

2.7.6 至 2.8.0 2003-02-14

版本 2.8.0 对回滚日志文件的格式进行了更改。主数据库文件格式不变。2.7.6 及更早版本可以读写 2.8.0 数据库,反之亦然。版本 2.8.0 可以回滚由版本 2.7.6 和更早版本启动的事务。但是2.7.6及之前版本不能回滚2.8.0及以后版本启动的事务。

唯一一次这会成为问题是当您有一个使用 2.8.0 或更高版本的程序因未完成的事务而崩溃,然后您尝试使用 2.7.6 或更早版本检查数据库。2.7.6 代码将无法读取日志文件,因此无法回滚未完成的事务来恢复数据库。

2.8.14 至 3.0.0 2004-06-18

3.0.0 版是 SQLite 的一次重大升级,它包含对 UTF-16、BLOB 和更紧凑编码的支持,从而使数据库文件通常缩小 25% 到 50%。新文件格式非常不同,与版本 2 文件格式完全不兼容。