SQLite3 里 VACUUM 到底在干什么?何时用、怎么配、线上别踩这些坑
SQLite 是单机嵌入式场景最常用的开源引擎之一公有领域源码官方文档与 Fossil 仓库可核对。日常删改多了文件体积不一定掉下来——多半是页级空闲链表变大、碎片增多。这时就要弄清楚VACUUM 在重建文件、回收空间而不是「执行一句 SQL 就变魔术」。下文按CLI 实操 → PRAGMA 策略 → WAL/锁/磁盘 → 清单写版本以SQLite 3.x通用行为为准极端边缘版本差异请以你本机sqlite3 --version与官方文档为准。一、一句话结论VACUUM把当前数据库重写为新物理文件页重新打包扔掉零散空闲页通常显著减小.db文件占用。代价执行期间独占库磁盘上往往需要额外一份量级相近的空闲空间重建过程要写临时副本。替代节奏若只想控制膨胀速度考虑PRAGMA auto_vacuumincremental_vacuum而不是每次手撸全量VACUUM。二、VACUUM适用场景什么时候值得做大批量删除或更新后DELETE/UPDATE让文件「虚胖」监控或ls看到占用远大于真实有效数据。发布前瘦身把一个本地开发库打包给同事 / CI 缓存希望 artifact 变小。迁移式整理配合VACUUM INTO生成紧凑的新库文件见后文再原子替换。不适合高并发持续写入窗口里随手跑全量VACUUM——锁与 I/O 抖动会直接打到业务嵌入式也一样只是并发更低。三、命令行最小步骤可照抄sqlite3 /path/to/app.dbVACUUM;查看前后文件大小Linux / macOSls-lh/path/to/app.db sqlite3 /path/to/app.dbVACUUM;ls-lh/path/to/app.dbWindows PowerShell看大小(Get-Item.\app.db).Length sqlite3.\app.dbVACUUM;(Get-Item.\app.db).Length说明若提示database is locked说明还有别的连接占着写锁——先停应用或确保单连接维护窗口。四、VACUUM INTO边整理边「另存一份」官方支持的写法大意是把整理后的结果写到新路径原库仍保留适合做灰度切换或离线备份链。示例VACUUMINTOpacked.db;实践顺序可以是业务低峰停写或只读在同版本 SQLite 上执行VACUUM INTO得到packed.db校验应用指向新文件或做原子mv。与 shell 层cp不同VACUUM INTO产出的是已紧缩页布局的新库。五、auto_vacuum与incremental_vacuum别和全量VACUUM混为一谈三者解决的是不同维度的问题概念作用PRAGMA auto_vacuum建库时策略是否在删除数据后把页还给 freelistNONE / FULL / INCREMENTAL。只能在库较空时切换策略不是随时改着玩。PRAGMA incremental_vacuum(N)在INCREMENTAL模式下每次回收最多 N 个页渐进整理比全量VACUUM温和。VACUUM一次性重写整个库文件空间回收最彻底停顿与空间开销最大。查询当前策略PRAGMA auto_vacuum;PRAGMA page_count;PRAGMA freelist_count;在INCREMENTAL模式下可试着回收一部分空闲页示例最多 500 页PRAGMA incremental_vacuum(500);工程含义如果你希望「线上偶尔挤一挤水分」而不是「半夜全量搬家」可以评估INCREMENTAL incremental_vacuum但最终是否需要全量VACUUM仍以监控到的文件膨胀与维护窗口为准。六、WAL 模式下你在额外关心什么启用 WALPRAGMA journal_modeWAL时磁盘上常见app.dbapp.db-walapp.db-shm。全量VACUUM之前通常要保证没有长事务占着写理解VACUUM会重写主库WAL 文件会在流程中被处理掉具体细节以官方描述与本机测试为准若在服务器上跑尽量安排在低峰 备份策略清晰的时段。不确定时先在 staging 库上演练一遍录sqlite3版本与journal_mode输出。七、磁盘与锁最容易翻车的两点磁盘重建需要额外临时空间。磁盘红了时跑VACUUM可能中途失败留下半成品或事务异常——务预留空间并监控。锁VACUUM需要排他访问。多进程 / 连接池场景若没有协调就会出现locked或长时间阻塞。嵌入式移动端可在应用退出后由维护任务执行服务端则要有变更窗口或只读副本维护的概念。八、与开源协作工作流的衔接仓库里常见用法本地集成测试数据库CI 里生成 fixture 后跑一次VACUUM减小缓存 artifact注意密钥不要打进库。开发者文档在README或CONTRIBUTING.md写清「示例库重建命令」方便新人可复现。与 Git.db是否入仓由团队决定若仅作演示VACUUM 后体积更小clone 更快——但仍建议大文件用 LFS 或外链别把生产数据提交进公开仓库。上述对应 Persona 中的开源协作锚点 可核对命令 读者可带走清单。九、排错检查清单建议收藏sqlite3 --version与生产是否一致大版本跨迁移先备份。PRAGMA journal_mode;/PRAGMA foreign_keys;是否符合预期。是否有第二个进程打开同一路径含桌面工具、方言 shell。磁盘剩余空间是否大于约一份库文件量级。是否更适合incremental_vacuum而不是上来就全量VACUUM。维护前是否已在副本上演练VACUUM INTO很适合练手。十、总结VACUUM是 SQLite物理文件级整理不是心理安慰 SQL它能减小体积但要用锁、磁盘、WAL、维护窗口来交换。日常可以先学会PRAGMA page_count/freelist_count读现象再决定全量VACUUM还是增量incremental_vacuum。更多边角参数如页大小、安全等级以SQLite 官方文档为准本文只覆盖最常落地的分支。你在生产或移动端里是定期全量VACUUM还是偏向auto_vacuum 增量有没有踩过「磁盘不够中途失败」或「被锁到超时」评论区说说环境嵌入式 / 服务端和 SQLite 版本一起对齐经验。