CHAPTER 06読む目安 15分トランザクション・制約・インデックス・バックアップ

データを守る仕組み

この章のゴール:データベースが「速くて正確で壊れにくい」のはなぜか。トランザクション・制約・インデックス・バックアップの役割を説明できる。

「速くて正確で壊れにくい」の正体

第1章で、データベースはExcelと違って「同時に使える」「間違いを防げる」「大量でも速い」と説明しました。この章では、PostgreSQLがそれをどんな仕組みで実現しているかを4つに分けて見ていきます。どれも裏方の仕組みですが、「なぜデータベースは信頼できるのか」を自分の言葉で説明できるようになるのが目標です。

仕組み1:トランザクション(全部やるか、全部やらないか)

みなと文具に、あおば商事から120,000円の入金がありました。経理の人はこれを記録するために、2つの変更を行います。

  1. 請求書テーブルの該当する行に、入金日を書き込む(UPDATE)
  2. 入金テーブルに、入金の記録を1行追加する(INSERT)

もし1だけが済んだ直後に停電やエラーが起きたら、「請求書は入金済みなのに、入金の記録がない」という矛盾した状態になります。

これを防ぐのがトランザクションです。複数の変更を1つの束にして、「束の全部を確定するか、全部をなかったことにするか」の二択しか起きないようにします。途中半端な状態は、絶対に残りません。

BEGIN;                                        -- 束の始まり
UPDATE invoices SET paid_on = '2026-10-15' WHERE id = 1;
INSERT INTO deposits (invoice_id, amount, received_on)
       VALUES (1, 120000, '2026-10-15');
COMMIT;                                       -- まとめて確定(取り消すなら ROLLBACK)
TRANSACTION(1つの束) ① 請求書に入金日を書く ② 入金の記録を追加する この途中の状態は、外からは決して見えない COMMIT:両方とも確定 ROLLBACK:両方とも取消 「①だけ済んだ状態」は起こり得ない。停電やエラーでも、束ごと取り消される
図6-1 トランザクション。入金処理のように複数の変更がセットになっている業務では、「全部か無か」が保証されていることが決定的に重要です。

トランザクションには、ほかにも大切な約束があります。

  • 確定したら消えない:COMMITが成功した変更は、直後に停電しても失われません。PostgreSQLは変更内容を先に「記録簿」(WAL:先行書き込みログと呼ばれます)に書いてから本体に反映するため、途中で止まっても記録簿から復元できます。
  • 他の人の途中経過は見えない:経理の人がCOMMITする前に、営業の人が同じ請求書を見ても、入金前の状態が見えます。PostgreSQLは読む人と書く人がぶつからないよう、行の「版」を複数持つ仕組み(MVCC)で整理しています。第1章の「複数人で同時に使える」は、この仕組みのおかげです。
ACID(アシッド)という言葉

この4つの性質(全部か無か・矛盾を残さない・互いに干渉しない・確定したら消えない)は、英語の頭文字をとってACIDと呼ばれます。「PostgreSQLはACIDに準拠している」と聞いたら、「お金の処理を任せられる堅実さがある」という意味だと受け取ってください。

仕組み2:制約(入口で間違いを止める)

第4章で見た「主キー」「外部キー」「NOT NULL」は、まとめて制約と呼ばれます。制約は、間違ったデータを入口の時点で拒否する仕組みです。入ってしまってから探して直すより、はるかに確実で安上がりです。

制約守らせること例
PRIMARY KEY行を一意にする(重複・空欄禁止)同じ得意先コードを2回登録できない
FOREIGN KEY他の表に実在する値だけを許す存在しない得意先の請求書を作れない
NOT NULL空欄を禁止する金額が空の請求書を作れない
UNIQUE主キー以外でも重複を禁止する同じ請求書番号(伝票No.)を2回使えない
CHECK値の範囲や条件を決める金額はマイナス不可(CHECK (amount >= 0))

制約が守らせているのは、結局のところ業務のルールです。「どんな制約がついているか」を知ることは、「そのシステムがどんな間違いを許さないか」を知ることと同じです。

仕組み3:インデックス(本の索引)

請求書が100万行あるとき、「得意先コード C001 の請求書」を探すには、何もなければ100万行を頭から全部見るしかありません。これではExcelと同じで、遅くなります。

インデックス(索引)は、本の巻末の索引と同じ発想です。「C001 の行は何ページ目にある」という一覧を別に作っておけば、全ページをめくらずに一気にたどり着けます。

インデックスなし 100万行を上から順に全部確認(遅い) インデックスあり 索引(cust列) C001 → 4行目C002 → 2行目C003 → 9行目… 該当行へ直行(速い)
図6-2 インデックスは「本の索引」。よく検索に使う列(得意先コード、日付など)に索引を作っておくと、行数が増えても探す時間がほとんど増えません。主キーには自動的に索引が作られます。

ただし索引は無料ではありません。行を追加・変更するたびに索引も更新する必要があるため、索引を作りすぎると書き込みが遅くなります。「どの列に索引を張るか」は、システム部門が利用状況を見ながら調整している部分です。

仕組み4:バックアップ(それでも壊れたときのために)

どれほど堅実でも、ディスクの故障や操作ミスでデータが失われる可能性はゼロになりません。最後の砦がバックアップです。

  • 定期的な丸ごとの複製:毎晩、データベース全体を別の場所に保存しておく方法。PostgreSQLには pg_dump という専用の道具があります。
  • 記録簿(WAL)を取っておく:先ほどの「変更の記録簿」を保管し続ければ、「昨夜の複製」+「そこから今朝10時までの記録簿」で、任意の時点の状態に戻せます。誤ってDELETEしてしまった直前に戻す、といった復旧もこの方法で行います。
経理・監査の目で見ると

「バックアップは取っているか」だけでなく、「戻せることを確かめたか(復元テスト)」「どの時点まで戻せるか」が本当の論点です。内部統制やシステム監査で問われるのはこの部分です。

この章のまとめ

  1. トランザクションは複数の変更を1つの束にして「全部か無か」を保証する。確定した変更は停電でも消えず、他の人の途中経過は見えない(ACID)。
  2. 制約(主キー・外部キー・NOT NULL・UNIQUE・CHECK)は、間違ったデータを入口で止める業務ルールそのもの。
  3. インデックスは本の索引。検索を速くするが、作りすぎると書き込みが遅くなる。
  4. バックアップは最後の砦。丸ごとの複製と変更の記録簿を組み合わせ、戻せることを確かめておく。

確認クイズ

Q1トランザクションが保証していることはどれですか。

Q2インデックスについて正しい説明はどれですか。

Q3「金額にマイナスの値を入れられないようにしたい」。これを実現するのはどの仕組みですか。