はじめに
MariaDB は MySQL から分岐したオープンソースのリレーショナルデータベースです。当初は MySQL とほぼ同じコードを共有していましたが、時間とともに独自のストレージエンジン、レプリケーション方式、クラスタリング技術を発展させてきました。そのため「MySQL と互換性のある何か」という程度の理解にとどまっていると、実際の運用環境で出会うさまざまな選択肢や動作の違いをきちんと扱うのが難しくなります。
この記事では、MariaDB のアーキテクチャを上から下へとたどっていきます。まず、クライアントのリクエストが入ってきて SQL が解析され、オプティマイザーが実行計画を立て、実際にデータを読み書きするストレージエンジンに到達するまでの全体の流れを描きます。次に InnoDB、Aria、ColumnStore、MyRocks といったストレージエンジンを比較し、データを複数ノードに広げる方法を、非同期レプリケーションから準同期、GTID、そして Galera 同期マルチマスタークラスターまで見ていきます。最後にパーティショニングと、運用時によく出会う落とし穴を整理します。
バージョンによってデフォルト値やサポート有無が変わることがあるため、具体的な数値や機能については、常にご利用中のバージョンの公式ドキュメントを確認することをおすすめします。この記事は大きな絵と概念をつかむことに焦点を当てます。
サーバーアーキテクチャ全体
MariaDB サーバーは大きく 2 つの層に分けて考えると理解が早いです。上側は SQL を解釈して実行計画を立てる **SQL 層(サーバー層)** で、下側は実際にデータをディスクに保存して読み出す **ストレージエンジン層** です。この 2 つを分離したことが、MySQL 系統の最も重要な設計上の特徴です。
クライアント (アプリ / mysql CLI / コネクタ)
│
▼
┌───────────────────────────────────────────────────┐
│ Connection Layer │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Thread Pool │ │ 認証 │ │ セッション │ │
│ │ │ │ │ │ / 権限 │ │
│ └─────────────┘ └──────────────┘ └───────────┘ │
└───────────────────────────┬───────────────────────┘
│
▼
┌───────────────────────────────────────────────────┐
│ SQL Layer │
│ ┌────────┐ ┌────────┐ ┌──────────┐ ┌───────┐ │
│ │ Parser │──▶│Rewrite │──▶│Optimizer │─▶│ Plan │ │
│ └────────┘ └────────┘ └──────────┘ └───┬───┘ │
│ │ クエリキャッシュ(あれば) / 権限確認 │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Executor │ │
│ └───────────────────────┬──────────────────────┘ │
└──────────────────────────┼─────────────────────────┘
│ Storage Engine API (handler)
▼
┌───────────────────────────────────────────────────┐
│ Storage Engine Layer │
│ ┌────────┐ ┌──────┐ ┌────────────┐ ┌────────┐ │
│ │ InnoDB │ │ Aria │ │ ColumnStore│ │MyRocks │ │
│ └────────┘ └──────┘ └────────────┘ └────────┘ │
└───────────────────────────────────────────────────┘
│
▼
データファイル / ログ / インデックス
各段階が何をするのかを見ていきます。
接続層 (Connection Layer)
クライアントが接続すると、サーバーはまず接続を受け入れて認証を処理します。ユーザー名、パスワード、接続元ホスト、権限を確認し、セッション単位の変数とコンテキストを準備します。
MariaDB は接続ごとにスレッドを割り当てる従来の方式と、**スレッドプール(thread pool)** 方式の両方をサポートします。接続が多く、短いクエリが頻繁な環境では、スレッドプールがコンテキストスイッチのコストとメモリ使用を減らしてくれます。同時に数千もの接続を扱う必要があるワークロードであれば、スレッドプールを検討する価値があります。
SQL 層 (Parser · Optimizer · Executor)
接続が確立すると、入ってきた SQL 文字列は次の段階を経ます。
1. **パーサー(Parser)**: SQL 文字列をトークンに分割し、文法を検査して内部の構文木にします。文法エラーはここで取り除かれます。
2. **前処理 / リライト(Preprocess · Rewrite)**: ビューを展開したり、一部のサブクエリをジョインに変換したりして、オプティマイザーが扱いやすい形に整えます。
3. **オプティマイザー(Optimizer)**: コストベースで、複数の実行方法のうち最も安いと推定される計画を選びます。どのインデックスを使うか、ジョインの順序をどうするか、一時テーブルやソートが必要かを決めます。
4. **エグゼキューター(Executor)**: 確定した計画に従ってストレージエンジン API を呼び出し、実際に行を読み書きします。
オプティマイザーはテーブルの統計情報(行数、インデックスの選択度など)に依存します。統計が古かったり不正確だったりすると誤った計画を選ぶことがあるため、運用では統計の更新が重要です。
ストレージエンジン層
エグゼキューターはデータを直接触りません。代わりに **ハンドラー(handler)API** という一貫したインターフェースを通じて、ストレージエンジンに「この条件に合う次の行をくれ」「この行を書け」といったリクエストを送ります。これによって、同じ SQL でもテーブルがどのエンジンを使うかによって、トランザクションのサポート有無、ロック方式、ディスクレイアウトが完全に変わります。
この分離のおかげで、1 つのデータベースの中でテーブルごとに異なるエンジンを混ぜて使えます。たとえば、トランザクションが重要な注文テーブルは InnoDB に、大量集計分析用のテーブルは ColumnStore に置く、といった具合です。
ストレージエンジンを深く見る
ストレージエンジンは MariaDB アーキテクチャの核心です。各エンジンは異なるワークロードに最適化されています。
InnoDB
InnoDB はほとんどの OLTP(オンライントランザクション処理)ワークロードのデフォルトの選択肢です。次のような特徴を持ちます。
- **ACID トランザクション**: コミット、ロールバック、分離レベルをサポートします。
- **行単位ロック(row-level locking)**: 同時実行性が高い環境で、テーブル全体ではなく必要な行だけをロックします。
- **MVCC(多版型同時実行制御)**: 読み取りと書き込みが互いをあまりブロックしないよう、読み取りは特定時点の一貫したスナップショットを見ます。
- **クラスタ化インデックス(clustered index)**: データが主キー順に物理的に並んで保存されます。そのため主キーの設計が性能に大きく影響します。
- **クラッシュリカバリ**: REDO ログを通じて、異常終了の後でも一貫性を回復します。
InnoDB の内部動作を単純化すると次のようになります。
書き込みパス (単純化)
COMMIT ──▶ REDO ログ記録(WAL) ──▶ バッファプールのページ修正
│ │
│ (ディスクに先に) │ (メモリ上の dirty page)
▼ ▼
ログファイル バッファプール(メモリ)
│
│ チェックポイント / 背景 flush
▼
データファイル(.ibd)
ここで核となる概念が **WAL(Write-Ahead Logging)** です。データページをディスクに即座に書く代わりに、変更内容をまず REDO ログに順次記録します。順次書き込みはランダム書き込みよりはるかに速く、もしサーバーが突然落ちても REDO ログを再生して復旧できます。
**バッファプール(buffer pool)** は InnoDB がデータとインデックスのページをキャッシュしておくメモリ領域です。ワーキングセットがバッファプールに収まると、ディスク I/O が大きく減るため、バッファプールのサイズは InnoDB の性能チューニングで最も重要な項目の 1 つです。
Aria
Aria は MyISAM の後継として開発されたエンジンです。クラッシュリカバリができる点で MyISAM より安全です。MariaDB の内部でシステムテーブルや一時テーブルの用途で使われることもあります。ただし InnoDB 並みの完全なトランザクションや行ロックは提供しないため、同時書き込みが多い一般的な OLTP テーブルには InnoDB のほうが適しています。
ColumnStore
ColumnStore は分析(OLAP)ワークロードのための **カラム指向(columnar)** エンジンです。従来の行指向の保存方式とは異なり、同じカラムの値をまとめて保存します。
行指向 (InnoDB) カラム指向 (ColumnStore)
[id|name|amount|date] id : 1,2,3,4,...
[ 1|kim | 100 |...] name : kim,lee,park,...
[ 2|lee | 250 |...] amount : 100,250,90,...
[ 3|park| 90 |...] date : ...
1 行を丸ごと読む 特定のカラムだけ読む
集計クエリ(たとえば特定カラムの合計や平均)は必要なカラムだけ読めばよいため I/O が大きく減り、同じカラム同士が集まっているので圧縮率も高くなります。一方で、1 件ずつ頻繁に更新する OLTP パターンには向きません。大容量データをスキャンして集計する分析システムに適しています。
MyRocks
MyRocks は RocksDB ベースの **LSM ツリー(Log-Structured Merge-tree)** エンジンです。B ツリーベースの InnoDB とは書き込み処理の方式が根本的に異なります。
- **書き込み増幅(write amplification)が低い**: LSM 構造は書き込みを順次まとめて処理するため、特定のワークロードでディスクに実際に書かれる量が減ります。
- **高い圧縮率と容量効率**: 同じデータをより少ない容量に保存する傾向があり、保存コストが重要な大容量環境に有利です。
- **読み取り時のトレードオフ**: LSM 構造の特性上、読み取りパスが複数のレベルを経ることがあり、ワークロードによって読み取りコストが変わります。
書き込みが非常に多く、保存容量を節約する必要のある環境で、InnoDB の代替として検討されます。
ストレージエンジンの選択基準(比較表)
| 項目 | InnoDB | Aria | ColumnStore | MyRocks |
|------|--------|------|-------------|---------|
| 主な用途 | 汎用 OLTP | システム/一時テーブル | 分析 OLAP | 書き込み多い大容量 |
| トランザクション(ACID) | 完全サポート | 限定的 | 分析中心 | サポート |
| ロック単位 | 行単位 | テーブル中心 | 分析中心 | 行単位 |
| 保存構造 | B ツリー | B ツリー | カラム指向 | LSM ツリー |
| 圧縮 | オプション | 限定的 | 強い | 強い |
| 強み | バランス、同時実行 | 軽量 | 集計スキャン | 書き込み、容量効率 |
| 弱み | 容量使用 | 同時書き込み | 単件更新 | 読み取りトレードオフ |
選択の出発点はほぼ常に InnoDB です。トランザクションと同時実行性、安定性のバランスが良いからです。ColumnStore と MyRocks は「このワークロードが InnoDB の弱点を正確に突いている」という確信があるときに導入を検討するのが安全です。サポートされるエンジンの一覧やデフォルトで有効かどうかは、バージョンやビルドによって異なることがあるため、公式ドキュメントで確認してください。
インストール済みのエンジンを確認する方法は次のとおりです。
-- 利用可能なストレージエンジンとサポート状態を確認
SHOW ENGINES;
-- 特定のテーブルがどのエンジンを使うか確認
SELECT table_name, engine
FROM information_schema.tables
WHERE table_schema = 'mydb';
-- テーブル作成時にエンジンを指定
CREATE TABLE orders (
id BIGINT NOT NULL AUTO_INCREMENT,
user_id BIGINT NOT NULL,
amount DECIMAL(12,2) NOT NULL,
created DATETIME NOT NULL,
PRIMARY KEY (id),
KEY idx_user (user_id)
) ENGINE=InnoDB;
レプリケーション
1 台のサーバーだけでは可用性と読み取りスケーリングに限界があります。レプリケーションは、あるサーバー(プライマリ/マスター)の変更を別のサーバー(レプリカ/スレーブ)に届けて同じデータを保つ技術です。
MariaDB レプリケーションの中心には **バイナリログ(binary log, binlog)** があります。プライマリはデータを変更するすべての操作を binlog に記録し、レプリカはこのログを受け取って自分のデータに再適用します。
┌────────────── Primary ──────────────┐
│ トランザクション ──▶ ストレージエンジン│
│ │ │
│ └──▶ Binary Log (binlog) 記録 │
└──────────────────┬───────────────────┘
│ binlog イベント送信
▼
┌────────────── Replica ───────────────┐
│ IO スレッド ──▶ Relay Log に保存 │
│ │ │
│ SQL/Worker スレッド ─▶ データに適用 │
└──────────────────────────────────────┘
レプリカ側の動作をもう少し詳しく見ると、**IO スレッド** がプライマリから binlog イベントを受け取ってローカルの **リレーログ(relay log)** に保存し、**SQL スレッド(または並列ワーカー)** がリレーログを読んで実際のデータに適用します。
非同期レプリケーション (Asynchronous)
デフォルトのレプリケーション方式は **非同期** です。プライマリはトランザクションをコミットすると即座にクライアントに成功を返し、レプリカがその変更を受け取って適用したかは待ちません。
- **利点**: プライマリの書き込み遅延がレプリカの影響を受けないため、速いです。
- **欠点**: プライマリがコミット直後に落ちると、まだレプリカへ渡せていないトランザクションが消えることがあります(データ消失の可能性)。また、レプリカがプライマリより遅れる **レプリケーション遅延(replication lag)** が生じることがあります。
準同期レプリケーション (Semi-synchronous)
準同期レプリケーションは非同期と同期の折衷案です。プライマリがコミットをクライアントに確定する前に、**少なくとも 1 つのレプリカがそのイベントを受け取ったという確認(ack)** を待ちます。
ここで重要なのは、これはレプリカがイベントを **適用した** という保証ではなく、**受信してリレーログに安全に書き込んだ** という保証である点です。それでも、プライマリだけがデータを持つ状況を減らすため、非同期よりデータ消失のリスクは小さくなります。その代わり、レプリカの ack を待つ分だけコミット遅延が増えます。
GTID (Global Transaction ID)
従来のレプリケーションは「binlog ファイル名とその中の位置(オフセット)」でどこまで複製したかを追跡していました。この方式はフェイルオーバー(障害時に別サーバーへ昇格)の際に位置を正確に合わせるのが難しいものでした。
**GTID** はすべてのトランザクションにクラスター全体で一意な識別子を付ける方式です。これによってレプリカは「自分がどのトランザクションまで適用したか」を位置ではなく ID で知ることができ、プライマリが変わっても抜けたトランザクションを明確に引き継げます。フェイルオーバーやトポロジー変更がはるかに容易になります。
レプリケーション状態を確認し、GTID ベースでレプリケーションを開始する例は次のとおりです(構文はバージョンによって異なることがあります)。
-- レプリカでレプリケーション状態を確認
SHOW REPLICA STATUS\G
-- GTID ベースのレプリケーション設定例
CHANGE MASTER TO
MASTER_HOST='primary.example.internal',
MASTER_USER='repl',
MASTER_PASSWORD='secret',
MASTER_USE_GTID=slave_pos;
START REPLICA;
Galera クラスター (同期マルチマスター)
これまでのレプリケーションは、プライマリ 1 台が書き込みを受け、残りが追従する構造でした。**Galera クラスター** は違います。すべてのノードが読み取りと書き込みの両方を受けられる **同期マルチマスター** 方式です。
アプリケーション / ロードバランサ
/ | \
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Node A │◀─▶│ Node B │◀─▶│ Node C │
│ (R/W) │ │ (R/W) │ │ (R/W) │
└──────────┘ └──────────┘ └──────────┘
▲ ▲ ▲
└───────── wsrep グループ通信 ──┘
(コミット時に write-set を全ノードへ伝播/認証)
Galera の核心は、コミット時点で起こる **認証ベースのレプリケーション(certification-based replication)** です。流れを単純化すると次のようになります。
Galera コミットの流れ (単純化)
1) クライアントが Node A でトランザクションを実行
│
▼
2) コミット直前に変更内容を write-set にまとめる
(変わった行とそのキー情報)
│
▼
3) write-set を全ノードへブロードキャスト
│
▼
4) 各ノードが同じ順序で認証(certification)を実施
- 他ノードの同時トランザクションと衝突するか?
│
├── 衝突なし ──▶ 全ノードがコミット (一貫した状態)
│
└── 衝突あり ──▶ 後のトランザクションを拒否(ロールバック)
→ アプリにデッドロック類似のエラー
ここで「同期」という言葉の意味を正確に理解することが重要です。Galera はコミット時点で write-set を全ノードに伝播し認証を通すため、コミットが成功すれば、そのトランザクションはクラスター全体に反映されることが保証されます。ただし、実際に各ノードのディスクへ適用(apply)されるのは少し遅れることがあり、よく **仮想同期(virtually synchronous)** と呼ばれます。
Galera の利点と注意点
- **データ一貫性**: 認証を通過したトランザクションは全ノードに反映されるため、非同期レプリケーションのデータ消失リスクがほぼありません。
- **高可用性**: 1 ノードが落ちても、残りのノードが読み取りと書き込みを受け続けます。
- **読み取りスケーリング**: どのノードからでも読めます。
ただし次の点に注意が必要です。
- **書き込み衝突と認証失敗**: 複数のノードで同じ行を同時に変更すると、認証段階で衝突が起き、後のトランザクションがロールバックされます。そのため、マルチマスターで自由に書き込みを分散するより、**書き込みは 1 つのノードに集める** パターンがよく使われます。
- **コミット遅延**: すべてのノードと通信する必要があるため、ネットワークが遅かったりノードが遠く離れていたりするとコミットが遅くなります。地理的に分散した環境では慎重になる必要があります。
- **クォーラムとスプリットブレイン**: ネットワークが分断されたときにデータが分かれるのを防ぐため、多数派(クォーラム)を成した側だけが動作します。そのためノード数を奇数(たとえば 3)にするのが一般的です。
- **DDL と大きなトランザクション**: スキーマ変更や非常に大きなトランザクションはクラスター全体に影響しうるため、扱いが難しくなります。
Galera の設定例
Galera は wsrep 関連の設定で動作します(パラメータ名や推奨値はバージョンによって異なることがあります)。
[galera]
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name=my_cluster
wsrep_cluster_address=gcomm://10.0.0.1,10.0.0.2,10.0.0.3
wsrep_node_address=10.0.0.1
wsrep_sst_method=mariabackup
Galera は InnoDB と行ベースのレプリケーション形式を前提とする
default_storage_engine=InnoDB
binlog_format=ROW
innodb_autoinc_lock_mode=2
新しいノードがクラスターに参加するときは、既存ノードからデータを受け取って同期する必要があります。これを **SST(State Snapshot Transfer)** といい、データセット全体を丸ごとコピーします。変更分だけを素早く追いつく **IST(Incremental State Transfer)** もあります。大容量クラスターでは SST は時間と負荷が大きいため、運用時に考慮が必要です。
レプリケーション方式の比較表
| 項目 | 非同期 | 準同期 | Galera |
|------|--------|--------|--------|
| 書き込みノード | 単一プライマリ | 単一プライマリ | 全ノード可能 |
| コミット応答のタイミング | 即時 | レプリカ受信 ack 後 | クラスター認証通過後 |
| データ消失リスク | あり | 低い | 非常に低い |
| コミット遅延 | 低い | 中 | ネットワーク依存 |
| レプリケーション遅延の可能性 | あり | あり | 非常に小さい |
| 代表的な用途 | 読み取り拡張、バックアップ | 消失に敏感な OLTP | HA、一貫性重視 |
パーティショニング
テーブルが非常に大きくなると、1 つの巨大なテーブルを論理的に複数の断片に分ける **パーティショニング** が役立ちます。アプリケーションからは依然として 1 つのテーブルに見えますが、内部では定義した規則に従って複数のパーティションにデータが分かれて保存されます。
1 つの論理テーブル (sales)
┌──────────────────────────────────────────────┐
│ PARTITION BY RANGE (YEAR(sale_date)) │
└──────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ p2023 │ │ p2024 │ │ p2025 │ │ pmax │
│ < 2024 │ │ < 2025 │ │ < 2026 │ │ 残り │
└────────┘ └────────┘ └────────┘ └────────┘
WHERE sale_date >= '2025-01-01'
──▶ p2023, p2024 はスキャン対象外 (パーティションプルーニング)
パーティショニングの最大の利点は **パーティションプルーニング(partition pruning)** です。クエリ条件にパーティションキーが入ると、オプティマイザーが無関係なパーティションを丸ごとスキップしてスキャン範囲を減らします。また、古いデータを丸ごと空にするときにパーティション単位で素早く削除できるため、大容量の時系列データ管理に役立ちます。
範囲パーティショニングの例は次のとおりです。
CREATE TABLE sales (
id BIGINT NOT NULL AUTO_INCREMENT,
sale_date DATE NOT NULL,
amount DECIMAL(12,2) NOT NULL,
PRIMARY KEY (id, sale_date)
)
ENGINE=InnoDB
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
注意したいのは、パーティショニングは万能ではないという点です。パーティションキーがクエリ条件に入らないと、すべてのパーティションを探さなければならず、かえって遅くなることがあります。また、パーティションキーは主キーを含むすべての一意キーに含まれなければならないという制約があり、キー設計に影響します。
MariaDB と MySQL の関係と違い
MariaDB は MySQL からフォークして始まったため、多くの SQL 構文やクライアントプロトコルが互換です。しかし、2 つのプロジェクトが独立して発展する中で、違いが大きくなっています。
| 項目 | MariaDB | MySQL |
|------|---------|-------|
| 出発点 | MySQL からフォーク | 元祖 |
| ライセンス/ガバナンス | コミュニティ中心の財団 | 商用ベンダー主導 |
| ストレージエンジンの多様性 | Aria, ColumnStore など多様 | InnoDB 中心 |
| 同期クラスター | Galera を標準統合 | 別のグループレプリケーション |
| JSON 処理 | 関数中心のアプローチ | ネイティブ型を強調 |
| 一部の新機能 | 独自機能を追加 | 独自機能を追加 |
実務で覚えておくべき点は、**バージョンが上がるほど 2 製品の互換性が 100% ではない** ということです。基本的な CRUD と標準 SQL はおおむね互換ですが、レプリケーションプロトコル、GTID 形式、JSON 処理、一部のシステム変数、新しい関数などで違いがあることがあります。したがって、一方から他方への移行を計画するなら、単純なダンプ/リストアだけで終わると仮定せず、十分な互換性検証を行う必要があります。具体的な違いは、ご利用中のバージョン同士を公式ドキュメントで突き合わせるのが安全です。
運用とチューニング
アーキテクチャを理解したら、運用でよく手を入れる項目を整理しておくとよいでしょう。
よく見る設定項目
[mysqld]
InnoDB バッファプール: ワーキングセットをメモリに収めるほどディスク I/O が減る
(専用 DB サーバーなら物理メモリのかなりの部分を割り当てるのが一般的)
innodb_buffer_pool_size = 8G
REDO ログ関連: 小さすぎるとチェックポイントが頻繁になる
(推奨値やパラメータ名はバージョンによって異なることがある)
innodb_log_file_size = 1G
コミット時のログ flush ポリシー (耐久性と性能のトレードオフ)
1: 最も安全(毎コミット flush)、0/2: より速いが消失リスク増
innodb_flush_log_at_trx_commit = 1
レプリケーション形式: Galera と安定したレプリケーションには ROW 推奨
binlog_format = ROW
接続が多い環境ならスレッドプールを検討
thread_handling = pool-of-threads
各値の適正ラインは、ワークロードやハードウェア、バージョンによって異なります。上記の値はあくまで出発点であり、実際の運用ではモニタリング指標を見ながら調整する必要があります。
モニタリングのポイント
- **バッファプールのヒット率**: ディスクに落ちる割合が高ければ、バッファプールが小さいかワーキングセットが大きすぎる兆候です。
- **レプリケーション遅延**: レプリカがプライマリよりどれだけ遅れているかを定期的に確認します。
- **スロークエリログ(slow query log)**: 実行計画の悪いクエリを見つける出発点です。
- **ロック待ちとデッドロック**: 同時実行の問題を早期に発見します。
- **Galera のステータス変数**: クラスターサイズ、フロー制御の発生頻度、認証失敗率などを見ます。
実行計画は EXPLAIN で確認します。
-- オプティマイザーが選んだ実行計画を確認
EXPLAIN
SELECT u.id, u.name, COUNT(o.id) AS cnt
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created >= '2026-01-01'
GROUP BY u.id, u.name;
-- 実際の実行統計まで見たいとき (サポート時)
ANALYZE
SELECT * FROM orders WHERE user_id = 42;
落とし穴とよくある間違い
長く運用する中で繰り返し出会う落とし穴をまとめました。
1. **バッファプールを小さく取りすぎる**: ディスク I/O がボトルネックなのに、原因をクエリのせいだけにしてしまうことが多いです。ワーキングセットとバッファプールのサイズの関係をまず確認してください。
2. **非同期レプリケーションを同期と勘違いする**: 非同期レプリケーションでは、プライマリ障害時に最後のいくつかのトランザクションが消えることがあります。「レプリケーションがあるから消失はない」という仮定は危険です。消失に敏感なら準同期や Galera を検討してください。
3. **Galera でマルチマスターに無分別に書き込みを分散する**: 同じ行を複数ノードで同時に変更すると認証衝突が頻発します。通常は書き込みを 1 ノードに集め、残りを読み取り用に使います。
4. **パーティションプルーニングが効かないクエリ**: パーティションキーが WHERE 条件にないと、すべてのパーティションをスキャンします。パーティショニングを導入したのにかえって遅くなったら、プルーニングが効いているか EXPLAIN で確認してください。
5. **統計の未更新による悪い計画**: データ分布が大きく変わったのに統計が古いと、オプティマイザーが見当違いのインデックスを選ぶことがあります。
6. **エンジンをワークロードに合わない形で選ぶ**: 分析集計に InnoDB だけを使って遅いと不満を言ったり、単件更新が頻繁なのに ColumnStore を使ったりする不一致に注意してください。
7. **DDL を重く実行する**: 大きなテーブルのスキーマ変更はロックと負荷を引き起こすことがあります。オンライン DDL のオプションとその制約をご利用バージョンのドキュメントで確認し、Galera ではさらに慎重に扱う必要があります。
8. **MariaDB と MySQL の互換性を過信する**: バージョンの異なる 2 製品間の移行を単純なダンプ/リストアで終えられると仮定しないでください。レプリケーション、GTID、一部の関数で違いが出ることがあります。
おわりに
MariaDB のアーキテクチャは「SQL を解釈する層」と「データを保存するストレージエンジン層」の分離から出発します。この分離のおかげで、同じ SQL でも InnoDB、Aria、ColumnStore、MyRocks のように性格がまったく異なるエンジンを、ワークロードに合わせて選んで使えます。
データを複数ノードに広げる方法は、非同期レプリケーションから準同期、GTID、そして Galera 同期マルチマスターまで、一貫性と性能の間で異なるバランス点を提供します。どれかが「正解」なのではなく、データ消失の許容度、遅延の要求、運用の複雑さに応じて選択が変わります。
パーティショニングは大容量テーブルを扱う強力なツールですが、パーティションキーの設計とプルーニングが核心である点を覚えておく必要があります。そして MariaDB と MySQL は根は同じですが、違いがますます大きくなっているため、バージョンごとの動作は常に公式ドキュメントで確認する習慣が安全です。
最後に強調すると、この記事の具体的なパラメータ、構文、デフォルト値はバージョンによって変わることがあります。大きな絵で方向を定めつつ、実際に適用する前には、ご利用中のバージョンの公式ドキュメントを必ず確認することをおすすめします。
参考資料
- MariaDB Knowledge Base: https://mariadb.com/kb/en/
- Storage Engines: https://mariadb.com/kb/en/storage-engines/
- InnoDB: https://mariadb.com/kb/en/innodb/
- Galera Cluster: https://mariadb.com/kb/en/galera-cluster/
- Replication: https://mariadb.com/kb/en/replication/
- Partitioning Tables: https://mariadb.com/kb/en/partitioning-tables/
- Global Transaction ID: https://mariadb.com/kb/en/gtid/
- Galera Cluster Documentation: https://galeracluster.com/library/documentation/
- MySQL Reference Manual: https://dev.mysql.com/doc/
현재 단락 (1/285)
MariaDB は MySQL から分岐したオープンソースのリレーショナルデータベースです。当初は MySQL とほぼ同じコードを共有していましたが、時間とともに独自のストレージエンジン、レプリケーシ...