MySQL道普請便り

第127回 CLONEプラグインを導入しよう

この記事を読むのに必要な時間:およそ 3.5 分

MySQL 8.0.17以降に,CLONEプラグインというものが追加されました。これはオンラインで取得することができるフルバックアップで,同一データのMySQLサーバーを作成する際にとても便利なものです。

今回はCLONEプラグインの導入から実施までと,利用する際の注意点について確認していきましょう。なお,検証環境はCentOS 7でMySQL 8.0.21を利用しています。

また,CLONEプラグインではよく,DonorとRecipientというワードが利用されます。これはDonarがCLONEの元(データのコピー元のインスタンス)でRecipientがCLONE先(データのコピー先のインスタンス)になります。

CLONEプラグインの導入

CLONEプラグインはMySQLサーバーのパッケージに同梱されており,利用するためにはINSTALL PLUGINステートメントでインストールする必要があります。INSTALL PLUGINを実行後に,SHOW PLUGINでインストールされていることが確認できます。

mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so';
Query OK, 0 rows affected (0.49 sec)

mysql> SHOW PLGUINS;

〈省略〉

| mysqlx                          | ACTIVE   | DAEMON             | NULL           | GPL     |
| clone                           | ACTIVE   | CLONE              | mysql_clone.so | GPL     |
+---------------------------------+----------+--------------------+----------------+---------+
45 rows in set (0.06 sec)

これで準備は完了です。

CLONEを使ってデータをコピーする

CLONEを使ってデータを取得するには,CLONE LOCAL DATA DIRECTORY = <取得したいディレクトリパス>を指定します。実行権限として,全スキーマ,テーブル(*.*)に対してCLONE_ADMIN権限が必要です(ただし,ローカルでのみ実行する場合はBACKUP_ADMIN権限でも可⁠⁠。もし,特定のユーザーで実行する場合はCLONE_ADMIN権限があるか確認し,必要であれば権限を付与しなければなりません。

また,CLONEは実行する際に指定のディレクトリを生成してから行われるため,事前にディレクトリが存在する場合は,空のディレクトリであったとしても下記のようなエラーが発生し,データを取得することができません。実行前はディレクトリが存在しないことを確認してから実行しましょう。

ERROR 1007 (HY000): Can't create database '/tmp/testdb'; database exists

エラーなく実行できた場合は,Query OKが表示されます。

mysql> CLONE LOCAL DATA DIRECTORY = '/tmp/clone_testdb';
Query OK, 0 rows affected (2.30 sec)

実行が完了すると,指定したディレクトリ配下にスキーマ,テーブル,テーブルスペース,データディクショナリなどがコピーされていることが確認できます。

$ ll /tmp/testdb
total 682064
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 #clone
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 d1
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 d2
-rw-r----- 1 mysql mysql     24800 Jul 29 03:12 ib_buffer_pool
-rw-r----- 1 mysql mysql  12582912 Jul 29 03:12 ibdata1
-rw-r----- 1 mysql mysql 268435456 Jul 29 03:12 ib_logfile0
-rw-r----- 1 mysql mysql 268435456 Jul 29 03:12 ib_logfile1
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 mysql
-rw-r----- 1 mysql mysql  79691776 Jul 29 03:12 mysql.ibd
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 sys
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 test
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 trxtest
-rw-r----- 1 mysql mysql  14680064 Jul 29 03:12 undo_001
-rw-r----- 1 mysql mysql  26214400 Jul 29 03:12 undo_002
-rw-r----- 1 mysql mysql  28311552 Jul 29 03:12 undo_table_space.ibu
drwxr-x--- 2 mysql mysql      4096 Jul 29 03:12 world

これを利用して,違うポートでMySQLを起動してみます。筆者の環境では/data配下にdatadirを配置しているため,同じように/data配下に移動させて,my.cnfを準備して起動させてみます。

$ mv /tmp/testdb /data/clone_testdb
$ cp /data/testdb/my.cnf /data/clone_testdb/my.cnf
$ vim /data/clone_testdb/my.cnf <-port番号やserver-id,datadirなどを変更 
$ /usr/local/mysql8021/bin/mysqld_safe --defaults-file=/data/clone_testdb/my.cnf --ledir=/usr/local/mysql8021/bin "$@" &
$ /usr/local/mysql8021/bin/mysql --defaults-file=/data/clone_testdb/my.cnf -uroot -p
mysql> SELECT @@port;
+--------+
| @@port |
+--------+
|   3310 |
+--------+
1 row in set (0.00 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| d1                 |
| d2                 |
| information_schema |
| mysql              |
| nyumon             |
| performance_schema |
| sys                |
| test               |
| trxtest            |
| world              |
+--------------------+
10 rows in set (0.18 sec)

簡単にMySQLを複製することができました。

このインスタンスをレプリケーションスレーブとして追加する場合,GTIDを利用しているときはGTID関連の情報もコピーされているので,MASTER_AUTO_POSITION=1を指定してCHANGE MASTERステートメントを実行することで追加できます。GTIDを利用していない場合でも,performance_schema.clone_statusテーブルを確認することでCLONE実施の情報を取得できるので,この情報をもとにCHANGE MASTERステートメントを実行して追加することが可能です。

mysql> SELECT * FROM performance_schema.clone_status\G
*************************** 1. row ***************************
             ID: 1
            PID: 12
          STATE: Completed
     BEGIN_TIME: 2020-07-29 03:12:13.358
       END_TIME: 2020-07-29 03:12:14.556
         SOURCE: LOCAL INSTANCE
    DESTINATION: /tmp/clone_testdb/
       ERROR_NO: 0
  ERROR_MESSAGE:
    BINLOG_FILE:
BINLOG_POSITION: 0
  GTID_EXECUTED:
1 row in set (0.15 sec)

リモートサーバーにおけるクローンも可能で,下記のようにCLONE INSTANCE FROM '<cloneを実行するユーザー>'@'<DonarのIP>':<Donarのport> IDENTIFIED BY '<パスワード>' (DATA DIRECTORY = '<取得先>')とすることで,リモートサーバーに向けて実行することが可能です。

DATA DIRECTORYがカッコ()書きになっているのは,指定しなかった場合にRecipient側のデータがDonarと同じデータに置き換わり,インスタンスの再起動が実行されるためです。DATA DIRECTORYを記述しないと,データが置き換わってRecipient側にのみ存在していたデータは消えてしまうので注意してください。

mysql> CLONE INSTANCE FROM 'root'@'127.0.0.1':3306 IDENTIFIED BY 'xxxxxx' DATA DIRECTORY = '/tmp/remote_testdb';
Query OK, 0 rows affected (2.17 sec)

また,リモートサーバーで実行する場合,Donarとなるインスタンス情報がRecipient側のclone_valid_donor_listに設定されている必要があります。設定されていないな場合や設定が間違っている場合は,ERROR 3869 (HY000): Clone system configuration: 127.0.0.1:3306 is not found in clone_valid_donor_list: 127.0.0.1:3307といったエラーが出力されるので,設定後再実行してみましょう。

mysql> SET GLOBAL clone_valid_donor_list = '127.0.0.1:3306';
Query OK, 0 rows affected (0.06 sec)

mysql> SHOW VARIABLES LIKE 'clone_valid_donor_list';
+------------------------+----------------+
| Variable_name          | Value          |
+------------------------+----------------+
| clone_valid_donor_list | 127.0.0.1:3306 |
+------------------------+----------------+
1 row in set (0.07 sec)

リモートサーバーでの実行に関しての詳しい説明は,公式ドキュメントの5.6.7.3 Cloning Remote Dataをご確認ください。

注意点

CLONEプラグインを利用する際はいくつかの注意点があります。

  • Donar側の並列でのDDL操作は許可されていません。もし,頻繁にDDL(TRUNCATEも含む)が実行される環境であれば,参照のない遅延しても良いスレーブサーバーなどで実行することをおすすめします。
  • DonarとRecipient間で異なるバージョンからクローンすることはできません。利用するときはDonarとRecipientのバージョンを揃えて実行するようにしましょう。
  • CLONEの対象となるデータはInnoDBストレージエンジンとなります。実行前に各テーブルのストレージエンジンを確認し,InnoDB以外のものがないか確認をしてください。

その他にもいくつか制限がありますので,実行前に5.6.7.13 Clone Plugin Limitationsを読んでおくと良いかと思います。

まとめ

今回は,MySQL 8.0.17で追加されたCLONEプラグインについて簡単に説明しました。CLONEプラグインを利用することで,手軽にデータの複製が可能になり,ますます便利になりました。実行例として,MySQL Server Teamのブログに詳しく紹介されていますので,こちらもぜひご一読ください。

著者プロフィール

深町日出海(ふかまちひでみ)

GMOメディア株式会社のデータベースエンジニア。主にOracleとMySQLを担当。得意なプログラム言語はJava。MySQLの好きなところはTABLEやINDEXの識別子に64byteまで使えるところ。

Twitter:@lhfukamachi