0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【続編】CodexのSQLite大量書き込みはWindowsでも起きていた――10分監視で回避策を再検証

0
Last updated at Posted at 2026-07-26

前回の記事では、macOS上のCodex Desktopがlogs_2.sqliteへ診断ログを継続的に書き込む状態を実測し、可逆的なSQLiteトリガーで新規挿入を止めた。

今回はその続編として、Windows 11の別PCでも同じ現象が起きているのかを確認した。

結論から言うと、Codex Desktop 26.721.4979.0でも診断ログの継続的な挿入・削除を確認した。対策前は45秒でログIDが836進み、約18.6 ID/秒だった。対策後はCodexを実際に使いながら10分間監視し、新規ログIDの増加は0だった。

ただし、今回の10分監視では重要な補足も見つかった。

新規INSERTが止まっていても、既存ログの整理によって行数が減り、DBやWALが低頻度で更新されることがある。

「WALの更新時刻が一度でも変わったら対策失敗」と判定すると、正常に効いている回避策を誤って失敗扱いしてしまう。

TL;DR

  • Windows 11 / Codex Desktop 26.721.4979.0でもSQLite診断ログのchurnを確認した
  • 対策前の45秒で最大ログIDは+836、約18.6 ID/秒だった
  • DBは約758.4 MiB、WALは約26.1 MiBだった
  • 保持行数が減っていても最大IDは増えており、挿入と削除が同時に進んでいた
  • block_log_inserts適用後、600秒・120サンプルで最大IDの増加は0だった
  • その間に既存ログが1,955行減り、WALのmtimeは4回変化した
  • 主判定は「トリガーが残っている」「sqlite_sequence差分が0」の2点
  • Windowsの一般的なプロセスI/O値は、SSDへの物理書き込み量として扱えない
  • 回避策は非公式であり、/feedbackやサポート用の診断情報が保存されなくなる

診断スクリプトと匿名化した測定データは次のリポジトリへ追加した。

なぜWindowsでも調べたのか

元になったIssue #28224では、21日間で約37 TBのSSD書き込みが観測されたと報告されている。

その後、Codex 0.142.0以降へログ量を減らす修正が入り、報告者の環境では約85%削減されたとしてIssueはクローズされた。しかし「診断ログを完全に無効化する修正」ではない。

後続のIssue #31478では、修正後のバージョンでも約27.6 ID/秒で採番が進む状態が報告されている。そこで、現在使っているWindows PCを推測ではなく実測することにした。

検証環境

項目
OS Windows 11 Pro 64-bit、build 26200
Codex Desktop OpenAI.Codex 26.721.4979.0
Python 3.12.10
対象DB %USERPROFILE%\.codex\logs_2.sqlite
SQLiteモード WAL
DBサイズ 795,271,168 bytes(約758.4 MiB)
WALサイズ 27,373,312 bytes(約26.1 MiB)
検証日 2026年7月26日

Windowsのストレージ管理画面では、CドライブのSSDはHealthy / OKだった。ただし、管理者権限なしではSMARTの累積書き込み量や消耗率を取得できなかった。

したがって、この記事で確認するのはSQLite上の論理的な挿入とファイル更新であり、SSDの残り寿命そのものではない。

同名DBが2個あった

最初に.codex配下の大きなファイルを調べると、logs_2.sqliteが2か所に存在した。

パス サイズ 状態
%USERPROFILE%\.codex\logs_2.sqlite 約758 MiB 現在更新中
%USERPROFILE%\.codex\sqlite\logs_2.sqlite 約392 MiB DB本体とWALは更新なし

単に同名ファイルを見つけて対策するだけでは、古いDBへトリガーを作ってしまう可能性がある。

診断ツールでは、次の優先順位でアクティブな保存先を解決する。

  1. --dbで明示したパス
  2. --sqlite-home
  3. CODEX_SQLITE_HOME
  4. config.tomlsqlite_home
  5. ${CODEX_HOME:-~/.codex}/logs_2.sqlite

さらに、実際の更新時刻とCodexプロセスの稼働を照合した。

対策前の45秒監視

Codex Desktopを起動し、通常のやり取りを行いながら5秒間隔で測定した。

指標 開始 終了 差分
最大ログID 134,976,616 134,977,452 +836
保持行数 107,167 106,978 -189
採番速度 約18.6 ID/秒

ここで重要なのは、保持行数は189件減ったのに、最大IDは836進んだことだ。

現在の行数だけを見ると「ログが増えていない」ように見える。しかし内部では新しいログを挿入し、古いログを削除している。WALはサンプル中ほぼ毎回更新され、DB本体もチェックポイントとみられる更新を繰り返していた。

保持ログ本文の生値は取得・公開せず、レベルとターゲットだけを集計した。

レベル 保持行数
TRACE 64,107
DEBUG 20,286
INFO 19,784
WARN 2,689
ERROR 88

最も多かった組み合わせはcodex_api::sse::responsesTRACEで、43,791行だった。

WindowsのプロセスI/O値には注意する

対策前、WindowsのWin32_PerfFormattedData_PerfProc_ProcessでCodex app-serverを測ると、IOWriteBytesPersecは20秒平均約1.59 MiB/s、最大約21.6 MiB/sだった。

一見すると、これを24時間や年間へ換算したくなる。

しかし、対策後も同じカウンターは15秒平均約1.79 MiB/sを示した。一方で、SQLiteの最大IDは固定され、WAL更新も大幅に減っていた。

WindowsのプロセスI/Oカウンターにはファイル以外のパイプなども含まれる。そのため、値をそのままSSDへの物理書き込み量として扱うことはできない。

短時間のプロセスI/O値から「年間○TB書く」「SSD寿命が○年縮む」と外挿するのは避けるべきだ。

可逆的な回避策を適用する

今回も、logsテーブルへの新規挿入だけを無視するSQLiteトリガーを使用した。

CREATE TRIGGER block_log_inserts
BEFORE INSERT ON logs
BEGIN
  SELECT RAISE(IGNORE);
END;

このトリガーは、state_5.sqlite、会話履歴、セッション、ゴールには触れない。削除すれば診断ログを再開できる。

安全確認を含むスクリプトでは、Windows PowerShellから次のように実行する。

git clone https://github.com/Sunwood-ai-labs/diagnose-codex-sqlite-writes.git
Set-Location .\diagnose-codex-sqlite-writes

py -3 .\scripts\diagnose_codex_sqlite_writes.py `
  --action mitigate `
  --confirm-diagnostic-logging-loss `
  --duration 60 `
  --interval 5 `
  --verbose

通常は、Codex Desktop、Codex CLI、IDEのCodex連携を終了してから実行する。

今回の実験はCodexとの対話セッション自体を監視対象にしたため、ライブDBへSQLiteのbusy_timeoutを設定したうえで適用した。スクリプトで同じことを行うには、ロック競合のリスクを明示的に受け入れた場合だけ--allow-running-codexを追加できる。

py -3 .\scripts\diagnose_codex_sqlite_writes.py `
  --action mitigate `
  --confirm-diagnostic-logging-loss `
  --allow-running-codex `
  --duration 60 `
  --interval 5 `
  --verbose

可能なら、Codexを終了してから適用する方が安全である。

適用直後の35秒確認

トリガー作成直後、5秒間隔で7回確認した。

指標 結果
最大ログID 134,988,790 → 134,988,790
保持行数 107,154 → 107,154
WAL mtime変化 0
トリガー状態 expected

この短時間確認では、採番値、保持行数、WAL更新時刻がすべて固定された。

ただし、35秒だけで「今後もずっと止まる」とは言い切れない。そこで、同じCodexセッションを使い続けながら10分間監視した。

10分監視で見えたもの

5秒間隔で600秒、合計120回サンプリングした。

指標 結果
監視時間 600秒
サンプル数 120
最大ログID 134,988,790 → 134,988,790
採番値の増加 0
保持行数 107,154 → 105,199(-1,955)
DB mtime変化 1回
WAL mtime変化 4回
トリガー不在 0回
読み取りエラー 0回

最大ログIDは10分間一度も増えなかった。つまり、logsテーブルへの成功した新規挿入は観測されていない。

一方、保持行数は途中で1,955行減り、DBのmtimeが1回、WALのmtimeが4回変化した。これは、すでに保存されていたログのretention cleanupやSQLiteのチェックポイントによるものと解釈できる。最後の約59秒ではWAL更新もなかった。

最初に作った簡易監視では「WALのmtime変化が1回でもあればCHECK_REQUIRED」という厳しすぎる条件にしていた。そのため、出力上は要確認になった。

しかし、次の事実を分けて考える必要がある。

  • 新しい診断ログの挿入:sqlite_sequenceが進む
  • 既存ログの整理:行数が減り、DB/WALが更新されることがある
  • SQLiteメンテナンス:採番値が固定でもファイル更新が起きることがある

したがって、回避策の主判定は次の2点にする。

  1. 監視終了時にもblock_log_insertsが期待どおり存在する
  2. Codex稼働中のsqlite_sequence差分が0である

行数減少や低頻度のmtime変化は、主判定とは分けて報告する。

自分のPCで10分確認する

公開スクリプトでは次のコマンドで同じ条件を再現できる。

py -3 .\scripts\diagnose_codex_sqlite_writes.py `
  --duration 600 `
  --interval 5 `
  --verbose

監視中にCodexへ通常のプロンプトを送り、実際のログ発生経路を動かす。

期待する出力は次のようなものだ。

Verdict: MITIGATED
Sequence: 134988790 -> 134988790 (+0, 0.0 ids/s)
Trigger block_log_inserts status: expected -> expected

WALのmtime変化が少数残っても、採番差分が0なら新規ログ挿入は止まっている。行数が減った場合は既存ログ整理として別に確認する。

匿名化した今回の測定値もJSONで公開している。

診断ログを元へ戻す

OpenAIサポートへ問い合わせる場合や、/feedback用の診断情報を再び保存したい場合は、トリガーを削除する。

py -3 .\scripts\diagnose_codex_sqlite_writes.py `
  --action restore `
  --confirm-enable-diagnostic-logging `
  --duration 5 `
  --interval 1 `
  --verbose

復元するとSQLiteへの診断ログ書き込みも再開する。

今回証明できたこと

  • Windows 11の対象PCでもSQLite診断ログの継続的な採番を確認した
  • 保持行数が減っていても、新規挿入が並行していた
  • トリガー適用後、Codex稼働中の10分監視で採番値は増えなかった
  • 既存ログ整理による行数減少と低頻度のWAL更新は残り得る
  • 採番値とmtimeを分けて判定する必要がある
  • 同名DBが複数ある場合、アクティブな保存先の解決が重要である

今回証明していないこと

  • SSDへ実際に書き込まれた物理バイト数
  • SSD内部の書き込み増幅率
  • すでに消費したTBW
  • SSDの残り寿命
  • すべてのCodexバージョン・機能・OSで同じ頻度になること
  • 将来のCodex更新やDB再作成後もトリガーが残ること
  • この回避策がOpenAI公式サポート対象であること

Windows上でSSDがHealthyと表示されても、過去に書き込み寿命を消費していない証拠にはならない。一方、短時間のSQLite測定だけでSSD故障を断定することもできない。

観測できた事実と、測定できていないSSD内部の状態は分けて扱う必要がある。

まとめ

前編のmacOSに続き、Windowsの新しいCodex DesktopでもSQLite診断ログのchurnを確認した。

今回のWindows環境では、対策前に約18.6 ID/秒で採番が進んでいた。block_log_inserts適用後は、Codexを使いながら10分監視しても採番値の増加は0だった。

そして、長めに監視したことで「新規挿入が止まっていても、既存ログ整理によるWAL更新は残る」という点も確認できた。

ファイルサイズやmtimeだけでなく、成功したINSERTを示す採番値を測る。

対策を置いただけで終わらせず、Codexの実稼働中にsqlite_sequenceが止まったことまで確認するのが重要だ。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?