スマートスタイル TECH BLOG|データベース&クラウドの最新技術情報を配信

PXC(Galera Cluster)におけるDDLの挙動について

はじめに

DDL(Data Definition Language)は、MySQLの開発・運用では欠かせない要素です。MySQL5.6で導入された「オンラインDDL」では、従来READロックを取得していたALTER TABLEコマンドがほぼロック無しで実行できるようになり(例外あり)、運用の柔軟性も増してきました。

しかし、Percona XtraDB Cluster(以下、PXC)におけるDDLの仕様は、通常のMySQLとは少々異なります。本稿ではその部分について解説します。

DDLとは

まず初めにDDLに関しての説明です。DDLはデータベースのオブジェクト(メタデータ)を操作するSQL(クエリ、コマンド)を指しています。ここでいうオブジェクトとは、主にデータベース / テーブルに関する定義情報です。例えば、データベースを作成する「CREATE DATABASE」や、テーブルを削除する「DROP TABLE」などが該当します。

MySQLにおける代表的なDDLは「ALTER TABLE」です。これは既存のテーブルの構造を変更するSQLであり、以下のようなことができます。

  • インデックス / カラムの追加・削除
  • テーブル名 / カラム名の変更
  • カラムのデータ型変更
  • テーブルの文字コード変更
  • InnoDBページ圧縮の有効化

MySQL5.5までは、DDLの実行中は参照クエリは受け付けますが、更新クエリ(DML)はDDLが完了するまで待たされる仕様になっていました。
しかし、MySQL5.6から実装された「オンラインDDL」が利用できる場合(※)は、DDL実行中であっても更新クエリを受け付けるようになりました。

※ マニュアルの『表 14.5 DDL 操作のオンラインステータスのサマリー』で「並列 DML を許可?」が「はい」になっているもの

オンラインDDLのおかげで、サービスに影響(停止)を与えることなくDDLを実行することが可能になり、メンテナンス作業などの運用に大きなメリットが生まれました。

PXCにおけるDDL

PXC(Galera)でも、問題なくDDLは実行できます。しかし、「マルチマスタ」であり全ノードで更新を受け付ける仕様上、DDLが原因でノード間でテーブル構造に差分が生じると、データの整合性が崩れてしまいます(※)。

※ DDLは non-transactional な処理であり、途中で失敗した時にロールバックなどが難しいため

そのため、PXCでは2つの実行形式が存在し、wsrep_osu_method変数で制御できます。
(OSUは Online Schema Upgradeの略です)

  • wsrep_OSU_method = TOI

TOI(Total Order Isolation)は、PXC(Galera)のデフォルト方式です。この設定が有効な場合、DDLを実行した時に全ノードで整合性を保つために、DDLが実行される順番(GTID)が同じになるように調整されます。

つまりは全ノードで同時にDDLが実行されるわけですが、この代償としてDDLが完了するまでの間は全てのトランザクションが待ち状態(※)になります。これはMySQLでは「オンラインDDL」に該当する操作であっても同じ挙動になります。

※ より正確には commit の完了が待たされます

そのため、実行に長時間かかることが予想されるDDL(巨大テーブルへのALTER TABLEなど)は、サービス稼働中には実施しない、メンテナンス期間を設けるなどの工夫が必要となります。

  • wsrep_OSU_method = RSU

RSU(Rolling Schema Upgrade)はもう1つのDDL実行方式です。同設定を有効にすると、DDLが実行されている間のみ、ノードがクラスターから切り離され、他ノードへの更新クエリの送受信を受付しなくなります。そのため、DDLを実行してもそれが他ノードに伝播せず、該当ノードのみに反映します。その後、RSUを無効にするとクラスタから切り離されていた間実行された更新差分が適用され、クラスタに復帰します(※)。

※ この時の挙動はIST方式と同じであるため、Galera Cacheが十分なサイズ用意されていない場合はSSTが作動し変更が上書きされます

DDLが反映されるのは、RSUを実行したノードのみとなりますのでDDLの内容によっては、ノード間の整合性が保てなくなる可能性があります。特に「カラム追加」などの場合は、クエリの書き方によってはエラーとなる可能性があります。

また、カラムのデータ型を変更した場合はslave_type_conversions変数の制限にひっかかり、Galeraレプリケーションが停止してしまうこともあります。

TOI と RSU の使い分け

メンテナンス時間などPXC側で更新クエリが実行できない時間帯があっても許容されるケース、もしくはDDL自体が短時間で完了することが分かるケースでは、デフォルトの wsrep_osu_method = TOI でDDLを実行して問題ありません(ただし、完了するのに長時間かかるALTER TABLEには注意が必要です)。

一方、更新クエリの実行件数が多く、かつ停止時間が許容できないような場合は、RSUを使って1ノードずつDDLを発行していくことが推奨されます。なお、作業中はクラスタからノードが1台減った状態(3ノード構成なら2ノード)になるので、この時にノード障害が発生すると復旧が少し複雑になる可能性があります。

pt-online-schema-change について

上記の TOI / RSU 以外に、pt-online-schema-change(以下、pt-osc)を利用する方法もあります。

pt-osc は、その名の通り、更新クエリをブロックすることなくオンラインでDDLを実行することができるツールで、Percona社が開発する Percona Toolkitに含まれています。

pt-osc の仕組みは以下の通りです。

  1. pt-oscの対象となるテーブルをコピーする
     → 対象テーブルを TABLE01 、コピーテーブルを TABLE01_new とする
  2. TABLE01_newに対して、DDLを実行する(カラム追加、インデックス追加など)
  3. TABLE01 に対する INSERT / DELETE / UPDATE の内容を TABLE01_new にトレースするトリガを作成する
  4. TABLE01_new でDDLが実行している間に、TABLE01で更新されたレコードの情報をコピーする
  5. DDLが完了したら、RENAMEコマンドで TABLE01 と TABLE01_new の名前を入れ替える
  6. 旧TABLE01 とトリガを削除する

pt-osc の特徴は、オンラインDDLが実装されていないMySQL5.5以前でも「オンラインDDLと同等の効果」が実現できることです。ただし、必ずテーブルコピーが必要な点、またトリガーによるレコード更新が常に発生する点などから、サーバ負荷は通常のDDLよりも高くなってしまいます。

pt-osc にできること/できないこと

【できること】

  • 更新トランザクションをブロックしないDDL実行
  • DDLの制御(–max-load–max-flow-ctl オプションなど)

【できないこと】

  • DDL実行中の高負荷回避(テーブルコピー、トリガー)
  • 失敗したDDLを途中から再開

PXC と pt-osc の組み合わせ

PXCに対してDDLを実行したいときに、TOI によるトランザクションのブロックも、RSU によるテーブル互換性が崩れることも許容できない場合は、pt-osc を検討すべきです。

pt-oscによる処理は全てバックグラウンドで行われ、他ノードにも伝播するため整合性も保たれます。また、元テーブルでは処理が行われないため、トランザクションがブロックされることもありません。

ただし、以下のような注意点(制限)があります。

  • pt-osc は必ずテーブルコピーを伴うため、テーブルサイズと同程度のディスク空き領域が必要です
  • wsrep_max_ws_sizeの設定がpt-oscが必要とする更新サイズを下回る場合、pt-oscがエラーとなる可能性があります
  • 元テーブルで既に別のトリガーが定義されている場合、原則としてpt-oscは実行できません
  • サーバへの負荷が高くなるため、クエリのパフォーマンスが全体的に落ちる可能性があります
  • 上記に起因して、Flow Controlが発生する可能性があります
     → pt-osc実行中のFlow Controlを制御するため、–max-flow-ctl オプションが用意されています

なお、MySQLで実行する場合とPXCで実行する場合とで大きな違いはありません。

まとめ

PXCでDDLを実行する場合は3つの選択肢があり、それぞれ以下のようなメリット・デメリットがあります。

TOI RSU pt-osc
利点 手順が簡単で、エラーが起こってもリカバリが容易 ダウンタイムが発生しない ダウンタイムが発生しない
欠点 トランザクションがブロックされる時間(ダウンタイム)が発生する 後方互換性が担保されていないDDLが実行できない DBへの負荷が大きい
適した操作 短時間で完了するDDL
メンテナンス時間中に実行するDDL
インデックス追加などクエリの互換性に影響を与えないDDL ダウンタイムが許容できないDDL

デモ

以下のデモでは、dbdeployerで構築したPXC3ノード環境を利用します。

★TOI のデモ

1. 大きなテストテーブルを作成する

2. もう1つ同様のテストテーブルを作成する

4. wsrep_osu_method=TOIの状態で、インデックスを追加するDDLを実行

ADD INDEXするだけであれば、通常のMySQLの場合はオンラインDDLとなり、更新クエリ / 参照クエリが両方とも実行できますが、PXCではオンラインDDLにはなりません。そのため、DDLの実行中はすべてのトランザクションがCOMMIT待機状態になります。

5. ALTER実行中に新しいクライアントを開いて、large_tblに対して SELECT / UPDATE を実行

6. ALTER実行中に新しいクライアントを開いて、large_tbl_2に対して SELECT / UPDATE を実行

この時、PROCESSLISTを見ると “wsrep: initiating pre-commit for write set”状態でトランザクションが待たされているのが分かります。

※ トランザクションがブロックされるのは「DDLの実行中」のみです
※ DDLの完了後、自動で待ち状態だったトランザクションが適用されます

★RSU のデモ

1. 新しいテストデータを作成

RSU用に新しいテストテーブルを作成します。

2. Node2で、RSU形式のDDLを実行しnew_colカラムを追加

3. Node1とNode2でテーブル定義に差分ができてることを確認

4. 互換性のないINSERTを実行するとエラーとなることを確認

★pt-osc のデモ

1. テストデータを準備

wsrep_osu_method=TOI のデモで使ったテーブルと同じものを準備する

2. pt-oscをセットアップ

Percona Toolkit をインストールする、もしくはpt-oscのみをダウンロードするの2通りの方法があります。
ここでは、後者を採用しています。

3. pt-oscでPKの削除・再作成を行う

14.11.1 オンライン DDL の概要

上記マニュアルの通り、「Primary Keyの削除」はMySQLであってもオンラインDDLには該当しないため、更新トランザクションはブロックされます。
しかし、pt-oscであればその制限を回避することができます。

4. 別クライアントを開き、テーブルを更新できることを確認

まとめ

PXC(Galera Cluster)は原則としてMySQLとの互換性が担保されており、MySQLと同じ操作性で利用できます。
しかし、いくつかの細かい挙動の違いはあり、DDLもその一つです。本番稼働中のPXCでDDLを実行する場合は注意してください。


Percona

 

Return Top