朝のデスクで、二つの画面に並んだ集計を見比べながら、食い違いがないかを落ち着いて確かめている一人運用の保守担当者

データ不整合に気づく仕組み|件数突合チェックを毎朝自動で回す

「先月の売上、管理画面と会計の数字が合わないんですけど……」。 経理の人からそう声をかけられて、慌ててDBを開く。調べてみると、ある日の連携処理が途中で止まっていて、数十件だけ相手側に渡っていなかった——。そんな経験、ありませんか。

データの食い違い(不整合)は、エラー画面のように派手には出てきません。処理は「正常終了」と言っているのに、中身だけが静かにずれていく。だから、誰かが数字を見比べたときに初めて見つかることが多いのです。それは見落としではなく、気づく仕組みがまだ無かっただけです。

この記事では、お客さまや他部署より先に自分が気づけるように、件数や合計を突き合わせる小さなチェック(突合)を毎朝自動で回すやり方を、一人運用の目線で一緒に組み立てます。大きな監視ツールは要りません。SQLが1本書ければ始められます。

結論:データ不整合は「数えて・比べて・ずれたときだけ知らせる」チェックで早く気づけます。やることは3つ。①「本来一致するはずの2つの数」を1組決める、②その2つを数えるSQLを書き、差が0でないときだけ通知する、③cronなどで毎朝自動で回す。まずは「いちばん問い合わせが来やすい数字」1組から始めます。

SQLの書き方や関数名は、使っているDB(MySQL・PostgreSQL など)やバージョンで少しずつ違います。ここでの例は考え方の見本として、自分の環境で SELECT だけ試してから使ってください。

何が起きているのか:データ不整合が「静かに」生まれる理由

不整合は、たいてい2つの場所に同じ事実を持っているところで生まれます。たとえば次のような組み合わせです。

ずれる原因は、だいたい次のどれかです。

どれも「処理は終わっている」ように見えるのが厄介なところです。cronやバッチの失敗検知を入れていても、成功扱いで中身だけずれるケースは拾えません。そこで、結果のデータそのものを数えて確かめる、というのが突合チェックの考え方です。

件数突合チェックの作り方(数える・比べる・知らせる)

件数突合チェックの3ステップを示した図。左は二つの箱の中身を数える様子、中央は天秤で二つの数を比べる様子、右はずれたときだけ通知が届くスマホ
「数える」「比べる」「知らせる」の3つだけ。ずれたときだけ通知するのがコツ

突合チェックは、3つの部品でできています。順番に作っていきましょう。

① 数える:「本来一致するはずの2つの数」を決める

最初に決めるのは、「この2つは必ず同じになるはず」と言える数の組です。全部を一度にやろうとせず、1組だけ選びます。選び方の目安は、過去に問い合わせや「合わない」が起きた数字です。

よく使う組み合わせの例です。

「本来は0件」になるものは特に作りやすいので、最初の1本におすすめです。

② 比べる:差が出たらすぐ分かるSQLにする

数え方は、SELECT だけで書きます。チェックではデータを書き換えないのが大前提です。

親のない明細を数える例(テーブル名・列名は自分の環境に読み替えてください):

-- 親(orders)が存在しない明細(order_items)の件数。本来は 0
SELECT COUNT(*) AS orphan_count
FROM order_items oi
LEFT JOIN orders o ON o.id = oi.order_id
WHERE o.id IS NULL;

同じ注文番号の重複を数える例:

-- 同じ注文番号が2行以上ある番号の数。本来は 0
SELECT COUNT(*) AS dup_count
FROM (
  SELECT order_no
  FROM orders
  GROUP BY order_no
  HAVING COUNT(*) > 1
) d;

2つの数を比べるものは、どちらも「昨日分」のように期間をそろえるのがコツです。期間がずれていると、本当は合っているのに「差あり」になってしまいます。とくに日付の境目(タイムゾーンや締め時刻)は食い違いやすいところなので、日付・タイムゾーンのずれもあわせて確かめておくと安心です。

③ 知らせる:ずれたときだけ通知する

チェックの結果は、差が0なら黙っている、0でないときだけ知らせるようにします。毎朝「異常なし」が届くと、すぐに読まなくなってしまうからです(監視アラートの鳴らしすぎと同じ理屈です)。

シェルで組む場合の考え方の例です(接続方法や通知の送り先は環境に合わせてください)。

#!/bin/sh
# 毎朝の突合チェック:差が 0 でなければ通知する
COUNT=$(mysql --defaults-extra-file=/path/to/readonly.cnf -N -e "
  SELECT COUNT(*) FROM order_items oi
  LEFT JOIN orders o ON o.id = oi.order_id
  WHERE o.id IS NULL;" mydb)

if [ "$COUNT" != "0" ]; then
  echo "親のない明細が ${COUNT} 件あります(order_items)" | mail -s "[突合] 不整合あり" ops@example.com
fi

ここで押さえたいのは2点です。

毎朝自動で回す

できたスクリプトは、cronなどで朝、業務が始まる前に回します。夜間バッチが終わったあとの時間にすると、その日の処理結果まで含めて確かめられます。

# 毎朝 7:30 に突合チェック(夜間バッチ完了後の時間に合わせる)
30 7 * * * /opt/check/tsugo-check.sh >> /var/log/tsugo-check.log 2>&1

重いテーブルを全件数えるSQLは、本番の負荷になることがあります。最初は期間を「昨日分」に絞る、アクセスの少ない時間に回す、レプリカ(読み取り用の複製)があればそちらで数える、のどれかで負荷を抑えましょう。

具体例:こんなふうに気づけるようになる

実際の現場で、突合チェックが役に立つのはこんな場面です。

どれも、チェックが「直してくれる」わけではありません。でも、ずれに気づくのが1か月後から翌朝に変わるだけで、直す量も、説明の重さも、ぐっと小さくなります。

影響:先に気づけると、何が変わるか

明日やること:いちばん問い合わせが来る数字を1組だけ

全部のテーブルを見張る必要はありません。明日できる、いちばん小さな一歩はこれです。

  1. 過去に「数字が合わない」と言われたことがある場所を1つ思い出す(なければ、親子関係のあるテーブルを1組)。
  2. その数字について、「本来は0件」または「本来は同じ」になるSQLを1本、SELECT だけで書く。
  3. 本番(できれば読み取り専用ユーザー)で1回だけ手で実行し、今の結果を見てみる。すでにずれていたら、それは今日見つけられた収穫です。
  4. 結果が0でないときだけ通知するスクリプトにして、毎朝のcronに登録する。
  5. どのチェックを、何時に、何を見ているかを、運用ドキュメントに一行メモしておく。

最初の1本ができれば、2本目からは同じ形をコピーして足していくだけです。

「件数突合チェック」チェックリスト

突合チェックを作るとき・見直すときに当ててみてください。

全部に○が付かなくても大丈夫です。まずは1組の数字を毎朝数えるだけで、気づくのはお客さまより先になります。

よければ、こちらも

突合チェックは、バッチ・データ修正・監視とつながっています。あわせて読むと、気づいてから直すまでがなめらかになります。

朝の通知を確かめて今日も数字が合っていると分かり、コーヒーを手に安心して一日を始める保守運用の担当者

データのずれは、誰かが悪いから起きるのではありません。2つの場所に同じ事実を持つ以上、いつかはどこかで少しずつずれるものです。大事なのは、ずれないことより、ずれたときに早く気づけることです。 今日は、いちばん問い合わせが来る数字を1組、SELECT COUNT(*) で数えてみるだけで十分です。その1本が、毎朝あなたの代わりに数字を見張ってくれるようになります。

ほかの実務ヒントは記事一覧からどうぞ。保守運用の小さな備えを、メールでも少しずつお届けしています。

関連用語