概要:
第一次排查时混淆了保留日志量与写入量的概念。在 codex
插入日志 → 写入 WAL → 更新索引 → checkpoint → 合并主文件 → 删除旧记录 → 再插入
的过程中,海量的日志插入导致了高频的写后删循环,配合 SQLite 的 WAL 预写式日志机制在 SSD 底层产生了极强的写入放大。
也就是说,保留的日志虽然不多,但实际过程中写入+删除的数据量远超正常范围。这才是可能会导致 SSD 损耗的实际因素。
本次排查将聚焦在写入速度监控,对SSD的影响检查,以及确认官方修复内容这三点上。
1. Codex日志情况监控
保留行 vs 累计插入行
- 检查保留行
1 | SELECT level, COUNT(*) FROM logs GROUP BY level; |
数据库中保留了一共约7000行的日志记录。
- 检查累计插入行
1 | -- 查看历史累计总写入量 |
数据库累计插入过579万行记录
由于之前手动清空过一次数据,清除前大约也有7000行的数据量。所以保留的日志量实际约为 1.5万行。
1.5万行 vs 579万行
这说明写后删除量可能已经非常庞大。保险起见,需要确认下目前磁盘的I/O和健康情况。
磁盘I/O与健康信息
- 监控磁盘I/0
按 win 输入 resmon ,回车打开资源监视器
切换到磁盘选项卡,点击表头的写(字节/秒)使它按降序排列,勾选codex.exe开启独占监控。
可以看到当前总写入才 3,753 字节/秒(大概 3.7 KB/s),属于正常待机状态。
- 磁盘健康状况
打开 CrystalDiskInfo 软件检查情况。


整体没什么问题。继续监控 codex 单独进程的写入情况。
2. 使用 Procmon 监控
- 搜索 Process Monitor Microsoft 下载软件
- 管理员身份运行 Procmon.exe
- 首先
Ctrl + E,Ctrl + X停止并清除捕捉,避免内存消耗
设置过滤器
Filter 菜单中勾选 Drop Filtered Events,避免无关事件占用内存。
Ctrl + L设置如下规则
Process Name is codex.exe Include
Path contains logs_2.sqlite Include
Operation is WriteFile Include(可选)
设置完成后保存,Ctrl + X确保记录为空,Ctrl + E开始捕获。
- 工具栏上只保留“文件系统活动”,可以关闭注册表、网络和进程活动
分析监控记录
稍等一会儿,主窗口出现如下内容
看到基本都是在写入WAL和更新SHM索引
监控一段时间后(30分钟~1小时), Ctrl + E停止监控
查看累计写入量
打开 Tools → File Summary
By Path 下各日志的 Write Bytes相加,得到闲时(1小时)的总写入量为 10.14MB
这个量级对SSD寿命来说基本可以忽略。
3. 确认官方修复内容
根据GITHUB ISSUE #28224 来看,维护者陆续做了这三件事以修复该问题:
不再记录成功 WebSocket 的完整事件(0.142.0)
旧版本中,每收到一个正常成功的 WebSocket 事件,可能产生三条本地记录:
| 完整 payload 的 TRACE 日志 |
| 一份 OpenTelemetry log |
| 一份 OpenTelemetry trace |
修复后只记录如下信息
| 事件数量 | 执行耗时 | 响应时间 | 解析过程 | 出错信息 |
过滤大量无价值日志(0.142.0)
以下日志不再存入本地 SQLite
同时适用于 cli , desktop app 和 vs code 插件
修复 0.142.0 的过滤漏洞(0.143.0)
142 中排除 target = log 日志时,拦截时日志可能(原本是第三方依赖库的日志)还没有转换为 target = log ,导致 142 版本的拦截失效,仍然有 target = log 绕过检查插入数据库。0.143.0 中在入库前又检查了一次,确保 target = log 不会写入。
确认完毕,更新本地 codex 到最新版 [0.144.0-alpha.4]
后续观察
更新完毕后,先撤销之前的拦截触发器
- 记得先关闭 codex 再操作,避免产生临时锁冲突
1 | DROP TRIGGER IF EXISTS block_useless_logs; |
点击写入更改存盘。
检查日志插入情况
1 | SELECT |
检查到每分钟插入日志条数如下
TODO
利用Procmon持续监控写入量
评论