コース一覧
データベース内部構造:インデックス・トランザクション・分散DB
MVCC(マルチバージョン同時実行制御)

データベース内部構造:インデックス・トランザクション・分散DB

SQLの書き方ではなく、DBMSの内側を学ぶコースです。RDBとNoSQL、正規化、B-tree、トランザクションとMVCC、クエリプランナ、レプリケーションと分散SQLを通して、性能と整合性の判断根拠を身につけます。

1
データベースの基礎
0. データベースとは8分
1. RDB と NoSQL の違い8分
2. データベースの歴史8分
3. エンティティ関係モデル (ER)8分
4. 主キー・外部キー・候補キー8分
2
正規化
0. 正規化とは何か8分
1. 第1正規形8分
2. 第2正規形8分
3. 第3正規形8分
4. 非正規化のトレードオフ8分
3
インデックスと B-tree
0. インデックスの役割8分
1. B-tree の仕組み8分
2. B+tree(実際の DB 実装)8分
3. ハッシュインデックス8分
4. カバリングインデックス8分
4
トランザクションと ACID
0. トランザクションとは8分
1. ACID 特性8分
2. 分離レベル8分
3. MVCC(マルチバージョン同時実行制御)8分
4. デッドロックと回避8分
5
クエリ最適化
0. クエリプランナの役割8分
1. EXPLAIN の読み方8分
2. Nested Loop / Hash / Merge Join8分
3. インデックスチューニング8分
4. 統計情報とカーディナリティ8分
6
スケーリング
0. レプリケーション8分
1. シャーディング8分
2. CAP 定理8分
3. 結果整合性8分
4. NewSQL と分散 SQL8分

データベース内部構造:インデックス・トランザクション・分散DB

01データベースとは
02RDB と NoSQL の違い
03データベースの歴史
04エンティティ関係モデル (ER)
05主キー・外部キー・候補キー
06正規化とは何か
07第1正規形
08第2正規形
09第3正規形
10非正規化のトレードオフ
11インデックスの役割
12B-tree の仕組み
13B+tree(実際の DB 実装)
14ハッシュインデックス
15カバリングインデックス
16トランザクションとは
17ACID 特性
18分離レベル
19MVCC(マルチバージョン同時実行制御)
20デッドロックと回避
21クエリプランナの役割
22EXPLAIN の読み方
23Nested Loop / Hash / Merge Join
24インデックスチューニング
25統計情報とカーディナリティ
26レプリケーション
27シャーディング
28CAP 定理
29結果整合性
30NewSQL と分散 SQL

データベース内部構造:インデックス・トランザクション・分散DB

MVCC(マルチバージョン同時実行制御)

集計を流したら、書き込みが止まった

売上テーブルを頭から読む集計クエリを、業務時間中に流したとします。数十秒後、注文の登録が次々とタイムアウトし始めました。集計は読んでいるだけで、1 行も書き換えていません。

読むだけでも止まるのは、読み手と書き手が同じ順番待ちの列に並ぶ作りだからです。読む側は「読んでいる間に書き換えられては困る」ので行を押さえ、書く側は「書いている途中を読まれては困る」ので行を押さえます。どちらも相手を待たせるので、長く読む処理が 1 本あるだけで書き込みが渋滞します。

古い値を捨てなければ、どちらも待たなくてよい

止まる理由は、1 行につき値が 1 つしかないことです。書き換えたら前の値が消えるので、読み手を待たせるしかありません。

そこで、更新のときに古い値を消さず、新しい値を別に足します。それぞれの版には「いつ作られたか」と「いつ消されたか」に相当する印が付いていて、読み手は自分が始めた時点を基準に、そのとき生きていた版を選びます。書き手は新しい版を足すだけなので、読み手を待たせません。読み手も、自分の版が残っている限り待ちません。これがマルチバージョン同時実行制御 (MVCC) です。

プレーンテキスト

時刻 10  T1 が開始
時刻 11  T2 が残高を 5000 から 8000 に更新して COMMIT
時刻 12  T1 が残高を読む  ->  5000(T1 が始まった時点の版)
時刻 13  T3 が開始して読む -> 8000

前の回で Repeatable Read を「自分が始めた時点の景色が固定される」と書きましたが、その固定はこの仕組みで実現されています。どの版を選ぶかはトランザクション単位で決まるので、読むだけの処理でも BEGIN で括る意味があります。括らずに 3 本の SELECT を投げれば、3 本がそれぞれ別の時点の景色を見ることになります。

ただし待たなくてよいのは読みだけです。同じ行を 2 本が更新しようとすれば、後から来た方は待たされます。読んだ値をもとに書き換える処理で、先に順番を押さえておきたいときは SELECT ... FOR UPDATE を使います。

古い版は、勝手には消えない

代償は、消したはずのデータがディスクに残り続けることです。どの版も、まだ読んでいるトランザクションがいるかもしれないので、その場では捨てられません。

回収は後片付けの処理が担当します。PostgreSQL では VACUUM、MySQL では取り消し用ログの整理がそれにあたります。問題は、開きっぱなしのトランザクションが 1 本でもあると、その開始時点より新しい版を捨てられないことです。

朝から放置された接続が 1 本あるだけで、その日 1 日ぶんの古い版が丸ごと残ります。テーブルの実サイズが行数の何倍にも膨らみ、読み取りまで遅くなります。「トランザクションは短く」が繰り返し言われるのは、待たせないためだけではありません。

犯人は探せば見つかります。PostgreSQL なら pg_stat_activity で、開いたまま idle in transaction で止まっている接続を確認します。多くは、アプリが例外で抜けたときに COMMIT も ROLLBACK も通らず、接続だけが返却されずに残っているケースです。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • テーブルDB の表 (Excel のシートみたいなもの)
  • 処理計算や代入を表す長方形
  • トランザクション「全部成功 or 全部なかったことに」をまとめる単位
  • PostgreSQL機能が豊富なオープンソースのRDBMS
  • MySQL広く使われるオープンソースのRDBMS
  • branchGit で開発するときに毎日打つ 5 つの基本コマンド
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/27·更新 2026/08/26

関連レッスン

  • デッドロックと回避

    複数トランザクションが互いのロックを待ち続けるデッドロックが起きる原理と、DBMS の検出の仕組み、アプリ側で予防する設計原則を実務目線で解説します。

  • クエリプランナの役割

    SQL から実行計画が生成される過程を追う

  • レプリケーション

    Primary / Replica 構成での読み取り分散と整合性

分からないところは Tap (AI先生) に質問できます

24 時間いつでも、あなたのレベルに合わせて日本語で答えます。