AI工具

Codex logs_2.sqlite 后续:问题修复后仍监控到 194 MB/小时的写入(三)

发布于 2026-07-14 #Codex#Procmon#SQLite#磁盘I/O#TRACE日志#WAL

概要:

上一篇中,在拦截 TRACE/DEBUG 日志的 Trigger 生效时,Procmon 监控一小时的总写入量约为 10.14MB

后来更新 Codex 并撤销 Trigger,我又监控了一小时。这次 logs_2.sqlite 相关文件的总写入量变成了194MB

撤销 Trigger 后 Procmon 一小时文件写入汇总

也就是说,撤销 Trigger 后的写入量约为之前的 19 倍。这其中主库写入 70MB, WAL 写入 123MB


查看日志来源

先统计数据库最新一条日志之前 60 秒内,各日志级别和 target 的写入数量:

1
2
3
4
5
6
7
8
9
10
11
12
13
WITH cutoff AS (
SELECT MAX(ts) - 60 AS start_ts
FROM logs
)
SELECT
level,
target,
COUNT(*) AS row_count
FROM logs, cutoff
WHERE ts >= cutoff.start_ts
GROUP BY level, target
ORDER BY row_count DESC
LIMIT 30;
最近 60 秒日志按 level 和 target 分组统计

从结果来看,官方移除无价值日志的维护已经起效,之前提到的那些日志没有再出现。
不过,目前仍然存在高频写入的 TRACE 日志。(例如TRACE codex_app_server::outgoing_message


检查WAL写回主库频率及数据量

在 Procmon 中设置以下过滤条件:

Process Name  is  codex.exe
Path          is  C:\Users\用户名\.codex\logs_2.sqlite
Operation     is  FlushBuffersFile

持续监控一小时,共捕捉到 17 次针对 logs_2.sqlite 主库的刷盘操作:

一小时内 logs_2.sqlite 的 FlushBuffersFile 记录

刷盘通常发生在checkpoint后写回主库时,因此可近似认为这一小时内完成了 17轮 checkpoint。

即 WAL 达到阈值 → 将 WAL 的更改写回主库 → WAL 从头记录 的过程约重复了17次

继续修改过滤条件为Operation is SetEndOfFileInfomationFile,得到这17次刷盘前SQLite设置的主库大小

一小时内 logs_2.sqlite 的 SetEndOfFileInfomationFile 记录

图中 Detail 的 EndOfFile: 14,286,848 代表: SQLite 需要让主数据库文件增长到这个大小,才能继续写入后面的页面。

也就是说在这一小时 17 次的写回主库操作中,主库大小从 14 MB → 26 MB → 38 MB,实际增长了约 24 MB 的大小。
按数据库页大小为 4096 B 计算,就是净增加了 5839 个数据库页面。


不过实际上主库的总写入量约为 70 MB , 即还有约 46 MB 的写入是更新了主库中已有页(可能是清除日志或其他操作)。因此主库文件的实际增长量只有约 24 MB 而非 70 MB 。

logs_2.sqlite大小

可以看到图中当前主库的文件大小为 38 MB , 和最后一次 EndOfFile: 38203392 设置的数值一致。

DB Browser 可能影响 WAL 重置

监控期间,logs_2.sqlite-wal4 MB 增长到了 14 MB

如果 DB Browser 仍保持读取连接,例如正在浏览数据或执行查询,checkpoint 可能执行不完全,WAL 也无法重置并从头复用,因此会越长越大…

不过主要原因应该还是清除 Trigger 后 TRACE 日志增长过快导致的。

处理建议
  • DB Browser 查询完后,点击关闭数据库释放连接。
  • 如果是命令行查询,一次性命令完成后 SQLite 会自动关闭连接;如果进入了 sqlite> 交互模式,则需要使用 .quit 退出。
  • 如果 WAL 已经很大,彻底关闭 Codex、ChatGPT 和 DB Browser。最后一个 SQLite 连接关闭时通常会执行最终 checkpoint,并清理 WAL、SHM 文件。

下次打开 Codex 后,WAL 会重新开始增长。

logs_2.sqlite、WAL 与 SHM 三者的关系
  • logs_2.sqlite:保存已经 checkpoint 的基础数据。
  • logs_2.sqlite-wal:保存已提交、但还没写回主库的页面更新。相比主库数据更新
  • logs_2.sqlite-shm:WAL 的临时索引和锁状态,帮助 SQLite 定位最新页面。

查询时: 打开的是 logs_2.sqlite。SQLite 会通过 SHM 检查所需页面在 WAL 中是否有更新版本:有就读取 WAL,没有才读取主库,因此查询到的是两者合并后的最新结果。

  • 如果主库丢了,单靠 WAL 通常无法还原完整数据库;
  • 如果 WAL 暂时没 checkpoint,单独复制主库则可能缺少最新提交。

因此不要在 Codex 运行时只复制 logs_2.sqlite 做备份,最好使用 SQLite 的 .backup 命令或先正常关闭所有连接。

关于 WAL 和主库写入量差值的说明

WAL 写入 123 MB,主库写入 70 MB,这两个之间有差值是正常的。

  • 这是因为 WAL 会记录多个修改版本可能中间改了10次,但主库只在 checkpoint 时记录最终的版本只写最新一个

TODO

综合下来本次监控发现:去除 trigger 后修复版本的日志写入量仍然偏大,计划再找时机监控取多段数据分析。
如果后续写入量仍然居高不下,考虑继续应用 trigger 拦截或者启用 RUST_LOG 按模块定向过滤日志

评论
分享

评论