8.8
深览指数
科技腾讯新闻·浮之静··AI 生成
Codex 日志正在燃烧你的 SSD
本文揭示 OpenAI Codex 因持久化 SQLite 日志 sink 默认接收过宽 TRACE 来源,导致高频写入 SSD、消耗寿命的严重工程缺陷。作者梳理了五个层面:日志的角色、SQLite 写放大机制、关键 GitHub issue 证据链、用户偏方(trigger、tmpfs 软链、迁移介质)的有效性边界,以及上游应做的真正修复。适合重度 Codex 用户、AI 工具开发者及关注本地持久化工程边界的读者阅读。原文 ↗
核心观点
- ▍Codex 的持久化 SQLite 日志 sink 默认接收过宽 TRACE 级日志,且与用户可见的 `RUST_LOG=warn` 过滤器不同步,导致高频 SSD 写入,问题核心是持久化边界错误而非单纯的日志文件增长。
- ▍真正的修复应在上游实施:收窄 SQLite log sink 的默认过滤级别、websocket/SSE payload 不该默认落盘、提供明确的配置开关(如 `sqlite_log_level = "warn"`),而非让用户依赖 trigger、RAM disk 或迁移介质等权宜之计。
- 01Issue #17320 确认,即使设置 `RUST_LOG=warn`,`logs_2.sqlite` 仍持续写入 TRACE 日志,流式回复时 `app-server` 进程向 WAL 的写入速率可达 5 MiB/s,峰值约 16 MiB/s。
- 02Issue #28224 报告者外推,Codex 日志写入可能达 640 TB/年,但保留日志量仅约 1 GiB,说明'保留数据很小但写入 churn 很大',净增长不能代表 SSD 实际写入。
- 03作者核对源码 `c03742ca` 确认,`app-server` 和 TUI 中 SQLite log DB layer 使用 `Targets::new().with_default(Level::TRACE)`,与用户设置的 `RUST_LOG` 环境变量构成独立过滤边界。
- 04`logs_2.sqlite` 的 `logs` 表包含 4 个索引(`idx_logs_ts`、`idx_logs_thread_id` 等),每插入一行日志会更新多个 B-tree 索引,后续 prune 删除又会更新这些结构,产生大量物理写入。
- 05当前保留策略(10 天、per-thread 约 10 MiB/1000 行)控制的是'最终留下多少日志',而非'为了留下这些日志,磁盘被写了多少次'。
- 06`logs_2.sqlite` 可能包含 websocket/SSE 原始 payload,带来隐私风险:低层对话或请求内容可能被持久化落盘。
反方 / 局限
- — 本文主动挖出了'用了 Codex 你的 SSD 一年必死'这个说法的局限:TBW 是保修阈值而非硬死亡线;SSD 的 FTL 和磨损均衡通常防止'烧同一小块';真正危险组合是'高频写入 + 盘接近写满 + 长时间运行'。
- — 网上流传的触发器(`RAISE(IGNORE)`)虽能阻断新行添加,但并非源码修复,会导致反馈日志缺失,且后续版本迁移 schema 时可能被无声删除,需要用户升级后复查。
- — macOS 上软链 `logs_2.sqlite` 到 `/tmp` 基本无效,因为 macOS 的 `/tmp` 是 APFS 路径而非 tmpfs,日志仍在同一块内置 SSD 上,不会减少写入。
OpenAI CodexSQLiteSSD TBWWAL (Write-Ahead Log)RUST_LOGOpenTelemetryGitHub Issue #17320GitHub Issue #28224tmpfsAPFS
36 分钟 · 5 卡片 · 14 资料
读原文 →