June 27, 2014 by Stephane Combaudon
MySQL Utilitiesは、Oracleが提供する、色々なMySQLの管理タスクを行うためのツールの集まりだ。GTIDレプリケーションが有効なら、mysqlrpladminとmysqlfailoverの2つは、スレーブのマスタ昇格を行うのに役立つツールだ。この記事では、mysqlrepladmin(1.4.3)を見てみよう。
概要
- mysqlrpladminは、GTIDレプリケーションが有効な時、手動でのフェイルオーバ・スイッチオーバを実行できる
- 各MySQLサーバで
--master-info-repository=TABLE
を有効にしておくか、ツールを実行する時に--rpl-user
オプションをつける必要がある - 現在のGAバージョンである1.4.3では、不正なトランザクション(訳注 : スレーブに直接実行されるトランザクション)の検出に失敗してしまうので、使用の際には十分に注意し、バグID73110に注意して修正版がコミットされるか確認しよう
- いくつかの制限が残っている。例えば、スレーブを設定ファイルに書いておけなかったり、実際のフェイルオーバ、スイッチオーバを実行せずに、ツールの動作を検証することができなかったりといった点だ。
フェイルオーバとスイッチオーバ
mysqlrpladminは、マスタがダウンした時にスレーブを新しいマスタに昇格し、その後レプリケーションの再設定を行うことができる。これには2つのシナリオがある。1つが計画していない昇格(フェイルオーバ)で、もう1つが計画済みの昇格(スイッチオーバ)だ。言葉の上では違いはあるが、ツールの実行方法としては密接な関係がある。
テストのためのセットアップ
テスト環境は、マスタ1台とスレーブ2台、全てGTIDレプリケーションを使用する。mysqlrpladminでは、healthコマンドで現在のレプリケーショントポロジを表示することができる。
$ mysqlrpladmin --master=root@localhost:13001 --discover-slaves-login=root health
# Discovering slaves for master at localhost:13001
# Discovering slave at localhost:13002
# Found slave: localhost:13002
# Discovering slave at localhost:13003
# Found slave: localhost:13003
# Checking privileges.
#
# Replication Topology Health:
+------------+--------+---------+--------+------------+---------+
| host | port | role | state | gtid_mode | health |
+------------+--------+---------+--------+------------+---------+
| localhost | 13001 | MASTER | UP | ON | OK |
| localhost | 13002 | SLAVE | UP | ON | OK |
| localhost | 13003 | SLAVE | UP | ON | OK |
+------------+--------+---------+--------+------------+---------+
# ...done.
見ての通り、マスタへの接続情報を書いてやる必要がある(当然ではある)が、スレーブに対しての情報は書かなくてもツールが勝手に見つけてくれるようになっている。
単純なフェイルオーバ
フェイルオーバ時にこのツールはどのように動作するのだろう?基本的には、スレーブの一覧と、昇格候補の一覧を与えるだけで、以下のように動作する。
- いくつかの健全性チェックを実行
- 新しいマスタになる候補を選ぶ
- 新マスタ候補を他の全てのスレーブに対して可能な限り最新の状態にする
- 全てのスレーブを新マスタからレプリケーションするように設定
マスタをkill -9で停止して、フェイルオーバを実行してみよう。
$ mysqlrpladmin --slaves=root:@localhost:13002,root:@localhost:13003 --candidates=root@localhost:13002 failover
今回は、マスタがダウンしているのでツールはスレーブを自動的に探し出すことはできない。そのため、--slavesオプションで指定してやる必要がある。
ここで、以下のようなエラーが出てしまった。
# Checking privileges.
# Checking privileges on candidates.
ERROR: You must specify either the --rpl-user or set all slaves to use --master-info-repository=TABLE.
エラーメッセージの内容は明白ではあるが、healthコマンドを実行した時にこういった詳細情報(恐らくエラーではなく警告)が出てくれるとうれしい。そうすれば、緊急事態の最中にどのオプションが不足しているのかドキュメントを見る代わりに、ツールを実行する前にチェックできる。
では、レプリケーションユーザを指定して実行してみよう。
$ mysqlrpladmin --slaves=root:@localhost:13002,root:@localhost:13003 --candidates=root@localhost:13002 --rpl-user=repl:repl failover
# Checking privileges.
# Checking privileges on candidates.
# Performing failover.
# Candidate slave localhost:13002 will become the new master.
# Checking slaves status (before failover).
# Preparing candidate for failover.
# Creating replication user if it does not exist.
# Stopping slaves.
# Performing STOP on all slaves.
# Switching slaves to new master.
# Disconnecting new master as slave.
# Starting slaves.
# Performing START on all slaves.
# Checking slaves for errors.
# Failover complete.
#
# Replication Topology Health:
+------------+--------+---------+--------+------------+---------+
| host | port | role | state | gtid_mode | health |
+------------+--------+---------+--------+------------+---------+
| localhost | 13002 | MASTER | UP | ON | OK |
| localhost | 13003 | SLAVE | UP | ON | OK |
+------------+--------+---------+--------+------------+---------+
# ...done.
単純なスイッチオーバ
旧マスタを再起動して、新マスタのスレーブとして再設定してみよう(ちなみにこれはMySQL Utilitiesのツールであるmysqlreplicateで可能だ)。旧マスタを昇格させたいなら、以下のように実行する。
$ mysqlrpladmin --master=root@localhost:13002 --new-master=root@localhost:13001 --discover-slaves-login=root --demote-master --rpl-user=repl:repl --quiet switchover
# Discovering slave at localhost:13001
# Found slave: localhost:13001
# Discovering slave at localhost:13003
# Found slave: localhost:13003
+------------+--------+---------+--------+------------+---------+
| host | port | role | state | gtid_mode | health |
+------------+--------+---------+--------+------------+---------+
| localhost | 13001 | MASTER | UP | ON | OK |
| localhost | 13002 | SLAVE | UP | ON | OK |
| localhost | 13003 | SLAVE | UP | ON | OK |
+------------+--------+---------+--------+------------+---------+
今回はマスタが動作中だったので、discover-slaves-loginオプションを使うことができた点に注意しよう。また、ツールが出力する情報量を--quietや--verboseで調整したり、--logでログファイルに出力することもできる。
また、--demote-masterで、旧マスタを新マスタのスレーブとして指定している。このオプションをつけないと、旧マスタは他のノードと関係のないマスタになってしまう。
拡張機能
データベースレベルでスイッチオーバ・フェイルオーバをするのはもちろんだが、アプリケーションが正常に動作するには、何らかの変化が起きたということをアプリケーションの他のコンポーネントに知らせる必要がある場合が多いだろう。
ここで紹介する拡張機能が便利なのは、--exec-beforeオプションでスイッチオーバやフェイルオーバの前に、--exec-afterオプションでは後にスクリプトを実行できるということだ。
例えば、以下のような単純なスクリプトを考えよう。
# cat /usr/local/bin/check_before
#!/bin/bash
/usr/local/mysql5619/bin/mysql -uroot -S /tmp/node1.sock -Ee 'SHOW SLAVE STATUS' > /tmp/before
# cat /usr/local/bin/check_after
#!/bin/bash
/usr/local/mysql5619/bin/mysql -uroot -S /tmp/node1.sock -Ee 'SHOW SLAVE STATUS' > /tmp/after
以下のように実行できる。
$ mysqlrpladmin --master=root@localhost:13001 --new-master=root@localhost:13002 --discover-slaves-login=root --demote-master --rpl-user=repl:repl --quiet --exec-before=/usr/local/bin/check_before --exec-after=/usr/local/bin/check_after switchover
/tmp/beforeと/tmp/afterを見てみると、スクリプトがどのように実行されたか確認できる。
# cat /tmp/before
# cat /tmp/after
*************************** 1. row ***************************
Slave_IO_State: Queueing master event to the relay log
Master_Host: localhost
Master_User: repl
Master_Port: 13002
[...]
スクリプトがうまく動かない場合は、--verboseオプションが原因調査に役立つだろう。
不正なトランザクション(スレーブに直接実行されるトランザクション)の処理
GTIDレプリケーションを実行しているクラスタでマスタ昇格を行う場合、不正なトランザクションが多くの問題を引き起こすことについては、既に触れた通りだ。となると疑問なのは、mysqlrpladminは不正なトランザクションをどう扱うのだろうかということだ。
不正なトランザクションを実行してみよう。
# On localhost:13003
mysql> CREATE DATABASE test2;
mysql> FLUSH LOGS;
mysql> SHOW BINARY LOGS;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 69309 |
| mysql-bin.000002 | 1237667 |
| mysql-bin.000003 | 617 |
| mysql-bin.000004 | 231 |
+------------------+-----------+
mysql> PURGE BINARY LOGS TO 'mysql-bin.000004';
そしてlocalhost:13003をマスタに昇格させてみよう。
$ mysqlrpladmin --master=root@localhost:13001 --new-master=root@localhost:13003 --discover-slaves-login=root --demote-master --rpl-user=repl:repl --quiet switchover
[...]
+------------+--------+---------+--------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| host | port | role | state | gtid_mode | health |
+------------+--------+---------+--------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| localhost | 13003 | MASTER | UP | ON | OK |
| localhost | 13001 | SLAVE | UP | ON | IO thread is not running., Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.', Slave has 1 transactions behind master. |
| localhost | 13002 | SLAVE | UP | ON | IO thread is not running., Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.', Slave has 1 transactions behind master. |
+------------+--------+---------+--------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
おっと!ドキュメントには不正なトランザクションもチェックすると書かれているのに、検出してくれなかったようだ。これが、不正なトランザクションが正常に検出されず、GTID環境でのフェイルオーバ・スイッチオーバができないという、大きな問題だ。
ドキュメントには不正なトランザクションは検出されるとあり、コードを見るとそうなっているようではあるが、うまく動いていないようだ。この不具合は報告されている。
制約
不正なトランザクションの処理に関する問題以外にも、以下の制約を見つけた。
- 設定ファイルにスレーブを列挙できない。たくさんのスレーブがある環境では面倒なので、mysqlrpladminのオプションをつけてくれるラッパースクリプトを書くべきだろう。
- 昇格するスレーブを選ぶのは自動的ではあるが、--candidatesオプションに列挙した順番に依存しているのは、洗練された作りとは言えない。
- 実際のフェイルオーバ・スイッチオーバを実行せずに、設定がすべて正しいことを確認する--dry-runモードがあると便利だろう。例えばMHAにはこれが存在している。
結論
mysqlrpladminは、GTIDレプリケーションを使っている環境で、手動フェイルオーバ・スイッチオーバを行うのに便利なツールだ。現時点では、不正なトランザクションの検出に失敗するので、ツールの実行時には注意が必要になる。