跳到主要内容
AZ Tools

SQLite 数据库检查器

像 SQLite 自己那样直接从字节读取数据库文件,不经过 SQL 引擎,文件也不会离开你的机器。100 字节的头部给出页大小、文本编码、处于回滚模式还是 WAL 模式、空闲列表上有多少页、应用写入的 user_version 与 application_id,以及最后写入该文件的 SQLite 版本。随后遍历第 1 页上的 sqlite_schema b 树,列出每张表、索引、视图和触发器及其 CREATE 语句,并逐一遍历每张表自己的 b 树直到叶子,因此行数是数出来的而不是估算的。有两点需要先知道:WAL 模式下最新的提交往往还留在 -wal 文件里而不在主文件中,未做检查点的数据库报出的行数会少于应用看到的;WITHOUT ROWID 表把行存放在索引 b 树中,因此其行数显示为未知而不是给出错误的数字。列名、声明类型以及 PRIMARY KEY 和 NOT NULL 标记来自对 CREATE 语句文本的解析,普通结构没问题,遇到少见的 DDL 可能偏差,所以原始语句始终一并显示。包括 SQLCipher 在内的加密数据库会被拒绝而不是读一半,因为它们的头部同样被加密,开头没有那串魔数。行内容有意不显示:这个工具回答文件里有什么、有多大,而不是某条记录写了什么。

使用方法

  1. 把 .sqlite、.db 或 .sqlite3 文件拖到方框里,或点击选择。文件留在浏览器中。
  2. 先看头部:页大小乘以页数就是文件大小,空闲页则是 VACUUM 能归还的空间。
  3. 确认日志模式。若为 WAL,仍在 -wal 中的提交不在此文件里,行数应视为下限。
  4. 浏览表列表,查看行数、列及其声明类型,以及每张表上的索引。
  5. 当解析出的列看起来不对时,展开表下方的 CREATE 语句,以原始 DDL 为准。

常见问题

为什么这里的行数和我的应用不一样?
多半是预写日志的缘故。WAL 模式下 SQLite 把新增和修改的页追加到单独的 -wal 文件,只有在检查点时才合并进主库,因此不带该文件复制出来的数据库是上次检查点时的快照。本工具只读你给的这个文件,所以最近的插入可能缺失。复制前执行 PRAGMA wal_checkpoint(TRUNCATE),或把 -wal 和 -shm 一并带上。另一个原因是 WITHOUT ROWID 表,这种情况会显示为未知而不是给出错误数字。
能打开用 SQLCipher 加密的数据库吗?
不能,而且会明确告诉你,而不是显示一堆无意义的内容。SQLCipher 连头部一起加密,所以加密文件开头不是 "SQLite format 3" 这几个字节,没有密钥就无从解析。这项检查也能区分加密文件和损坏文件:被截断但未加密的数据库头部仍可读,工具会尽量读出内容,并提示页数与文件长度对不上。
空闲页是什么?需要执行 VACUUM 吗?
删除行并不会让 SQLite 文件变小,腾出的页会进入空闲列表,供之后的插入重复使用。也就是说空闲页是文件已经占有、以后还会再用的空间。VACUUM 会不带这些页重建数据库,把空间还给文件系统,在大批删除之后或分发数据库之前值得做,但它要重写整个文件并使已打开的连接失效,因此不是可以随手对线上库执行的操作。
user_version 和 application_id 是什么?
这是头部中 SQLite 自己从不改动、留给应用随意使用的两个 32 位字段。常见做法是把 user_version 当作结构迁移的计数器,应用拿它和代码期望的版本比较并执行中间的迁移;把 application_id 当作标识文件格式的魔数,好让 file(1) 之类的工具区分不同种类的 SQLite 文件。没人设置过时两者都是 0。
结构版本和结构格式有什么区别?
结构版本,SQLite 称为 schema cookie,是每次结构变化就递增的计数器,预编译语句靠比较它来判断是否需要重新编译。结构格式是文件布局的代次,取值 1 到 4,表示该文件可以使用哪些特性:4 允许降序索引和布尔字面量,近二十年的 SQLite 写出的都是 4。
文件会被上传到什么地方吗?
不会。数据库用浏览器自带的 File API 读取,由页面里的 JavaScript 解析;没有任何内容发往服务器,也不存在可以接收它的服务端组件。你可以打开页面后断开网络再检查文件来验证,一切照常工作,因为整个工具已经在页面里了。

相关工具