模型交付

Android SQLite WAL 导入:创建一致数据库快照

只讨论活动 SQLite WAL 数据库快照的事务一致性、备份 API 与导入前验证;区别 Room schema migration 和文件路径迁移,不声称 Cove 已提供导出接口。

审核状态: 内容已校验;中文稿供用户审核 · 2026-10-08 · Fact IDs: ANDROID-SQLITE-WAL-SNAPSHOT-2026-10, ANDROID-PRIVACY-01, RAG-01

直接回答

WAL 模式下,活动 SQLite 数据库状态不一定只存在于主数据库文件。已提交的页面更改可能留在 `-wal` 文件,直到 checkpoint;`-shm` 文件供并发访问时使用 WAL index。只复制主文件可能漏掉已提交状态。若在 writer 或 checkpoint 仍运行时逐个复制主文件、WAL 和 SHM,文件也可能来自不同时间。文件都存在并不构成一致快照协议。 优先选择经 SQLite API 读取数据库状态的备份路径,不把文件当作互不关联的 blob。C Online Backup API 调用顺序是 `sqlite3_backup_init()`、一次或多次 `sqlite3_backup_step()`,最后 `sqlite3_backup_finish()`。每次 step 只在读取期间持有 source shared lock,不会全程锁住源库;若其他连接在两次 step 间修改源库,下一个 step 会自动重启备份;若通过同一 source connection 写入,则这些修改会同步进入目标。按准确 API 处理 `SQLITE_DONE`、可重试的 `SQLITE_BUSY`/`SQLITE_LOCKED`、致命错误与 finish 结果。该引擎能力不代表 Android `SQLiteDatabase` wrapper 或 Room 一定暴露 C API。`VACUUM INTO` 也能一致复制:源文件保持不变,目标保存逻辑内容,但文件会被压实,物理布局可不同。 不要把“transaction began”或用户点击导出当成精确快照时刻。`BEGIN DEFERRED` 语句只关闭自动提交;数据库首次被访问时事务才真正开始。若第一条访问是 SELECT,读事务此时建立历史视图,并在结束前保持稳定。增量 Online Backup 的源变更合同不同:外部连接在 step 之间写入,下次 step 会重启备份;使用同一 source connection 写入时,变更会同步进入目标。记录 source connection、API 路径、step 结果、重启/重试与完成状态;不可推断超出 API 和观测的逻辑时刻。 SQLite snapshot object 与备份文件不是同一种产物。Snapshot API 记录 WAL 模式数据库的历史状态,由满足条件的连接读取;它依赖 SQLite build 支持(例如 `SQLITE_ENABLE_SNAPSHOT`)和相应连接流程。它本身不是可移植数据库备份文件。不能持久化一个类似指针的 snapshot object,就声称进程死亡或换设备后可以重新打开。设计前检查编译选项与运行时支持。 生产源数据库的所有权仍归数据库 owner。只需要读取快照的消费者不能为了方便执行 checkpoint、截断 WAL、切换 journal mode 或重写用户数据库。若所选 API 需要稳定连接或 backup 操作,应由数据库所有者协调并遵循其合同。不要分别复制 sidecar、删除 `-wal`/`-shm`、未经授权强制 checkpoint,或在文档化机制之外阻塞 writer。生成的副本属于 app 自有输出,需有单独的访问、保留和删除策略。 一致快照仍需常规数据库验证。通过目标 SQLite driver 打开目标副本;尽可能只读打开;检查 `user_version` 和所需 schema object;运行所选运行时支持的完整性检查。验证与迁移分开:有效的旧 schema 可能需要计划迁移;无效或截断文件不能通过静默执行 schema change 来“修好”。Room migration 测试会从历史导出的 schema 验证 app 版本迁移路径,并不能证明活动 WAL 文件副本具备事务一致性。 导入现有应用数据库是后续的独立步骤。先定义记录是合并、替换还是供用户审核;修改用户数据前检查身份冲突、foreign key、加密密钥是否可用及内容所有权。先写入独立 candidate,检查数量和关键关系,再由 app 的数据库 owner 提交。导入失败应保持现有数据库可用且源副本不变。得到一个文件快照并不表示授权导入内容或适配另一个 Room schema。 用实际 Android driver 和备份路径测试:快照期间 writer 提交已知行、reader 持有稳定事务、WAL 中有尚未 checkpoint 的内容、取消、磁盘满、进程中断,以及损坏/错误 schema 输入。检查完成副本中的表内容和事务标记是否构成逻辑一致集合,不要只看文件大小或时间戳。记录备份是否重启及最后接受的结果。合成数据库不放真实笔记、prompt、转录、健康信息或模型内容。 不要把手工三文件复制当基线,再凭一次成功运行推断无竞争协议。`VACUUM INTO` 输出不能称为与源字节完全一致;它可以更改物理布局,同时按其合同保留数据库内容。本文仅讨论快照/导入方法,不表示 Cove 导出 Room 数据库、某 Android driver 暴露原生 backup API,或任何设备已通过该测试。

WAL 活动时的数据库导出漏掉已提交行

本地笔记数据库启用 WAL。后台 writer 提交一条笔记,另一个组件先复制主数据库文件再复制 sidecar。目录里看起来有三份合理文件,但没有组件证明它们来自同一个一致数据库状态。

决策

停止逐文件复制。让数据库 owner 使用实际 SQLite driver 支持的备份路径,并在任何导入或迁移前校验独立目标副本。

预期结果

接受的快照依照所选 API 合同表示一个 SQLite 一致视图;活动源仍归其 owner 管理,现有读者可以继续使用。

需要收集的证据

只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:

  • ANDROID-SQLITE-WAL-SNAPSHOT-2026-10:WAL 状态分布于主文件和 sidecar;Online Backup 每次 step 分别读取源库,外部写入会使后续 step 重启备份;`VACUUM INTO` 输出保留逻辑内容但文件布局可不同。
  • ANDROID-PRIVACY-01:数据库文件访问、存储和用户控制仍由应用负责。
  • RAG-01:本地 RAG 的 ingestion、index storage、retrieval 和 generation 阶段须分别验证;数据库快照只涉及其中的数据供给边界。

收到完整字节流还不够;最终落盘、完整性、运行时加载和恢复路径也必须验证。

实施流程

  1. 确认 journal mode、driver 和源所有者. 记录准确的 Android SQLite/Room driver、运行时 SQLite 版本及 build flags、journal mode、源连接 owner 和目标位置。不能从文件格式或 Room migration interface 推断 C API 可用。
  2. 选择受支持的一致复制机制. 选用实际运行时暴露的 backup API、受支持 wrapper,或按文档使用 `VACUUM INTO`。确认锁、增量步骤、源变更、返回码、取消和目标替换语义。若用 `BEGIN DEFERRED`,记录首次实际数据库访问;BEGIN 本身尚未建立 read snapshot。
  3. 通过数据库 owner 执行操作. 由拥有数据库连接的组件协调快照。不要独立复制主库/WAL/SHM、删除 sidecar、切换 journal mode,或为简化消费端而强制 checkpoint。
  4. 校验独立目标副本. 通过目标 driver 打开完成的副本,验证 schema/version 和事务标记,并运行受支持的 integrity check。区分需要迁移的有效旧 schema 与损坏或不完整字节。
  5. 暂存导入并测试并发结果. 候选审核期间保持原源和当前 app 数据库不变。测试备份期间写入、稳定 reader transaction、restart/retry、取消、磁盘满和进程中断;只发布范围明确的逻辑一致性证据。

让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。

验收标准

  • 记录准确 WAL mode、SQLite 版本/build feature、Android driver、源 owner 和受支持备份 API;不假设 Room 暴露 C API。
  • 活动状态下绝不把主文件、`-wal` 和 `-shm` 分开复制作为快照,也不把临时 snapshot object 当可移植备份。
  • DEFERRED 读视图从首次实际数据库访问开始,而非 BEGIN 语句;备份声明遵循准确的源连接变更/重启合同和观察结果。
  • 只读快照消费者未经明确 owner 操作授权,不 checkpoint、截断、切换 journal mode 或重写源库。
  • 快照校验、Room schema migration、应用数据合并和用户授权彼此独立;导入失败时当前数据库仍可用。

决策对照表

维度选择或证据解读方式
只复制主数据库文件不能作为活动 WAL 快照方法。已提交页面可能仍在 WAL 中,主文件副本会漏掉这些内容。
独立复制主文件、WAL 和 SHM仍有连接可写或 checkpoint 时避免。分开的副本可能来自不同瞬间,不能证明它们具有共同事务边界。
SQLite Online Backup API经支持的 driver/wrapper 调用并处理源变更合同。通过 SQLite API 创建目标数据库;Android wrapper 可用性和具体操作观察须单独核验。
`VACUUM INTO`仅当运行时支持且其复制行为适合时使用。创建一致的数据库副本但物理布局可能变化,不是逐字节拷贝。
Room migration有效数据库就绪后执行版本化 schema 转换。负责 schema/data 版本变换,不会单独为活动 WAL 数据库创建一致快照。

需要避免的失败模式

  • WAL 活跃时只复制主数据库文件,遗漏尚未 checkpoint 的已提交页面。
  • 分开复制主文件、`-wal` 和 `-shm`,然后把文件夹称为同一事务快照。
  • 把 SQLite C backup API 当作 Room/Android `SQLiteDatabase` 必然暴露的接口。
  • 把 snapshot object 当成可跨进程/设备恢复的备份文件,或未经所有者授权主动 checkpoint 源库。

还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。

最小复现记录

层级记录内容
设备厂商、型号、芯片、内存档位、操作系统版本
软件应用版本和 Git 提交号
模型系列、变体、版本、格式、文件长度、摘要、量化方式
运行时名称、版本、请求后端及实际后端证据
工作负载样例版本、输入摘要、提示词摘要、输出策略
结果完成、失败、取消、回退及保护隐私的诊断信息

发布检查表

  • ☐ 主要搜索问题已回答,且没有未经支持的数字。
  • ☐ 所有模型文件和运行时版本均已固定。
  • ☐ 代表性任务和失败处理策略均有说明。
  • ☐ 生命周期、取消、清理和回退均已测试。
  • ☐ 用户内容与网络边界均有说明。
  • ☐ 结论只适用于被记录的配置。
  • ☐ 新增测试结果时链接到原始方法或证据。

来源与相关证据

中文部署与排错专题见。奇连 AI 端侧专题。

常见问题

WAL 活动时能只复制 SQLite 主文件吗?

这可能遗漏仍位于 WAL 中、尚未 checkpoint 的已提交页面。活动 WAL 数据库不能靠只复制主文件获得一致快照。

可以依次复制主文件、`-wal` 和 `-shm` 吗?

writer 或 checkpoint 仍可改变它们时不可以。分开复制可能抓到不同状态。应让实际 driver 使用文档规定的 SQLite backup 机制,并由数据库 owner 协调。

Room 在 Android 上一定提供 SQLite C Online Backup API 吗?

不要这样假定。先识别 resolved driver 和 wrapper API。SQLite C API 文档说明引擎行为,不代表任意 Android/Room 抽象都能调用它。

SQLite snapshot object 等于可导出的备份文件吗?

不等于。Snapshot API 表示特定连接流程和 build 支持下的历史 WAL 状态,不是可移植副本。导出文件应使用真正的备份文件机制,并核验编译期支持。