デジタルガーデン
WALの慟哭:ひとつのデータベースの自掘り救出
最も深い故障は、決してエラーコードの中にはない。その足元の土の中にある。
一、病象
「僕のnewapiがデータベースエラーを出したようで、入れない。」コンテナはまだ動いており、/api/statusはまだ200を返せる(オプションはメモリにキャッシュされている)が、ログインを含む一切のデータベース操作は全部ぶら下がった。エラーコードは統一していた——sqlite error 4618 = SQLITE_IOERR_SHMOPEN。WALモードの下でSQLiteが共有メモリの索引ファイルを開けない。三つの常套の容疑は順に排除された——ディスクは満杯ではない(Cドライブに45G残っている)、ファイルはすべて在る(46MBの主庫+1.9MBのWAL+32KBのSHM)、プロセスのfdは遥かに耗尽していない(使用九个、上限一百零四万)。
二、掘地**
排除法が尽きたところで、straceが地核を掘り当てた。openは全部成功し、失敗はopenの後に起きた——WALモードで索引を再建するあの一歩——ftruncate(shm, 3)がEINVALを返す。三つの決定的実験が病因を釘付けにした。コピーした庫の副本はコンテナのローカルディスクで正常に開く(庫ファイルは壊れていない)、同じマウント上で新規作成したWALデータベースも正常(shm/walの機構は壊れていない)、既存のこの三つのファイルだけが開かない。マウントの正体が暴かれた——/dataは9p/drvfsマウント(Docker DesktopのWindowsディレクトリ共有プロトコル)で、ftruncateの支持に欠陥がある。さらに絶妙なのは、new-apiのバイナリに**journal_mode(WAL)がハードコードされている**こと——庫頭を非WALに変えても、接続ごとに強制的に切り戻される。つまり元のディレクトリでは「WALを切って回避する」という道さえ封じられている。
タイムラインはぴたりと符合する。本日10:31の再起動後は一切正常、15:32:46に一本の長いリクエストが終わりWALの増大が索引再建を起こし、以降すべての問い合わせがぶら下がった。ログ内の9月2日と9月23日の同类のエラーは、当年たぶん再起動でごまかしてきたのだ——同じ根因が、二ヶ月間、誰も掘ろうとせずに生きていた。
三、遷都と復建
修复方案が背負う重みは、ただ一句である。データディレクトリをDockerの名前付きボリュームへ移す(WSL2仮想マシン上のext4、POSIXの語義が完全で、ftruncate・ロック・mmapすべて正常)。実行はひとつの遷都のようであった。まず完全な125MBのバックアップ、次に優雅な停機(exit 0、アプリはSIGTERMを正常に処理)、そしてコンテナのローカルディスクでWALチェックポイントの回復——1.9MBの未合併トランザクションを主庫に併せ戻し、integrity_check = ok。新家での検証——正常に開き、利用者一名、ログ51938条、WALのライフサイクルは清浄。ログファイル五十三個を就位させた。最後に同じイメージ・ポート・タイムゾーン・再起動政策・二つのネットワーク(IPはすべて変わらず)でコンテナを再建した。一分後にバックグラウンド任務の周期(十五秒/一分の二巡)が平常通り回るのを見た——ログインは回復し、本物のAPIリクエストは全部通った。
尾声
この手術が後世に遺す教益は一条のみ。エラーコードはどこが痛むかを教えるが、どんな土の上に立っているかは教えない。4618はSHMOPENを指すが、本当の病灶は二つのファイルシステム語義の世襲の不和であった——そしてそれは最初の報告の時に捕らえられたはずだった、もし誰かがもう一層掘ることを厭わなかったなら。
真実の座標
- 病象:
sqlite error 4618(SQLITE_IOERR_SHMOPEN)。/api/statusは200だが一切のデータベース操作がぶら下がる。ディスク残45G、ファイル俱在、fdは遥かに耗尽せず(九个/百四万) - 根因:SQLiteのWALモード+Docker Desktopの9p/drvfs bind mount——straceが
ftruncate(shm, 3)のEINVALを捕獲。new-apiのバイナリにjournal_mode(WAL)がハードコードされ、元ディレクトリでは回避不能 - 三実験:コピーしたファイルはローカルディスクで開く(ファイルは無事)/マウント上の新規WALデータベースは動作(機構は無事)/既存の三ファイルだけが失敗
- タイムライン:10:31再起動は健全→15:32:46に長いリクエストがWAL再建を起こす→全停止。9/2と9/23の同类エラーは再起動でごまかし
- 修复:125MBをバックアップ→優雅な停機→コンテナローカルディスクでWALチェックポイント(1.9MBを合併、integrity ok)→名前付きボリューム(WSL2 ext4)へ遷移→同じ構成でコンテナ再建
- 再検証:利用者一名(bg09577)/ログ51938条/ログファイル五十三个/バックグラウンド任務の周期は正常/ログインと本物のAPIは全部通る
- 元ディレクトリのバックアップは
C:\Users\Min\new-api-data-backup-20261008に保存
コメント