MySQL道普請便り

第24回GTIDを使用したレプリケーション構成を作成する[1]

従来のMySQLのレプリケーションでは、新規にスレーブを追加する際にマスターのバイナリログファイル名とバイナリログファイルのポジションを指定する必要がありました。

MySQL 5.6.5から追加された機能であるグローバルトランザクション識別子(GTID)を使用することで、マスターのバイナリログファイル名とバイナリログファイルのポジションを指定することなく、容易にレプリケーションを構成・開始できるようになります。今回はGTIDを使用したレプリケーション構成について紹介いたします。

環境構築

第22回 特定のSQL文が原因で発生したレプリケーション遅延の調査方法で紹介した方法にて、MySQLのインストールまで環境構築します。今回のMySQLのバージョンはMySQL5.6.31です。

構成は以下のようになっています。

IPMySQL PORTmaster/slave
172.17.0.13306master
172.17.0.33306slave

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_Set321e231b-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つの場合はレプリケーションができないためにマスターでエラーとなり実行できません。

  1. CREATE TABLE ... SELECT ステートメント
  2. トランザクション内のトランザクションおよび非トランザクションテーブルの両方を更新する
  3. トランザクション内の 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の機能等について紹介します。

おすすめ記事

記事・ニュース一覧