従来のMySQLのレプリケーションでは、新規にスレーブを追加する際にマスターのバイナリログファイル名とバイナリログファイルのポジションを指定する必要がありました。
MySQL 5.6.5から追加された機能であるグローバルトランザクション識別子(GTID) を使用することで、マスターのバイナリログファイル名とバイナリログファイルのポジションを指定することなく、容易にレプリケーションを構成・開始できるようになります。今回はGTIDを使用したレプリケーション構成について紹介いたします。
環境構築
第22回 特定のSQL文が原因で発生したレプリケーション遅延の調査方法 で紹介した方法にて、MySQLのインストールまで環境構築します。今回のMySQLのバージョンはMySQL5.6.31
です。
構成は以下のようになっています。
IP MySQL PORT master/slave
172.17.0.1 3306 master
172.17.0.3 3306 slave
GTIDを使用したレプリケーションの設定
MySQL5.6にてGTIDを有効にするためには、マスターとスレーブ共にMySQLが完全停止 している状態でなければ有効化できません。MySQL5.7からは従来のレプリケーション構成で運用している状態からでもGTIDの有効化が可能となっています。その設定方法は次回紹介します。
my.cnfの設定
まず、第22回で説明したレプリケーションを構成するための必須なサーバ変数は以下となります。
log-bin(バイナリログの有効化)
server-id=NO. ( マスターとスレーブで異なる値を記述すること)
そして、GTIDを有効にするためのサーバ変数は以下になります。
gtid-mode=ON(GTIDの有効化)
enforce-gtid-consistency=true(GTIDの一貫性を有効化)
log-slave-updates(スレーブでもバイナリログを記述する設定)
# vim /etc/my.cnf
log-bin
server-id=1
log-slave-updates
gtid-mode=ON
enforce-gtid-consistency=true
gtid-mode=ON
の場合はenforce-gtid-consistency=false
だとMySQLが起動できません。また、MySQL5.6においてはマスターとスレーブともにlog-slave-updates
が必須となり、記述されていないとMySQLが起動できません。
そして、マスターとスレーブ共にMySQLを起動します。
# /etc/init.d/mysqld start
Starting mysqld: [ OK ]
マスターの設定
レプリケーション用のユーザと権限を設定します(ユーザ名:repl、パスワード:replication) 。
mysql> CREATE USER 'repl'@'172.17.0.3' IDENTIFIED BY 'replication';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.17.0.3';
スレーブの設定
従来のレプリケーションであればCHANGE MASTER
構文に現在のマスターのバイナリログの情報を記述する必要がありましたが、GTIDを使用している場合は記述する必要はありません。バイナリログファイル名とバイナリログのポジションを指定する代わりに、MASTER_AUTO_POSITION = 1
と記述し実行します。
MASTER_AUTO_POSITION = 1
とすることで、GTIDを使用してログのポジションを自動的に識別し、スレーブに必要な更新データからレプリケーションを開始することができます。
mysql> CHANGE MASTER TO
MASTER_HOST = '172.17.0.1',
MASTER_PORT = 3306,
MASTER_USER = 'repl',
MASTER_PASSWORD = 'replication',
MASTER_AUTO_POSITION = 1;
そして、レプリケーションを開始します。
mysql> start slave;
これでGTIDを使用したレプリケーション構成は完了です。
GTIDについて
GTIDはコミット済みのトランザクション単位に与えられる一意識別子です。「 server_uuid :(コロン) transaction_id 」で表現されます。
server_uuid …サーバを識別するUUIDとなります。
transaction_id …コミットされたトランザクション順のシーケンス番号です。
たとえば、321e231b-3ce3-11e6-9fe5-0242ac110001:2
のような表示になります。321e231b-3ce3-11e6-9fe5-0242ac110001
がサーバーを識別するUUIDを示し、2
が2番目に実行されたトランザクションとなります。
では、GTIDを使用したレプリケーションを開始してSHOW MASTER INFOでマスターのステータスを確認します。
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000001 | 678 | | | 321e231b-3ce3-11e6-9fe5-0242ac110001:1-7 |
+------------------+----------+--------------+------------------+------------------------------------------+
この例ではExecuted_Gtid_Set
に321e231b-3ce3-11e6-9fe5-0242ac110001:1-7
という値が入っています。321e231b-3ce3-11e6-9fe5-0242ac110001
はマスター自身のserver_uuid です。transaction_idは1-7
という値になっています。これはtransaction_idセットといい、このケースは1番目から7番目までのトランザクションを表します。マスターでこれらのトランザクションが実行されたということです。
続いて、SHOW SLAVE STATUSでスレーブのステータスを確認します(一部表示は割愛しています) 。
mysql> show slave status\G
:
:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
:
:
Retrieved_Gtid_Set: 321e231b-3ce3-11e6-9fe5-0242ac110001:1-7
Executed_Gtid_Set: 321e231b-3ce3-11e6-9fe5-0242ac110001:1-7
Auto_Position: 1
Retrieved_Gtid_Set
の内容はserver_uuid はマスターを指し、1-7
は1番目から7番目までのトランザクションをマスターから受け取ったということです。Executed_Gtid_Set
の内容はこちらも同じくserver_uuid はマスターを指します。1-7
はスレーブで実行されたトランザクションの情報を指しています。よって、この例でのレプリケーションはマスターでの更新は、すべてスレーブで反映されていることがわかります。
GTIDを使用したレプリケーションの制限事項
GTIDを使用したレプリケーションでは制限事項があります。以下の3つの場合はレプリケーションができないためにマスターでエラーとなり実行できません。
CREATE TABLE ... SELECT ステートメント
トランザクション内のトランザクションおよび非トランザクションテーブルの両方を更新する
トランザクション内の CREATE TEMPORARY TABLE ステートメント
それぞれ実行して試してみます。
CREATE TABLE ... SELECT ステートメント
CREATE TABLE ... SELECT
は以下のようなエラーが表示され実行できません。
mysql> CREATE TABLE tbl2 SELECT * FROM tbl1;
ERROR 1786 (HY000): CREATE TABLE ... SELECT is forbidden when @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1.
対処方法としては、先にCREATE TABLE..LIKE
文でテーブルのコピーを作成または通常のCREATE TABLE
文でテーブルを作成しておき、その後INSERT INTO...SELECT
文でデータを投入することで対応可能です。
トランザクション内のトランザクションおよび非トランザクションテーブルの両方を更新する
たとえば、トランザクション非対応のMyISAMのようなストレージエンジンで作成したテーブルと、トランザクション対応のInnoDBストレージエンジンで作成したテーブルが混在したトランザクションを実行すると、MyISAMで作成されたテーブルを更新できません。
以下のようなテーブルを作成して、実行してみます。
innodb_t …InnoDBストレージエンジンで作成したテーブル
myisam_t …MyISAMストレージエンジンで作成したテーブル
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into innodb_t ( id2 ) values (1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into myisam_t ( id2 ) values (1);
ERROR 1785 (HY000): When @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1, updates to non-transactional tables can only be done in either autocommitted st
atements or single-statement transactions, and never in the same statement as updates to transactional tables.
mysql> commit;
mysql> select * from innodb_t;
+----+------+
| id | id2 |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.00 sec)
mysql> select * from myisam_t;
Empty set (0.00 sec)
以上のようにMyISAMのテーブルを更新しようとすると、エラーのため更新できませんでした。結果として、InnoDBのテーブルのデータは追加されていますが、MyISAMのテーブルはデータがありません。しかし、トランザクション内でない場合はMyISAMのテーブルでも更新でき、レプリケーションも行われます。
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into myisam_t ( id2 ) values (1);
Query OK, 1 row affected (0.00 sec)
トランザクション内の CREATE TEMPORARY TABLE ステートメント
トランザクション内でCREATE TEMPORARY TABLE
を実行すると、エラーとなりテンポラリーテーブルの作成ができません。
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> create temporary table tmp1(id int);
ERROR 1787 (HY000): When @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1, the statements CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE can be executed in a non-transactional context only, and require that AUTOCOMMIT = 1. These statements are also not allowed in a function or trigger because functions and triggers are also considered to be multi-statement transactions.
トランザクション内でない場合は作成できます。
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)
mysql> create temporary table tmp1(id int);
Query OK, 0 rows affected (0.01 sec)
まとめ
今回は、GTIDを使用したレプリケーションの設定方法・制限事項とGTIDについて紹介しました。従来のレプリケーションを構成するよりも、GTIDを使用するほうがレプリケーション構築が容易になります。ただし制限事項があるため、すでに運用されているシステムに対してGTIDを導入する場合は注意が必要です。
次回は、レプリケーションエラー時の対応方法や、MySQL5.7で変更されたGTIDの機能等について紹介します。