MySQLの新しいレプリケーショントポロジーを可能にする、
「MySQLグループレプリケーション」が絶賛開発中です。
今回はこのMySQLグループレプリケーションをちょっとフライングして使ってみようと思います。
フライング、と言っているのは、まだこれが開発途上版だからです。
この記事の執筆時点(2016/6/26)で、まだグループレプリケーションプラグインはGAリリースされていません。
MySQLではhttps://labs.mysql.com/のサイトで、開発中の製品やプラグインを公開し、
広くユーザの意見を取り入れています。
今回はこのlabs.mysqlで公開されているグループレプリケーションプラグインを使用してみよう、
というわけです。
まず、グループレプリケーションとはどんなものなのか、からですね。
グループレプリケーションは、
レプリケーショントポロジー内のどのサーバで更新をかけても、
それが他のMySQLサーバに伝播される、
という形のレプリケーションです。
これまでのMySQLレプリケーションは、
MasterからSlaveへ、一方向のデータ伝播を行うもので、
Slaveに対してかけた更新はMasterに伝播させることは原則できませんでした。
グループレプリケーションによってどのサーバでも更新がかけられるようになる、
ということですね。
なお、このレプリケーショングループに対しては、
加入離脱が自由です。
加入する際は、自分が実行していないGTIDのトランザクションを取得して
実行してから加入します。
2016年5月に開催された、MySQL Innovation Day Tokyoでの資料に、
グループレプリケーションについての情報がありました。
日本語でこの粒度の情報が出てきたのは、おそらくこれが初めてではないでしょうか?
MySQL Innovation Day Tokyo(MySQL 5.7でのレプリケーション強化点とグループ・レプリケーション)
さて、早速使ってみましょう。
現状、MySQL5.6.10対応のプラグインしか公開されていませんので、
まずMySQL5.6.10をインストールし、
通常のレプリケーション構成に必要なREPLICATION SLAVE権限を持ったユーザの作成や、
GTIDレプリケーションの有効化などを済ませておきます。
さらに、グループレプリケーション実施に当たって必要な設定をmy.cnfに記載します。
※デフォルトから変更する必要がある点のみ記載しています。
詳細はパッケージを展開した中にある、READMEに記載があります。
パス:(SourceRoot)/lib64/mysql/plugin/group_replication_license/README
1.binlog-format=row 2.master-info-repository=TABLE 3.relay-log-info-repository=TABLE 4.transaction-write-set-extraction=MURMUR32 5.binlog_checksum=NONE
それでは、グループレプリケーションプラグインを導入しましょう。
通常のプラグインインストールと同様です。
展開したパッケージの中に、group_replication.soファイルがありますので、
これをMySQLのプラグインディレクトリに配備し、
install pluginします。
# cp -p /root/mysql-group-replication-0.7.0-labs-linux-el7-x86-64bit/lib64/mysql/plugin/group_replication.so /usr/lib64/mysql/plugin/ # mysql -uroot -ppassword Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 12 Server version: 5.7.10-log MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql1> install plugin group_replication soname 'group_replication.so'; Query OK, 0 rows affected (0.00 sec)
これで導入は完了です。
プラグインを導入すると、サーバ変数が追加されます。
mysql1> show global variables like 'group_replication%'; +---------------------------------------------------+------------------------+ | Variable_name | Value | +---------------------------------------------------+------------------------+ | group_replication_allow_local_lower_version_join | OFF | | group_replication_auto_increment_increment | 7 | | group_replication_bootstrap_group | OFF | | group_replication_components_stop_timeout | 31536000 | | group_replication_gcs_engine | xcom | | group_replication_group_name | | | group_replication_local_address | | | group_replication_peer_addresses | | | group_replication_pipeline_type_var | STANDARD | | group_replication_recovery_complete_at | TRANSACTIONS_CERTIFIED | | group_replication_recovery_password | | | group_replication_recovery_reconnect_interval | 60 | | group_replication_recovery_retry_count | 86400 | | group_replication_recovery_ssl_ca | | | group_replication_recovery_ssl_capath | | | group_replication_recovery_ssl_cert | | | group_replication_recovery_ssl_cipher | | | group_replication_recovery_ssl_crl | | | group_replication_recovery_ssl_crlpath | | | group_replication_recovery_ssl_key | | | group_replication_recovery_ssl_verify_server_cert | OFF | | group_replication_recovery_use_ssl | OFF | | group_replication_recovery_user | root | | group_replication_start_on_boot | OFF | +---------------------------------------------------+------------------------+ 24 rows in set (0.00 sec)
結構ありますよね、、、
この中でも、覚えておいた方がよさそうなのは、
group_replication_auto_increment_increment group_replication_bootstrap_group group_replication_group_name group_replication_local_address group_replication_peer_addresses group_replication_recovery_password group_replication_recovery_user
あたりでしょうか。
さて、では早速グループレプリケーションを開始しましょう。
まず、全サーバで下記パラメータを入力する必要があります。
なお、これらはmy.cnfに書いても有効だったので、
手間を省くためにmy.cnfに書くのが便利そうです。
mysql1> SET GLOBAL group_replication_group_name="12345678-9012-3456-7890-123456789012"; Query OK, 0 rows affected (0.00 sec) mysql1> SET GLOBAL group_replication_local_address="192.168.2.221:10300"; Query OK, 0 rows affected (0.00 sec) mysql1> SET GLOBAL group_replication_peer_addresses="192.168.2.221:10300,192.168.2.222:10300,192.168.2.223:10300"; Query OK, 0 rows affected (0.00 sec) mysql1> SET GLOBAL group_replication_recovery_user='repl'; Query OK, 0 rows affected (0.00 sec) mysql1> SET GLOBAL group_replication_recovery_password='repl'; Query OK, 0 rows affected (0.00 sec)
group_replication_group_nameは、
グループに対するGTIDの設定、と考えて良いです。
name、といってもヒューマンフレンドリーな名前をつけることはできず、
UUIDのフォーマットに則った名前を付ける必要があります。
group_replication_local_addressは、読んで字のごとく自分自身のこと、
group_replication_peer_addressesはトポロジーに加入するMySQLサーバの一覧です。
なお、私が試した時には、これらにポートを指定しないと(=3306ポートのままだと)
グループレプリケーションレイヤーの疎通ができませんでした。
READMEを見た感じでは、必ずしも10300ポートである必要はないようですが、
要注意ポイントではありそうです。
group_replication_recovery_userと
group_replication_recovery_passwordは、
グループレプリケーションに再加入する際に、
グループで実行済みトランザクションに追いつくために使用するユーザ、
のようです。
通常のレプリケーションでいう、change master to master_user, master_passwordみたいなもんでしょう。
続いて、1サーバのみで下記を実行する必要があります。
mysql1> SET GLOBAL group_replication_bootstrap_group=1; Query OK, 0 rows affected (0.00 sec)
グループレプリケーション構成の最初の立ち上げをするか否か、
のパラメータです。
これをONにしていると、
グループレプリケーション開始時に新たなレプリケーショングループを立ち上げるようです。
なので、最初の立ち上げ時には必ずONでなければなりませんし、
既存のグループに加入する際にはOFFでなければなりません。
最初の立ち上げに使用したサーバであっても、
再加入する可能性を考えれば、
グループレプリケーション開始後にOFFにした方が良いでしょう。
さあ、ではグループレプリケーション開始です。
group_replication_bootstrap_group=1
としたサーバで下記クエリを実行します。
mysql1> start group_replication; Query OK, 0 rows affected (1.63 sec)
次に、残りのサーバで起動します。
group_replication_bootstrap_group=0
であることを確認してから、同様のコマンドを実行します。
無事起動したかどうかは、
performance_schemaのreplication_group_membersテーブルから確認できます。
mysql1> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-----------------+-------------+--------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | +---------------------------+--------------------------------------+-----------------+-------------+--------------+ | group_replication_applier | bcbb4f68-362b-11e6-8652-000c29818276 | cent7-mysql57-1 | 3306 | ONLINE | | group_replication_applier | bda9e711-362b-11e6-944b-000c29cf93af | cent7-mysql57-3 | 3306 | ONLINE | | group_replication_applier | be54a64b-362b-11e6-84e0-000c2932dd8b | cent7-mysql57-2 | 3306 | ONLINE | +---------------------------+--------------------------------------+-----------------+-------------+--------------+ 3 rows in set (0.00 sec)
どのサーバもMEMBER_STATEがONLINEになっていますね。
これでグループレプリケーションが開始できました。
ほか、通常のレプリケーションでのSHOW SLAVE STATUSにあたるような情報は、
下記コマンドで取得できます。
mysql1> SELECT * FROM performance_schema.replication_connection_status\G *************************** 1. row *************************** CHANNEL_NAME: group_replication_applier GROUP_NAME: 12345678-1234-1234-1234-123456789012 SOURCE_UUID: 12345678-1234-1234-1234-123456789012 THREAD_ID: NULL SERVICE_STATE: ON COUNT_RECEIVED_HEARTBEATS: 0 LAST_HEARTBEAT_TIMESTAMP: 0000-00-00 00:00:00 RECEIVED_TRANSACTION_SET: 12345678-1234-1234-1234-123456789012:1-2:6-7 LAST_ERROR_NUMBER: 0 LAST_ERROR_MESSAGE: LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00 1 row in set (0.00 sec)
動作確認をしてみましょう。
mysql1> create table UCO.ucotable (id int primary key, comment varchar(20)); Query OK, 0 rows affected (0.01 sec) mysql1> create table UCO.ucotable (id int primary key auto_increment, comment varchar(20)); Query OK, 0 rows affected (0.01 sec) mysql1> insert into UCO.ucotable values (null, "from MySQL Server 1"); Query OK, 1 row affected (0.00 sec) mysql1> select * from UCO.ucotable; +----+---------------------+ | id | comment | +----+---------------------+ | 1 | from MySQL Server 1 | +----+---------------------+ 1 row in set (0.00 sec)
これが他のMySQLサーバにも伝播しています。
mysql2> select * from UCO.ucotable; +----+---------------------+ | id | comment | +----+---------------------+ | 1 | from MySQL Server 1 | +----+---------------------+ 1 row in set (0.01 sec)
ここまでは通常のレプリケーションですが、
mysql2のMySQLサーバで実行したクエリが
mysql1サーバにも伝播するかどうかを確かめましょう。
mysql2> insert into UCO.ucotable values (null, "from MySQL Server 2"); Query OK, 1 row affected (0.01 sec) mysql2> select * from UCO.ucotable; +----+---------------------+ | id | comment | +----+---------------------+ | 1 | from MySQL Server 1 | | 2 | from MySQL Server 2 | +----+---------------------+ 2 rows in set (0.00 sec)
mysql1> select * from UCO.ucotable; +----+---------------------+ | id | comment | +----+---------------------+ | 1 | from MySQL Server 1 | | 2 | from MySQL Server 2 | +----+---------------------+ 2 rows in set (0.01 sec)
しっかり伝播していますね。
これがグループレプリケーションです。
なお、mysql1で再度同様のクエリを実行すると、
mysql1> insert into UCO.ucotable values (null, "from MySQL Server 1"); Query OK, 1 row affected (0.01 sec) mysql1> select * from UCO.ucotable; +----+---------------------+ | id | comment | +----+---------------------+ | 1 | from MySQL Server 1 | | 2 | from MySQL Server 2 | | 8 | from MySQL Server 1 | +----+---------------------+ 3 rows in set (0.00 sec)
となって、AUTO INCREMENTのカラムの値が飛びます。
これは、group_replication_auto_increment_incrementのデフォルトが7になっているためです。
mysql1> show global variables like 'group_replication_auto_increment_increment'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | group_replication_auto_increment_increment | 7 | +--------------------------------------------+-------+ 1 row in set (0.01 sec)
なお、オフセットの値はserver_idの値に従うそうです。
最後に、私が使ったmy.cnfの設定を記載しておきます。
1号機のものです。
# For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html [mysqld] # # Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M # # Remove leading # to turn on a very important data integrity option: logging # changes to the binary log between backups. # log_bin # # Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid # for group replication log_bin server_id=1 binlog_format=ROW gtid_mode=on enforce_gtid_consistency log_slave_updates master_info_repository=TABLE relay_log_info_repository=TABLE transaction_write_set_extraction=MURMUR32 binlog_checksum=NONE group_replication_group_name="12345678-1234-1234-1234-123456789012" group_replication_local_address="192.168.2.221:10300" group_replication_peer_addresses="192.168.2.221:10300,192.168.2.222:10300,192.168.2.223:10300" group_replication_bootstrap_group=1 group_replication_recovery_user='repl' group_replication_recovery_password='repl' [client] user=root password=root prompt='mysql1> '
group_replication_bootstrap_group=1は、
最初の起動を想定していたから書きましたが、
起動後にはすぐOFFにするので、
ここでは書かずに、起動する際のみオンラインでONにする方が良いかもしれませんね。
以上がMySQL Group Replicationの基本的な動作です。
まだまだ開発途中ですので、
動作が安定しているとは到底言いがたいですが(笑)、
マルチマスターな高可用性構成を組みたいが
MySQL ClusterにしてNDBストレージエンジンにするのは
アプリケーションが対応していない、
とか、
MySQL Fabricの管理ノードのSPOF解消とか、
使えるところはありそうです。
MySQL Routerとの相性も悪くないでしょう。
では。