コンテンツにスキップ

5-3. トランザクション・ACID・インデックス

  • トランザクションが必要になる場面
  • ACID という 4 つの性質
  • COMMITROLLBACK の考え方
  • インデックスが検索を速くする理由と、その代償

データベースは「保存できる」だけでは足りない。
壊れにくいこと必要なデータを速く見つけられること が実務では重要になる。


1. なぜトランザクションが必要なのか

Section titled “1. なぜトランザクションが必要なのか”

データベースでは、複数の更新を まとめて 1 つの意味ある処理 として扱いたいことがある。

たとえば銀行振込を考える。

口座Aから 1000 円引く
口座Bへ 1000 円足す

この 2 つは、片方だけ成功してはいけない。

正しい状態
A -1000
B +1000
危険な状態
A -1000
B +0

もし途中でエラーが起きて「引き落としだけ成功、入金は失敗」になると、データが壊れる。

そこで使うのがトランザクションである。


トランザクションとは、途中で失敗したら全体をなかったことにし、成功したらまとめて確定する処理単位 である。

代表的な流れは次のようになる。

BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;

もし途中で問題が起きたら、ROLLBACK で戻す。

BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
-- ここでエラー
ROLLBACK;
BEGIN
更新1
更新2
問題なし → COMMIT
問題あり → ROLLBACK

つまりトランザクションは、「全部成功」か「全部失敗」かを保証したいときの枠 である。


ACID は、トランザクションに期待される代表的な 4 つの性質をまとめた言葉である。

文字用語意味
AAtomicity全部成功か全部失敗か
CConsistencyルール違反のない状態を保つ
IIsolation同時実行どうしが不正に干渉しにくい
DDurability確定した結果が失われにくい

「1 つの処理単位として分割されない」という性質である。
銀行振込なら、出金だけ成功して入金が失敗する状態を防ぎたい。

処理の前後で、データが守るべきルールを壊さない性質である。

たとえば、

  • 残高がマイナスになってはいけない
  • 存在しない著者 ID を本が参照してはいけない

といったルールを守る。

複数のトランザクションが同時に動いても、お互いの途中結果で壊れにくくする性質である。

取引Aが更新中
取引Bが途中結果を読んでしまう
おかしな判断をする危険

データベースは、こうした干渉を減らす仕組みを持っている。

COMMIT した結果は、システム障害が起きても失われにくいべきだ、という性質である。

つまり ACID は、単なる略語ではなく、「安心して更新するための約束事」 である。


トランザクションでは、最後に結果をどう扱うかを明示する。

コマンド意味
COMMITここまでの変更を確定する
ROLLBACKここまでの変更を取り消す
  • 必要な更新がすべて成功したとき
  • 整合性チェックを通過したとき
  • 途中の SQL が失敗したとき
  • 業務ルールに反したとき
  • 想定しないエラーが起きたとき

ここで重要なのは、「途中で怪しい」と感じたら 中途半端に確定しない ことである。


インデックスとは、目的の行を速く見つけるための補助的な構造 である。

本の巻末索引を想像すると分かりやすい。

索引なし
1ページ目から順に探す
索引あり
キーワードから近い場所を先に絞る

データベースでも同じで、インデックスがないと全行を順に見ることがある。

books テーブル 100万件
isbn = '978...'
先頭から全部調べるかもしれない

インデックスがあると、検索対象を大きく絞りやすい。

CREATE INDEX idx_books_isbn ON books(isbn);
  • WHERE でよく検索する列
  • JOIN で結び付ける列
  • ORDER BY でよく並べ替える列

たとえば books.idbooks.author_idbooks.isbn などは候補になりやすい。


インデックスは万能ではない。

利点代償
検索が速くなりやすい追加・更新・削除時のコストが増える
JOIN が速くなりやすい保存領域を使う
並べ替えが有利なことがある付けすぎると管理が複雑になる

なぜ更新が遅くなりうるのかというと、表本体だけでなくインデックス側も更新しなければならないからである。

行を1件追加
テーブルへ追加
関連インデックスも更新

そのため、よく読む列だけに付ける という発想が大切になる。

多くの RDB では、主キーには自動的にインデックスが付く。
つまり「識別に使う列」と「よく探す列」は、しばしば相性がよい。


トランザクションとインデックスは、どちらも「見えにくいけれど重要な品質」を支えている。

  • トランザクションは 壊れにくさ を支える
  • インデックスは 見つけやすさ を支える

つまりデータベース設計では、

正しく保存できるか
正しく更新できるか
必要なときに速く読めるか

の 3 つを一緒に考える必要がある。


キーワード説明
トランザクションまとめて成功 / 失敗を扱う処理単位
COMMIT変更を確定する
ROLLBACK変更を取り消す
ACID原子性・一貫性・独立性・永続性
インデックス行を速く見つけるための補助構造
更新コストインデックスが多いと書き込みが重くなりうる

演習問題 に取り組んで、ACID とインデックスの考え方を整理しよう。

第5章が終わったら 第6章:セキュリティ基礎 へ進む準備ができる。