スマートスタイル TECH BLOG

データベース&クラウド技術情報

【続】MySQL8.0.17で導入されたCLONEプラグインについて

※ この記事は前回からの続きになっています

前回、調査しきれなかった以下の点について確認していきたいと思います。

  • MySQL InnoDB ClusterにおけるCLONE機能の利用
  • CLONE機能を使用するうえでのデメリット(制限)
  • リモートCLONEが内部的に実行しているコマンド
  • CLONEと従来のバックアップツールの比較

1. MySQL InnoDB ClusterにおけるCLONE機能の利用

MySQL InnoDB Cluster(MIC)において、CLONE機能は以下のようなケースで利用できます。

  1. 各ノードのバックアップ
  2. ノードの配下に非同期スレーブを追加
  3. ノードのプロビジョニング

特に注目すべきは「3. ノードのプロビジョニング」です。これはCLONE機能でノードのデータを丸ごと別ノードにコピーすることで、「新規ノード追加」や「障害ノードの復旧」を実現できます。
PXCなどGalera Clusterを使用しているユーザには、「GaleraのSST」と同様の機能と言えば分かりやすいかと思います。

それでは早速このプロビジョニング機能を試してみましょう。
dbdeployerを使用した前回の記事とは異なり、MySQL Shell内のsandbox機能を用いてMIC検証環境を構築します。

参考:
21.2.6 Sandbox Deployment of InnoDB Cluster

まずはローカル環境にMySQL Server と MySQL Shell をインストールします(必要であればClientも)。

次に、MySQL Shell にログインしてインスタンスを3つ立ち上げます。

この時 mysqld のポートを指定する必要がありますが、InnoDB Cluster用のポートが mysqldのポート × 10 + 1 で自動計算される仕様上、ポート番号の上限である”65535″を超えないよう注意してください。
→ ここで”7000″ポートと指定するとデプロイ時にエラーが起こります

次に3310ポートのインスタンス(node1とする)に接続し、クラスタを作成します。

続いて、node2 / node3 もクラスタに参加させます。
その中でノードのリカバリ(同期)方法についてのメッセージ(★)が出力されますが、そこに”CLONE”の選択肢が追加されているのが分かります。

これで、node1~node3のクラスタが完成しました。従来は mysqldump や MySQL Enterprise Backup などでノードをコピーする必要がありましたが、CLONE機能のおかげで簡単に構築ができるようになりました。

また上記の過程でCLONEプラグインがインストールされているため、初期構築時のみでなく通常運用時もCLONE機能が使えます。

以下は、ノード障害が発生した時に復旧させる場合にCLONE機能を使う例です。

2. CLONE機能を使用するうえでのデメリット(制限)

ここまでCLONEの良い点ばかりを紹介してきましたが、逆にデメリットについても調査しました。
マニュアルベースでは以下のような制限事項があります。

◆ DDL(TRUNCATE含む)はCLONE中は実行できない

実際に試してみます。前回の記事で構築した dbdeployer の環境を使用しても良いのですが、折角なので今回 MySQL Shell で構築したMIC環境を使用しましょう。

まずは、node1上で適当な大きさのテストデータを作成します。以下では、前回の記事同様 sysbench を使用した例を記載します。

作成したテーブルに対してDDLを実行している間、別コンソールでCLONEの作成を試みると、たしかにCLONE処理が待機させられていることが分かります。
→ processlist の”Waiting for backup lock”状態

ただし、MySQL8.0で追加された INSTANT DDLなどを活用すれば、影響を最小限に抑えつつ運用ができそうです。

◆ 異なるバージョン間のCLONEの復元はできない

クローンの取得元と復元先のMySQLは同じバージョンであることが求められます。
また、CLONEはMySQL8.0.17からの新機能なのでそれ以前のバージョン(MySQL5.7含む)では復元することができません。

◆ 複数インスタンスから同時にCLONEはできない

1回のCLONE操作で複数のMySQLインスタンスからデータを取得することはできません。
その場合は、各インスタンスに対して1回ずつCLONEを実行していきましょう。

◆ X Protocolを利用したリモートCLONEはできない

mysqlx_port 変数で指定した X Protocol 用ポートを指定して、CLONE操作を行うことはできません。
セキュリティ上の理由から利用できるポートを制限している場合などは注意が必要です。

◆ サーバの設定情報はCLONEでコピーされない

CLONEデータには my.cnf などの設定ファイルが含まれないため、Donorノードのパラメータ設定などはコピーされません。
また、SET PERSISTで変更した変数の情報も同様にコピーされません。

◆ バイナリログはコピーされない

設定ファイルと同様に、バイナリログもコピー対象から外れています。

◆ CLONEの対象はInnoDBのみ

CLONEプラグインが正式にサポートしているのはInnoDBのみです。そのため、MyISAMやCSV、sysスキーマなどのテーブルは、データが空の状態で復元されます。

◆ MySQL Router 経由でDonorノードに接続できない

MySQL Routerから直接DonorとなるMySQLに接続できません。これは運用時に注意が必要です。

◆ 絶対パスの一般テーブルスペースはサポート外

ローカル上でCLONEを作成する場合、絶対パスで作成された一般テーブルスペースはサポート対象外になります。
これはCLONE実行時に既存のファイルと同じパス上にCLONEデータを作成しようとして、競合してしまうためです。

また、このマニュアルには明記されていませんが以下のような制限事項もあるようでした。

◆ Group Replication 実行中は、手動のCLONEコマンドは実行できない

MIC環境で試したところ、以下のエラーが発生しました。

3. リモートCLONEが内部的に実行しているコマンド

次に、CLONEがInnoDBテーブルのデータをコピーする際に、内部的にどのような挙動をしているのか見てみたいと思います。

本来はソースコードを細かく読み解くのが確実ですが、今回はCLONE関連の Worklog を基に考えたいと思います。

まず、WL#9209: InnoDB: Clone local replicaのチケットを読むと、以下のことが分かります。

  • CLONEプラグインは「単なるデータ転送」ではなく、「InnoDBのスナップショットの取得」を目的にデザインされている(copy & apply)
  • スナップショットの送受信はCLONEプラグインと SE(ストレージエンジン)層のClone Handleで行われる(現時点ではシングルタスクのみ対応)
  • InnoDB の “Page Tracking” と “Redo Archiving” 機能が利用されている
  • スナップショットの取得は以下のようなステップで行われる
[INIT] —> [FILE COPY] —> [PAGE COPY] —> [REDO COPY] -> [Done]

【各フェーズの説明】

1. INIT
cloneオブジェクトの初期化

2. FILE COPY
全てのデータベースファイルをコピーし、呼び出し元(clone plugin)に送信

3. PAGE COPY
コピー開始/終了(バッファプールから読み取ったCLONE START LSN / CLONE FILE END LSN)までの間に変更されたページ(Page ID)を、送信
→ donor のランダムREAD, recipient のランダムWRITEを回避する

4. REDO COPY
LSNが記録されたRedoログを送信(レプリケーション開始に必要な座標も含む、詳細は[#9211](https://dev.mysql.com/worklog/task/?id=9211))

5. Done
処理の終了、cloneオブジェクト自体はsnapshot_end()が呼び出されるまで残る

次に、WL#9210: InnoDB: Clone remote replicaではリモート間のCLONE操作に関して説明がされています。これを読むと以下のことが分かります。

  • ローカルサーバ(RECIPIENT)上で、リモートサーバ(DONOR)を対象にCLONEコマンドを実行することでリモートCLONEが開始する
  • この時の操作はRPC(リモートプロシージャコール)”COM_CLONE”として行われる
    → RPCコマンドとレスポンスコードをまとめて”CLONE PROTOCOL”と呼ぶ
  • RECIPIENT / DONOR 間の処理の流れはワークログに記載された以下の図が分かりやすい

【図内の処理の説明】(一部、図に含まれないものもあります)

1. COM_INIT
clone protocol のバージョンを確認し、DONORのSE層とCLONEクライアント間でCLONE操作を開始する。将来的には内部的にバージョンの差異を埋めるように通信を行う機能も追加予定。

2. COM_ATTACH
進行中のCLONE操作にアタッチする新しい制御スレッドを指します。マルチスレッド処理をサポートします。

3. COM_REINIT
ネットワーク障害後にクローン操作を再開します。障害が発生すると、全てのCLONEクライアント/サーバのマスタスレッドがその他の全スレッドのクローズを待ったあと、再接続を試みます。これに成功した場合、CLONEクライアントはサーバに対して最新のSEロケータ情報を送信します。
クローン操作のロケータはスナップショットの論理ポインタのことです。サーバはスナップショットを再初期化してロケータを返します。

4. COM_EXECUTE
CLONE操作を開始し、クライアントにストリーミングデータを返します。シリアル化されたディスクリプタはSE固有のものであり、RECIPIENTがデータを保存している間に直接SEに渡されます。
DONORはネットワーク経由でスナップショットからデータをストリーミングします。データは応答データパケットとして複数チャンクで送信されます。

A) COM_RES_LOCS
クライアントからサーバへのロケータセット。
B) COM_RES_DATA_DESC
データパケットの情報を持つディスクリプタ。ヘッダがCLONEプラグインのSEインデックスになっている。その後の部分には、ステータス情報やタスク情報、ファイルのメタデータ、次ブロックの情報などが含まれている。
C) COM_RES_DATA
lengthデータ形式の生データ
D) COM_RES_COMPLETE
CLONE操作が問題なく終了した。
E) COM_RES_ERROR
CLONE操作がエラーで終了した。

COM_RES_DATA を使用すると、データ全体がこのような複数チャンクで転送されます。全て転送された後、DONORは CLONE_COM_END を送って終了します。

5. COM_ACK
異なるCLONEステータスへの切り替えが正常に行われたことを確認します。DONORはRECIPIENTから正常ACKを受け取れた時のみ、次の段階に移行します。動的スナップショットを前のステージに戻すことはできません。
これはCLONEクライアントのエラーをCLONEサーバに伝える時にも使用されます。COM_EXECUTE中はデータがCLONEサーバ→CLONEクライアントの一方向にのみストリーミングされることに注意してください。

6. COM_EXIT
CLONEプラグイン、およびプロトコルを終了し、通常のサーバプロトコルに戻ります。

以上2点のワークログから、CLONE機能はプラグイン、ストレージエンジン間で直接データ(スナップショット)をやり取りしていることが分かります。また、その送受信は並列化で実行されています。
こうした挙動を柔軟に制御するため、CLONE機能用のシステム変数が用意されています。詳細は前回の記事を参照してください。

また、performance_schema.clone_progressテーブルを参照すれば、実行中のCLONE操作が現在どの段階を実行中なのかを確認することもできます(CLONEのモニタリング)。また、以下のようにCLONE関連の instruments を有効にすることでも情報収集が可能です。

参考マニュアル

4. CLONEと従来のバックアップツールの比較

最後に同じテーブルデータに対し、mysqldump / MySQL Enterprise Backup / CLONE の取得・リストアを実施し、それぞれの操作にかかった時間を比較します。

※ MySQL Enterprise Backup(以下、MEB)は、MySQL Enterprise Editionで利用できるバックアップツールです

比較方法

以下のような手順で比較を行います。MySQLインスタンスは、上記で作成したテスト用インスタンス(port : 3340)を使用します。

(1) sysbench でテストデータを作成

(2) 調査対象のツールでバックアップを実行

CLONE機能の場合全データベースがバックアップ対象になるので、その他のバックアップツールも全データベースを対象としたフルバックアップを使用します。

ツール実行時にtimeコマンドをつけて、”real”の時間を計測します。

【A】mysqldump

【B】MEB

【B】CLONE

(3) 調査対象のツールでリストアを実行

sbtest / sbtest2 データベースを削除したのち、各ツールのバックアップリストアを実行します。ここでも time コマンドで時間を計測します。

【A】mysqldump

【B】MEB

【C】CLONE

(4) ステップ(1)に戻り、別のツールで試験を実施

テスト結果

各ツールのバックアップ・リストアにかかった時間は、以下のようになりました。
もちろん環境やデータ、試験方法によっても変わってくると思うので、参考程度に捉えて頂ければと思います。

mysqldump MEB CLONE
バックアップ 1m18.366s 48.923s 24.444s
リストア 11m30.922s 55.729s 20.699s

バックアップ対象の差異などもありますが、CLONEの実行時間がかなり速いことが分かりました。

まとめ

ここまで2つの記事に渡ってCLONE機能を取り上げてきましたが、実際に触ってみた体感としてもとても便利な機能だと思います。
今後のMySQL8.0運用の形が変わる可能性もあり、今後の機能改善や拡張からも目が離せません。

その他、参考にしたページ

A Breakthrough in Usability – Automatic Node Provisioning
21.2.5 Using MySQL Clone with InnoDB cluster

MySQL
Return Top