忍者ブログ
データベースエンジニアのための実践ブログ。Oracle・PostgreSQL・MySQLなどの環境構築、実行計画の読み方やチューニングといった現場で役立つノウハウ、DB基礎知識までを発信しています。

【データベースの基礎】データ損失を防ぐ生命線!「ログ先行書き込み(WAL / コミットログ)」の仕組みと役割

データベースシステムにおいて、障害が発生してもデータを安全に復旧(リカバリー)できるのはなぜだろうか。
その中心にあるメカニズムが「ログ先行書き込み(WAL: Write-Ahead Logging)」(あるいはコミットログ)である。

今回は、ログ先行書き込みの基本的な概念から、その必要性、内部の仕組み、代表的な採用製品、そしてメリット・デメリットまでをわかりやすく整理した。


1. ログ先行書き込み(WAL)とは?基本概念

データベースでは、パフォーマンスを向上させるために、変更されたデータ(更新内容)をまず高速なメモリ(バッファ)上で処理し、実際のストレージ(ディスク)への書き込みは後回し(遅延書き込み)にしている。

しかし、ディスクに書き込まれる前にサーバーの電源が落ちたり障害が発生したりすると、メモリ上のデータは消えてしまう。
これを防ぐため、「データ本体をディスクに書き込む前に、変更履歴(ログ)を必ず安全なストレージに順次書き込んでおく」という仕組みがWALである。


2. なぜWALが必要なのか?(仕組みと目的)

データベースの信頼性を保つ上で、WALには主に2つの重要な目的がある。

  • ① クラッシュリカバリー(障害からの復旧)
    突然のサーバーダウン時、ディスク上のデータファイルは中途半端な状態になっている可能性がある。このときWAL(変更ログ)を参照し、未完了の処理をロールバックしたり、完了していてディスクに反映されていなかった処理を再適用(リドゥ)することで、データを一貫性のある正しい状態に戻す。
  • ② トランザクションの耐久性(Durability)保証
    ACID特性の「D(Durability)」を担保する。アプリケーションが「コミット(保存)」を要求した際、重いデータファイルを直接ディスクに書き込むのではなく、軽量なログ領域へ確実に書き終えた時点で「保存完了」と応答できるため、高速かつ安全な処理が可能になる。

3. どんな製品で採用されている?(Oracleとの違い)

「WAL」という名称や概念は、多くのオープンソースデータベースや分散データベースで標準的に採用されている。

  • ・PostgreSQL: そのまま「WAL(Write-Ahead Log)」と呼ばれる仕組みで実装されており、アーキテクチャの根幹をなしている。
  • ・SQLite: 「WALモード」を有効にすることで、並行処理性能と安全性を飛躍的に向上させることができる。
  • ・MySQL (InnoDB): 「Redoログ(Redo Log)」と呼ばれる仕組みを採用しており、概念としてはWALと同等である。

Oracle Databaseの場合は?

質問にもある通り、Oracle Databaseでは「WAL」という用語は一般的に使われない。代わりに、同様の目的を持つ仕組みとして「Redoログ(Redo Log / Redoログファイル)」や、変更ベクトルを管理する「LGWR(ログライター)プロセス」が稼働している。用語やアーキテクチャの表現は異なるが、「変更を先にログへ書き込んでからデータファイルを更新する」という根本的な思想は同一である。


4. WALのメリット・デメリット

メリット
  • 書き込みパフォーマンスの向上: ランダムアクセスとなる重いデータファイルの更新を遅延させ、シーケンシャルにログへ追記することでI/Oを高速化できる。
  • 高い信頼性と復旧力: 突然の電源断やクラッシュがあっても、ログから正確にデータを復元できる。
  • レプリケーションへの応用: ログをそのままスタンバイサーバーへ転送・適用することで、手軽に高可用性(HA)構成や読み取り専用レプリカを構築できる。
デメリット・注意点
  • ストレージ容量の圧迫: 更新が頻繁なシステムではログが急速に肥大化するため、適切なローテーションや定期的なバックアップ(アーカイブ)が不可欠。
  • I/Oボトルネックの懸念: コミットのたびにログの物理的なディスク書き込み(フラッシュ)を待つため、ストレージの書き込み性能(特にIOPSやレイテンシ)が全体の性能を大きく左右する。

5. まとめ

ログ先行書き込み(WAL / Redoログ)は、データベースの「スピード」と「安全性」を両立させるための最も重要なアーキテクチャである。
普段何気なく発行している COMMIT の裏側では、このログへの書き込みが確実に行われることで、私たちのデータが守られている。

【エンジニアの押さえどころ】
✔ データ本体の書き込みよりも「ログへの書き込み」が先に行われる(これがWALの名前の由来)。
✔ PostgreSQLなどのOSSでは「WAL」、Oracleでは「Redoログ」と呼ばれるが、果たす役割は同じ。
✔ トランザクション性能や障害復旧をチューニングする際は、ログ出力先ストレージのパフォーマンスが鍵となる。
PR

【データベース内部構造】SQLはどう処理される?クエリ実行の内部プロセスと最適化の流れ

SQL文を発行した際、データベース(RDBMS)内部ではどのような処理が行われているのだろうか。
SQLは「どのようなデータを取得・更新したいか」という宣言的な記述を行う言語であり、「具体的にどのようにデータを取得するか」という手順はRDBMS内部の処理エンジンが自動的に判断している。

今回は、SQLが投入されてから結果が返されるまでの内部ステップと、効率的な実行処理を行うための「クエリ最適化(Query Optimization)」の流れを整理した。


1. SQL処理の5つのステップ

一般的なRDBMSにおいて、SQL文は主に以下の5つの段階を経て実行される。

  • ① Parsing(構文解析)
    送られてきたSQLの文法的な正しさ(シンタックスチェック)を解釈・検証する。
    SQL実行後の最初のプロセスとして、Parser(構文解析器)がSQLのロジカルな構造を関係演算を表す「Query Tree(クエリツリー)」へ変換する。
  • ② Query Validation(クエリ検証・意味解析)
    SQL内に指定されたテーブルや列(カラム)がデータベース上に実際に存在するか、アクセス権限があるかなどの「意味的妥当性」を検証する。
  • ③ Optimization(最適化 / クエリ最適化)
    関係演算を表す Query Tree を、実際のアクセス手順である「物理的な実行プラン(Execution Plan)」へ変換する。
    通常、データ取得の手順には複数のバリエーション(多くのプラン)が存在するため、その中で最も効率が良い(低コストな)実行プランを選択する。
  • ④ Plan Compile(プランコンパイル)
    クエリオプティマイザ(Query Optimizer)によって選択された最適な計画を、実行エンジンが直接処理できるマシンコードや内部コマンド形式へコンパイル・変換する。
  • ⑤ Execution(実行)
    Query 実行エンジン(Execution Engine)が物理プランに従ってストレージやキャッシュメモリからデータを読み書きし、最終的な結果をクライアントへ返す。

2. クエリ最適化(Query Optimization)の役割

SQLの処理工程の中で、パフォーマンスを決定づける最も重要なコンポーネントが「クエリオプティマイザ(Query Optimizer)」である。

【クエリ最適化の仕組みとポイント】

■ 物理プランの大量生成
1つのSQLに対して、「フルスキャンをするか / インデックスを使うか」「テーブル結合の順序をどうするか」「ハッシュ結合かループ結合か」など、多数の物理プラン候補が生成される。

■ コスト評価(Cost-Based Optimization)
オプティマイザは統計情報(データ件数、インデックスのカーディナリティ、データ配置など)を参照し、推定実行時間やI/Oコストなどの「いろいろな値」から最適なプランを算出・算出決定する。

■ 実行エンジンへの受け渡し
最小コストと判定された計画(最適プラン)のみが選択され、Query 実行エンジンに渡されて高速な処理が実現される。

3. まとめ

SQLは「データ取得の結果」を指示するだけで、裏側ではParser(構文解析器)による Query Tree の生成と、Query Optimizer(最適化エンジン)による物理実行プランの決定という高度な処理が自動的に行われている。

SQLパフォーマンスチューニングにおいては、オプティマイザが意図通りの最適な実行プランを選択できるよう、「最新の統計情報(Statistics)の維持」や「適切なインデックス設計」を行うことが重要となる。

【SQL実行プロセスから見るチューニングのポイント】
✔ プレースホルダ(バインド変数)を使い、Parsing・Plan Compileの再利用(ハードパース削減)を狙えているか?
✔ テーブル統計情報は最新に更新されているか?(古い統計情報だとオプティマイザが間違ったプランを選ぶ)
✔ EXPLAIN / AUTOTRACE 等で最適化された物理実行プランを分析しているか?

【データベース】データの信頼性を守る命綱!トランザクションの「ACID特性」とは

データベース(RDBMS)を扱う上で、絶対に避けて通れない最重要概念が「トランザクション(Transaction)」である。
銀行の口座振込やECサイトの注文処理など、複数のデータ更新を「1つの不可分な処理単位」として扱う仕組みを指す。

そして、このトランザクション処理が安全かつ正確に行われるために、RDBMSが保証すべき4つの性質の頭文字をとったものが「ACID(アシッド)特性」だ。
今回は、システム開発やデータベース設計の基本となるACID特性をわかりやすく整理した。


1. ACID特性の4つの要素

データベースのデータ破壊を防ぎ、整合性を完璧に保つためにRDBMSが備えるべき4つの原則は以下の通りである。

  • A:Atomicity(原子性 / All or Nothing)
    トランザクションに含まれる一連のデータ操作は、「すべて完全に実行される(Commit)」か「まったく実行されなかった状態に戻る(Rollback)」かのどちらか一方にしかならない性質。
    途中でエラーやシステム障害が発生した場合、中途半端に一部だけが更新された状態が残ることは絶対にない。
  • C:Consistency(一貫性 / 整合性)
    トランザクションの開始前と終了後で、データベースの整合性制約(主キー制約、外部キー制約、NOT NULL制約など)が常に満たされている性質。
    ルールに違反するような不正なデータ変更が行われそうになった場合、トランザクション全体が自動的に取り消される。
  • I:Isolation(独立性 / 隔離性)
    複数のトランザクションが同時に並行実行されていても、互いの処理過程が干渉・影響し合わない性質。
    他のトランザクションからは「まだ確定していない途中の状態」が見えず、あたかも1つずつ順番に実行(直列化)されたかのような結果が保証される。
  • D:Durability(永続性 / 堅牢性)
    トランザクションが一度確定(Commit)または取消(Rollback)した時点で、その結果は永続的に記憶され、絶対に失われない性質。
    確定直後にサーバーの電源が落ちたりシステム障害が発生したりしても、REDOログ等の仕組みによってデータは確実に復元される。

2. 具体例:銀行の口座振込で考えるACID

「Aさんの口座からBさんの口座へ1万円を振り込む」というトランザクション(①A口座から1万円引く ➔ ②B口座に1万円足す)を例に挙げると、ACID特性の重要性がより明確になる。

【振込処理におけるACIDの役割】
・原子性: ①のあと回線が切れても、B口座に足されずにA口座の1万円だけ消える(消滅する)事故を防ぐ(ロールバックされる)。
・一貫性: 残高がマイナス不可の制約がある場合、残高不足なら振込処理自体をエラーにして弾く。
・独立性: Aさんが振込処理を行っている最中に、CさんがAさんの残高を参照しても「振込途中の確定していない残高」は見えない。
・永続性: 「振込完了」の画面が出た直後に銀行のDBサーバーが停電しても、1万円の移動記録は消えずに残る。

3. まとめ

Webアプリケーションや基幹システムにおいて、データの辻褄が合わなくなるバグを防いでいるのは、RDBMSが提供するこのACID特性のおかげである。

システム設計時には、特に「隔離性(Isolation)レベルの設定(Dirty ReadやPhantom Readの防犯)」や「デッドロックの防止」など、ACID特性を意識したトランザクション設計を行うことが求められる。

【トランザクション設計のチェック項目】
✔ 複数の更新クエリが「1つのトランザクション」としてコミット/ロールバック制御されているか?(原子性)
✔ アプリ側の処理異常時に確実に ROLLBACK が発行される構造になっているか?(一貫性)
✔ 同時実行時のロック範囲や分離レベル(Read Committed等)が適切に設計されているか?(独立性)

【データベースの知識】現代のRDBの原点!コッドの12のルール(Codd's 12 Rules)とは

リレーショナルデータベース(RDB)の基礎理論を考案した Edgar F. Codd(エドガー・F・コッド)博士が1985年に提唱した「コッドの12のルール(Codd's 12 Rules)」。
「真のリレーショナルデータベース管理システム(RDBMS)とはどうあるべきか」を定義した指針であり、データベースの運用や基本設計、情報処理試験の理論問題においても極めて重要な概念となっている。

今回は、データベースを正しく管理・運用するためにRDBMSが備えるべき12の原則をわかりやすく整理した。


1. コッドの12のルール(RDBMSの要件定義)

コッド博士は、システムが独自の拡張や物理的な制約に頼らず、純粋に「リレーショナルモデル」としてデータの一貫性・独立性を保つために以下の12原則(および原則0である「完全なリレーショナル機能による管理」)を定めた。

  • ① 情報の表現原則(Information Rule)
    テーブル名や列名、制約といったメタデータを含め、データベース内のすべての情報は「表(リレーション)のセルに格納された値」として一元的に記録されなければならない。
  • ② アクセスの保証(Guaranteed Access Rule)
    すべてのデータ要素は、「テーブル名」「主キー(Primary Key)の値」「列(ドメイン)名」の組み合わせによって論理的に一意指定してアクセス可能でなければならない(物理アドレスやポインタの指定は不可)。
  • ③ NULLの統一的扱い(Systematic Treatment of Null Values)
    「値が存在しない(未知)」「適用不能」を表す NULL は、データ型に関わらず、システム全体で統一かつ体系的な方法で処理されなければならない。
  • ④ オンライン・アクティブ・カタログ(Dynamic Online Catalog)
    データベース構造を保持するカタログ(データディクショナリ)自体も通常のデータと同じ表形式で表現され、通常のSQL等のデータアクセス言語を使ってオンラインで照会できなければならない。
  • ⑤ 包括的なデータ言語の原則(Comprehensive Data Sublanguage Rule)
    データの定義(DDL)、ビューの定義、データの操作(DML)、整合性制約、トランザクション制御(COMMIT/ROLLBACK)などが、単一の明確に定義された言語(SQLなど)で完結して実現できなければならない。
  • ⑥ ビューの更新原則(View Updating Rule)
    理論的に更新可能なビューに対して更新(INSERT / UPDATE / DELETE)が発行された場合、RDBMSがそれを検知し、裏側にある実表(基底テーブル)に対して正しく更新処理を反映しなければならない。
  • ⑦ 高水準の挿入・更新・削除(High-Level Insert, Update, and Delete)
    データ操作言語は、一度の命令(クエリ)で1行ずつ処理するのではなく、複数の行(タプル/集合)をひと括りで集合処理できなければならない。
  • ⑧ 物理的データ独立性(Physical Data Independence)
    データの記憶形式やアクセスパス(インデックス構造やファイルの配置場所など)といった物理的な変更を行っても、アプリケーションプログラムのコードに影響を与えてはならない。
  • ⑨ 論理的データ独立性(Logical Data Independence)
    テーブルの分割・結合など、データベースの論理構造を変更した場合でも、既存のアプリケーションプログラムへの影響を最小限に抑えられなければならない(ビュー等の活用)。
  • ⑩ 整合性制約の独立性(Integrity Independence)
    主キー制約や外部キー制約などのデータ整合性制約は、アプリ側のプログラム内に記述するのではなく、RDBMS内のカタログに直接定義・保持されなければならない。制約が変更されてもアプリ側に影響を与えない。
  • ⑪ 分散の独立性(Distribution Independence)
    データベースが複数のサーバやネットワーク上に分散配置されたとしても、アプリケーション側からはあたかも単一のローカルデータベースを操作しているように見えなければならない(位置の透過性)。
  • ⑫ 規約無効化の否定(Non-Subversion Rule)
    RDBMSに低水準(レコード単位など)のインターフェースが存在する場合でも、その経路を使ってRDBMSに定義された整合性制約やセキュリティ規約を回避・破壊できてはならない。

2. まとめ:現代RDBMSにおける位置づけ

コッドの12のルールは、SQLデータベースの理想型を示した厳格な基準である。現実の主要なRDBMS(Oracle、PostgreSQL、MySQL、SQL Serverなど)であっても、これら12のルールを完全(100%)に満たしている製品は少ない。

しかし、「物理データからの独立」「集合操作」「整合性制約のRDBMS側での一元管理」といった根幹のコンセプトは、現代のデータベース設計やアプリケーション開発においても変わらない基礎知識として息づいている。

【データベース設計・運用のチェック項目】
✔ アプリケーション側に整合性チェックのロジックを抱え込みすぎていないか?(ルール10)
✔ 物理的なインデックス追加・変更がアプリ側に波及しない構造になっているか?(ルール8)
✔ NULLの判定ロジックがシステム全体で統一されているか?(ルール3)

【データベース】実行計画の要!「オプティマイザー」の役割と2つのアプローチ

リレーショナルデータベース(RDB)に対してSQL文を発行する際、私たちは「どのようなデータを満たすか(WHAT)」だけを指定し、「どのようにデータを取得するか(HOW)」の手順は記述しない。
この「どのようにデータを取得するか」という具体的なアクセス経路(実行計画)を裏で自動的に導き出しているのが、DBMSの心臓部である「オプティマイザー(最適化エンジン)」である。


1. オプティマイザーとは

データベースアクセスを最適化する仕組み、およびそのシステムをオプティマイザーと呼ぶ。

オプティマイザーは、ユーザーから送られてきたSQL文を構文解析(パース)し、テーブルの構造やインデックスの有無を分析する。その後、内部で複数の実行計画(プラン)を組み立て、その中から最も効率が良いと判断したアクセス経路を検出して実行に移す役割を担っている。


2. オプティマイザーの2つの種類

SQL文の実行計画を選択・決定する手法には、歴史的な経緯やアプローチの違いにより、大きく分けて次の2種類が存在する。

(1)ルールベース・オプティマイザー(RBO)

ルールベースのオプティマイザーは、データの量や状態に関わらず、あらかじめシステムに組み込まれた固定の優先順位(ルール)に則って、機械的に実行計画を決定する。

一般的には、以下のようなアクセス・パス(経路)の優先順位が定義されており、より上位の条件にマッチするインデックス等があれば、それを優先的に選択する。

  • (ア)ユニーク・キーまたは主キーによる単一行アクセス(最優先)
  • (イ)インデックス付きのクラスター・キー
  • (ウ)複合インデックス(複数カラムを組み合わせたインデックス)
  • (エ)単一カラム・インデックス
  • (オ)ソート/マージ結合
  • (カ)インデックス付きカラムの MAX または MIN 関数
  • (キ)インデックス付きカラムの ORDER BY
  • (ク)テーブル全体のスキャン(フルスキャン)(最も優先順位が低い)

(2)コストベース・オプティマイザー(CBO)

現在の主要なDBMS(Oracle、PostgreSQL、MySQL、SQL Serverなど)で主流となっているのが、このコストベースである。
あらかじめデータベース内に収集・蓄積されている、テーブルのレコード数、カラムの平均長、インデックスの深さ、データの分布度といった「統計情報」を基にする。

オプティマイザーは内部で複数の実行計画をシミュレーションし、それぞれのパターンで発生する「コスト」を計算して、最もコストが低いプランを採用する。

※ここでいう「コスト」とは、SQL文を実行するために必要と予測される、CPU処理時間やディスクI/O(読み書き)の経過時間に比例する見積値のことである。データ量が少なければフルスキャンを選び、データ量が多ければインデックスを選ぶ、といった柔軟な判断が可能となる。


3. まとめ

ルールベースは「構造」だけで判断するためデータ量の変化に弱く、現代の複雑なシステムでは不都合が生じやすい。そのため、現在のRDB運用においては、定期的に ANALYZE などのコマンドを実行して最新の「統計情報」を維持し、コストベース・オプティマイザーに正しい判断をさせることが、パフォーマンス管理における最大の鉄則となっている。

【オプティマイザー運用のチェック項目】
□ 意図しないフルスキャン(テーブル全体スキャン)が発生していないか?
□ 大規模なデータ更新(バッチ処理等)のあとに統計情報を更新しているか?
□ 期待通りのインデックスアクセスが選択されるよう、実行計画(EXPLAIN)を確認したか?
        
  • 1
  • 2
  • 3