本番DB障害を「探索SQL→原因特定→修正SQL」のループでAIに調査させる
本番DB障害を「探索SQL→原因特定→修正SQL」のループでAIに調査させる
本番データベースの不整合や問い合わせチケットは、開発チームにとって避けて通れない仕事だ。「請求金額がおかしい」「あるはずのデータが表示されない」「二重に登録されている」——こうした報告が届くたびに、経験者が本番へおそるおそる SELECT を投げ、頭の中で仮説を立て、次のクエリを組み立てる。この職人的な手順は属人的で、時間もかかる。
この一連の調査を、AIエージェントに「探索SQL → 原因特定 → 修正SQL」の反復ループとして任せる方法論がある程度確立できたので、一般化して共有したい。特定のプロダクトに依存しない、再現可能な手順として書く。
なぜ「探索SQL」から始めるべきか
障害調査でやってはいけないのは、報告文だけを読んで修正クエリを書き始めることだ。報告者が見ている症状と、DBの実際の状態は往々にしてズレている。「重複している」と言われたレコードが実は別キーの正当なデータだったり、「消えた」データが論理削除フラグで隠れているだけだったりする。
だからまず、状況を把握するための**探索的クエリ(probe SQL)**から始める。probe は必ず読み取り専用で、対象の件数・分布・時系列・関連テーブルとの結合状態を「見る」ことだけに徹する。ここで得た事実をもとに仮説を立て、次の probe で検証する。修正は、原因が確定してからでいい。
この「見てから触る」順序を強制することが、本番調査の安全性の土台になる。AIに任せる場合はなおさらで、いきなり UPDATE を書かせないためのフローそのものがガードレールになる。
ループの設計:probe / fix / impact / timeline
調査を4種類のクエリの役割分担として設計すると、AIに任せやすくなる。
- **probe(探索)**:現状把握と仮説検証。段階的に絞り込むため、1チケットで複数段重ねる(probe → probe2 → probe3 …)。最初は粗く全体像を、次第に疑わしい部分へフォーカスする。
- **fix / restore(修正・復旧)**:原因が確定した後に出す、状態を正すためのクエリ。実行は人間が承認する前提で、まず案として提示させる。
- **impact(影響範囲)**:不整合が何件・どの範囲に及んでいるか。請求や集計に波及する場合、金額換算まで見積もる。
- **timeline(時系列)**:いつから発生しているか。バグの混入時期やデプロイとの相関を掴む。
重要なのは probe を**多段**に重ねる定型フローだ。1回のクエリで真因に到達することは稀で、「全体件数を数える → 条件で絞る → 疑わしい行の周辺を結合で見る → 仮説の反例を探す」と段階を踏む。この段階性こそがAIに向いている。各段の結果を受けて次の probe を生成する反復は、まさにエージェントの得意領域だからだ。
擬似的に書くと、probe はこんな粒度で進む。
-- probe1: 全体像
SELECT status, COUNT(*) FROM generic_table GROUP BY status;
-- probe2: 疑わしい条件で絞る
SELECT * FROM generic_table
WHERE some_flag = 1 AND updated_at > :suspect_since
LIMIT 100;
-- probe3: 関連テーブルとの整合を確認
SELECT g.id
FROM generic_table g
LEFT JOIN related_table r ON r.parent_id = g.id
WHERE r.parent_id IS NULL;
テーブル名やカラム名は各自の環境に読み替えてほしい。ポイントは、各段が独立して「読むだけ」で完結し、次段の入力になっていることだ。
AIに任せる際のプロンプト設計とガードレール
エージェントに調査を任せるとき、プロンプトで次を明示する。
1. **ループの型を与える**:「まず probe を出し、結果を受けて仮説を述べ、必要なら probe を追加し、原因が確定したら fix / impact / timeline を分けて出せ」と手順を固定する。役割ごとにクエリを分類させると、後から人間がレビューしやすい。
2. **読み取り専用を既定にする**:probe と impact / timeline は必ず SELECT(および読み取り系)のみ。UPDATE / DELETE / DDL は「提案」として出させ、実行させない。可能なら実行環境自体を読み取り専用ロールに縛る。
3. **仮説と根拠をセットで言わせる**:「この行が原因と思う」だけでなく「probe2 の結果でこの条件のときだけ件数が合わないから」と根拠を紐付けさせる。根拠のない fix は却下する。
4. **破壊的操作にはガードを付けさせる**:提案する修正には必ず対象を限定する WHERE、影響行数の事前カウント、トランザクションと巻き戻し手順、可能ならバックアップの取得を含めさせる。
これらは要するに、熟練エンジニアが無意識にやっている安全手順を、明文化してエージェントに守らせているだけだ。
得られたもの
このループ化で得られた効果は大きく3つある。
第一に、**調査の再現性**。属人的だった「本番でどう当たりをつけるか」が、probe の多段フローとして誰でも回せる形になった。第二に、**影響見積もりの精度**。impact / timeline をルーチンに組み込んだことで、「何件で、いつから、いくら分ずれているか」を毎回そろえて出せる。請求への波及のような、経営判断に直結する数字を早く出せるのは大きい。第三に、**スループット**。多数の問い合わせチケットを、同じ型で並行して捌けるようになった。
注意点:本番でSELECT以外を流す危険と、人間の境界
最後に、これは省略できない部分だ。
**本番で SELECT 以外を自動実行させてはいけない。** どれだけ probe が積み上がって原因が明確に見えても、fix / restore の実行は必ず人間が承認・実行する境界を引く。AIの仮説は probe の結果解釈を誤ることがあり、その誤りが UPDATE に乗ると本番データを壊す。読み取りの誤りはやり直せるが、書き込みの誤りは取り返しがつかない。
具体的な境界線として、次を守るとよい。
- probe / impact / timeline は自動でよいが、fix / restore は提案までで停止する。
- 修正クエリは、影響行数のカウントを人間が目視で確認してから実行する。
- 実行はトランザクション内で行い、想定件数と一致しなければロールバックする。
- 本番接続はできる限り読み取り専用ロールを既定にし、書き込みは別途明示的に切り替える。
AIは探索と仮説生成、そして影響の見積もりを驚くほど加速してくれる。しかし「本番のデータを書き換える」という最終判断だけは、人間が握り続けるべきだ。ループの価値は、その最終判断に至るまでの道のりを速く・安全に・再現可能にすることにある。

