Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

报告 010 · SQLite、本地文件与维护边界

文档索引 · 总体设计 · 存储方案 · 研究状态

日期:2026-09-19。设计阶段的独立机制实验,非产品实现、模型实验或掉电测试。

目录:条件 · 结果 · 决策 · 资料与边界 · 复现。

1. 条件与执行

本实验在单机、SQLite 与本地文件条件下,预登记 22 例,编写独立脚本并执行一次。未在查看结果后修订条件或重跑。

环境为 Linux 6.18.52、XFS、Python 3.14.7、SQLite 3.53.4;实验临时目录位于仓库所在文件系统,未使用 /tmp 的 tmpfs。SQLite 使用 WAL、FULL;自动 checkpoint 关闭、busy timeout 为 0,以确定观察竞争和 WAL 行为。这些是实验参数,不能直接当产品配置。

夹具包含主体计数、输入消费、唯一提交键、文件引用及 queued 操作。固定文件 65,536 字节,经临时写、文件同步、排他 hard link 发布、目录同步,再提交 SQLite 引用与业务状态。子进程只模拟宿主在不同阶段终止,线程模拟进程内发布、读取与维护,并不重新引入多进程产品架构。

22 例符合预登记判据,174 项显式检查通过,13 个子进程、8 次有意 SIGKILL,失败检查和异常兜底强杀均为 0。 其中包含预期会失败的错误设计对照;“通过”表示观察符合预登记,不表示所有被测方案均正确。检查数不是独立样本数或故障概率。原始 JSON 保存条件、屏障、退出码、SQL 终态、文件摘要与错误码。

本实验没有调用模型、推进 go-mini、执行现实工具动作或测量真实业务吞吐;它覆盖 S1 的存储与维护子集,没有完成整个认知工作闭环。

2. 对照结果

场景实际观察设计含义
L1 同一锁对象活跃持锁者使第二实例拒绝;SIGKILL 后锁路径仍存在,第三实例取得同一 inode 的锁依赖实际文件锁状态,不按文件是否存在判定存活
L2 删除锁路径原进程活跃时重建路径,两个进程分别锁住不同 inode不能通过删除所谓残留锁文件解锁;锁对象在正常启停间保持稳定
F1/F2 临时写/文件同步后终止无已提交状态、待办或引用;保留临时残留文件存在不代表业务提交
F3/F4 最终文件发布/目录同步后终止文件可见但仍无业务提交,形成孤立文件文件先发布允许留下孤立内容,不应留下已提交悬空引用
F5 COMMIT 前终止计数、输入消费、引用、待办、回执全部回滚必要业务记录共同提交;仅执行过 SQL 不算成功
F6 COMMIT 后丢确认原回执与 queued 待办恢复,文件摘要正确;重送不新增意图查询原提交键解决确认丢失
F1~F5 后续进展恢复后原请求均能完成,最终计数和待办各 1并非用永久拒绝所有工作获得正确性
F7 引用先提交状态和待办已保存,但文件不存在,悬空引用 1否决先提交引用、之后再生成文件的顺序
F8 重送/冲突相同内容返回原回执,同键不同内容拒绝,计数和待办各 1幂等键必须绑定内容
F9/F10 注入 EIO/ENOSPC错误显式返回,业务计数、引用与待办均未提交文件 I/O 错误不能降级成成功;未真实填满磁盘或破坏设备
B1 只复制 db 与 backup API原数据为 9,只复制 db 读到 0,backup API 副本读到 9活跃 WAL 的最新提交可能不在主 db 文件内
B2 快照与回收竞争数据库快照保留引用,原库删除并回收后,复制文件得到 ENOENTSQLite 快照不自动保留外部文件
B3 受控完整备份维护期间拒绝新修改;副本与文件清单校验成功,恢复的计数/输入/待办/回执一致先固定维护边界,再备份数据库和所引用文件;恢复不自动执行待办
B4 复制失败/伪完成标记注入复制错误后无完成标记;伪造标记仍因文件缺失被拒标记是校验入口,不是完整性的充分证据
G1 只查数据库做回收发布者暂停在文件已发布、引用待提交处,GC 删除文件,恢复发布后产生悬空引用 1回收必须覆盖在途发布责任
G2 排空完整发布事务维护关闭新准入并等待发布者完成引用事务,再删除孤立文件;正式引用有效发布阶段从开始准备一直延续到引用事务终结
G3 排空文件读者新读者拒绝,GC 等待旧读者结束后才删除维护边界也覆盖本地文件读取生命周期
T1 旧快照升级得到 SQLITE_BUSY_SNAPSHOT(517);旧事务仍读到旧值;回滚重新读取后可提交不能在旧快照上无限重试写入
T2 两个写者第二个 BEGIN IMMEDIATE 得到 SQLITE_BUSY(5);前者结束后第二个能推进写入通路应串行调度,有界处理竞争
T3 长读与 checkpoint32 次更新后 checkpoint 为 [0,64,0],WAL 263,712 字节;读事务结束后为 [0,0,0],WAL 截断至 0不跨模型等待持有读事务;观察 WAL 增长及未结束读者

F3 的文件在 SIGKILL 后可见不证明目录同步可省略:内核和磁盘环境未重启。T3 的页数、文件大小和 32 次更新是本实验夹具参数,不是吞吐或容量阈值。

3. 据此明确的方案

  1. 固定锁文件对象。 Linux 单实例候选使用稳定路径上的非阻塞独占 flock;正常退出关闭持有描述符,不 unlink 锁文件。目录锁不是对恶意写入或遗留外部工作的隔离保证。
  2. 文件先发布,引用后提交。 文件就绪后以短 SQLite 事务共同保存必要状态和待办;提交后才确认,确认丢失查原键。文件失败不提交引用,孤立文件由维护处理。
  3. 维护统一关闭准入再排空。 发布者持有维护资格直至引用事务成功或明确放弃;清理等待相关读者结束。备份、删除与回收共用此边界,不能只锁文件 rename 或只查数据库引用。
  4. 备份必须校验闭包。 使用 backup API,固定其引用的文件集合,复制并校验数据库和文件后发布完成清单;恢复重新检查清单及内容,不能只看一个标记。
  5. 明确 SQLite 事务生命周期。 上下文读取结束就释放快照;计算完成后以 BEGIN IMMEDIATE 开始短写事务并复核条件。BUSY_SNAPSHOT 需回滚重读;普通写入竞争有界重试,仍用原业务键。不从本实验 busy=0 或关闭自动 checkpoint 推出产品调优参数。

Go 驱动、跨平台发布方式、吞吐曲线、真实磁盘错误与备份停顿仍未确定。

4. 一手资料及未验证边界

以下资料能支持契约或排除错误保证,不能证明本项目端到端可靠性。

未完全实测的命题一手依据设计推论与剩余验证
进程终止后锁是否一定释放Linux flock锁关联打开的文件描述,fork/dup 的副本会影响释放;避免继承锁描述符。L1 未测试完整子进程继承树或恶意忽略 advisory lock
fsync/发布能否保证掉电后文件可恢复Linux fsync、link、SQLite atomic commit文件、目录及存储刷新契约均重要;本实验未掉电,也未验证新建数据/备份目录的全部祖先项持久化
长读快照能否等待后继续升级SQLite isolation、事务文档结束旧快照并重建写事务;T1/T2 支持局部行为,Go 驱动中的错误与事务状态处理仍待测
WAL 和备份文件能否任意复制或移动SQLite WAL、backup API、文件损坏原因不单独操作活跃数据库文件或其日志;完整备份须包括外部内容,副本恢复步骤另行校验

维护入口依赖所有相关读写遵守;本实验只实现并测试夹具中的入口。没有验证直接绕开入口的库、符号链接/路径攻击、所有并发次序、长时间饥饿或维护等待超时后的降级。临时文件残留被记录,尚未实现完整删除、权限撤销与备份保留期流程。

现有记录只提供完整备份与指定故障点的行为,不能保证旧备份之后发生的外部动作可判定;原有 unknown 处理继续适用。真实认知闭环、Go 驱动与构建依赖、FTS5 中文检索质量、CPU/GPU 干扰仍属后续研究。

运行命令见预登记,输出排他创建,复跑须更换路径。原 E0~E8e 记录未修改。

文件SHA-256
预登记 README.md9c79ab6a8a63a16d770aa146ad1411983780f6ec8a8f024bd6c3c0b5ea129c77
experiment.py039e149ae1c9b1d92fff65e6263628149cfd534372b5cef1000a091c63db5569
local-storage.jsonbe742366fb84ee31c070c6899637bdc09936a2999111fa82af7b6430f6d9bd9a

数据可用性

本报告公开实验条件、汇总统计和失败分析。原始输入、脚本及逐次运行记录未随报告发布,因此不能仅凭本文独立复现实验。