Semisynchronous Replication (半同期レプリケーション?)を試してみた
今までの非同期レプリケーションでは、同期完了前にマスターが死んだ場合に、データのロストが起きるが、MySQL5.5から導入された Semisynchronous Replication(半同期?)を使うと、スレーブ側のバイナリログの更新までが同期で行われるのでデータのロストの可能性がぐっと減る。今回はMySQL5.5.5_m3 というバージョンを使って検証した。
OSは、CentOS5.5-64bit。RPMはOracle のサイトからダウンロード。
MySQL-client-5.5.5_m3-1.rhel5.x86_64.rpm MySQL-server-5.5.5_m3-1.rhel5.x86_64.rpm MySQL-devel-5.5.5_m3-1.rhel5.x86_64.rpm MySQL-shared-compat-5.5.5_m3-1.rhel5.x86_64.rpm
テストを簡単にするためにDBはtestを使用し、テーブル無しの状態から。
master:10.0.7.8、 slave:10.0.7.8 とする。
- マスター側の設定
プラグインのインストールとユーザ追加
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'pw'; #レプリケーション用のユーザの作成 mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; #レプリケーション用のユーザへの「REPLICATION SLAVE」権限設定
/etc/my.cnfの編集
[mysqld] log-bin=mysql-bin server-id=1 innodb_flush_log_at_trx_commit=1 sync_binlog=1 rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=10
ログの位置確認
mysql> SHOW MASTER STATUS; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 107 | | | +------------------+----------+--------------+------------------+
上記の値を以下で使用する。
- スレーブ側の設定
プラグインのインストール
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
/etc/my.cnfの編集
[mysqld] server-id=2 rpl_semi_sync_slave_enabled=1
mysql> CHANGE MASTER TO MASTER_HOST='10.0.7.8', MASTER_USER='repl', MASTER_PASSWORD='pw', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=107; mysql> STOP SLAVE IO_THREAD; mysql> START SLAVE IO_THREAD; mysql> START SLAVE;
- テスト開始
マスター側
mysql> CREATE TABLE `t1` (`id` int(11) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; mysql> INSERT INTO `t1` VALUES(1); mysql> INSERT INTO `t1` VALUES(2); mysql> INSERT INTO `t1` VALUES(3); mysql> SELECT * FROM `t1`; +------+ | id | +------+ | 1 | | 2 | | 3 | +------+ 3 rows in set (0.01 sec)
スレーブ側
mysql> SELECT * FROM `t1`; +------+ | id | +------+ | 1 | | 2 | | 3 | +------+ 3 rows in set (0.01 sec)
これでは、semisynchronousレプリケーション なのか、asynchronous レプリケーション のどちらでレプリケーションされたかわからない。
次に、SLAVE側のSQL_THREADを停止して、ログの位置を確認する。(878)
スレーブ側
mysql> STOP SLAVE SQL_THREAD; mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** <省略> Read_Master_Log_Pos: 878 Exec_Master_Log_Pos: 878 <省略> 1 row in set (0.00 sec)
次にマスター側にレコードを追加してログの位置を確認する。「1062」まで進んでいるのがわかる。
mysql> INSERT INTO `t1` VALUES(4); mysql> SELECT * FROM `t1`; +------+ | id | +------+ | 1 | | 2 | | 3 | | 4 | +------+ 4 rows in set (0.00 sec) mysql> SHOW MASTER STATUS\G *************************** 1. row *************************** File: mysql-bin.000002 Position: 1062 Binlog_Do_DB: Binlog_Ignore_DB: 1 row in set (0.00 sec)
次にスレーブ側のログの位置を確認する。「1062」まで作成されているが、「878」までしか実行されていない。テーブルの中身を確認すると3レコードのまま。
mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Read_Master_Log_Pos: 1062 Exec_Master_Log_Pos: 878 mysql> SELECT * FROM `t1`; +------+ | id | +------+ | 1 | | 2 | | 3 | +------+ 3 rows in set (0.00 sec)
semisynchronousレプリケーション により、バイナリログは正常に同期されていることがわかる。この時点で、マスター側を停止しても、スレーブ側へのレプリケーションが問題なく行われることを確認する。
マスター側のMySQLを停止する。
# service mysql stop
スレーブ側のSQL_THREADを再開する。ログの位置が「1062」まで実行されている。テーブルの中身を確認すると4レコードに増えていることを確認する。
mysql> START SLAVE SQL_THREAD; mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Read_Master_Log_Pos: 1062 Exec_Master_Log_Pos: 1062 mysql> SELECT * FROM `t1`; +------+ | id | +------+ | 1 | | 2 | | 3 | | 4 | +------+ 4 rows in set (0.01 sec)