検証環境
- CentOS 7.3
- MariaDB 10.1.24
- DBマスタサーバ(IP: 192.168.0.1)
- DBスレーブサーバ(IP: 192.168.0.2)
MySQLでGTID有効のレプリケーション構築を行う手順とは大きく異なりますのでご注意ください。
レプリケーション構築に関するMySQLとの違い
MariaDB10.0以降であればGTIDの設定をするだけでクラッシュセーフになるようです。
MySQL5.6以降と異なり、MariaDBは GTID(Global Transaction ID)がデフォルトで有効になっています。
したがって、設定ファイルにGTIDモードを有効にするための以下設定を書く必要はありません。
(※ 書いたらエラーで起動しなくなります)
gtid-mode = ON
enforce-gtid-consistency
また、GTIDの状態は mysql.gtid_slave_pos テーブルに書き込まれるため、以下設定も同様に必要ありません。
relay_log_info_repository = TABLE
relay_log_recovery = ON
######MariaDBとMySQLの設定値の違いは公式に記載があります。
System Variable Differences Between MariaDB 10.1 and MySQL 5.6
System Variable Differences Between MariaDB 10.1 and MySQL 5.7
1. 事前準備
初めてレプリケーション構築を行う場合、このステップは飛ばして結構です。
もし既存のレプリケーションやログが残っているDBで新たに構築し直す場合、ログをクリアしておく必要があります。
この作業を怠るとダウンしたマスタをスレーブ群に加える際、誤動作の原因となるようなので注意してください。
STOP SLAVE;
RESET SLAVE ALL;
DELETE FROM `mysql`.`gtid_slave_pos`;
RESET MASTER;
datadir(デフォルト /var/lib/mysql) に既存のバイナリログが出力されている場合は退避しておきます。
# バイナリログのファイル名を "slave-bin" と指定している場合
$ mkdir mysqlbak-yyyymmdd
$ mv /var/lib/mysql/slave-bin.* ./mysqlbak-yyyymmdd
2. マスタ側にレプリケーション用ユーザを作成
レプリケーションのみ権限を付与したユーザを用意しておきます。
CREATE USER 'repl'@'192.168.0.2' IDENTIFIED BY '[パスワード]';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.2';
FLUSH PRIVILEGES;
3. マスタ側の設定ファイルを編集
systemctl stop mariadb
vi /etc/my.cnf.d/server.cnf
[mysqld]
server-id = 1 # スレーブと異なるサーバIDにする
log-bin=master-bin # 任意のバイナリログファイル名
binlog-format = ROW
log-slave-updates
systemctl start mariadb
datadir(デフォルト /var/lib/mysql) にlog-bin
で設定したファイル名のバイナリログが出力されているか確認します。
また、設定が正常に反映されているかどうかは、以下の方法で確認できます。
SHOW VARIABLES LIKE 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id | 1 |
+---------------+-------+
4. スレーブの設定ファイルを編集
systemctl stop mariadb
vi /etc/my.cnf.d/server.cnf
[mysqld]
server-id = 2 # マスタと異なるサーバIDにする
read_only # 意図しない改変を防ぐために推奨
log-bin=slave-bin # 任意のバイナリログファイル名
log-slave-updates
systemctl start mariadb
datadir(デフォルト /var/lib/mysql) にlog-bin
で設定したファイル名のバイナリログが出力されているか確認します。
5. マスタのダンプファイルを取得
mysqldump --all-databases -u root -p --master-data=2 --single-transaction --routines > dump.sql
ダンプファイルから CHANGE MASTER TO
と書かれた行を検索し、バイナリログファイル名とポジションをメモしておきます。
私の環境の場合、grep
使うとかなり長い文字列でヒットしてしまったため、vi
で開いて/
検索しました。
CHANGE MASTER TO MASTER_LOG_FILE='xxxxx-bin.000001', MASTER_LOG_POS=xxx;
【2017.12.08 追記】
SHOW MASTER STATUS
クエリを実行することで、ダンプファイルを直接開いて検索する方法と同様にバイナリログファイル名とポジションを取得可能なようです(記事コメント欄参照)。
6. マスタの現時点でのGTIDを調べる
さきほどメモしたバイナリログファイル名とポジションをもとに、現時点でのGTIDを調べます。
SELECT BINLOG_GTID_POS( "xxxxx-bin.000001", xxx );
MariaDBのGTIDは**「ドメインID + サーバID + サーバーごとのトランザクション番号」**というフォーマットで構成されています。
'0-1-1' のような形式のGTIDがヒットするはずなので、またメモしておきます。
※ ここで空が返ってきてしまう場合、何かしら適当なUPDATE文を投げてMariaDBの再起動を行い、ダンプ取得の手順からやり直せばヒットするようになります。
7. スレーブにリストア
マスタのダンプファイルをもとにスレーブ側でリストアします。
mysql -f -u root -p < dump.sql
8. スレーブにGTIDを設定する
手順6でメモしておいたGTIDを設定します。
SET GLOBAL gtid_slave_pos = '0-1-1';
9. CHANGE MASTERの実行とスレーブ開始
スレーブ側で以下を実行します。
CHANGE MASTER TO
MASTER_HOST = '192.168.0.1',
MASTER_USER = 'repl',
MASTER_PASSWORD = '[replユーザのパスワード]',
MASTER_USE_GTID = slave_pos;
START SLAVE;
SHOW SLAVE STATUS \G
CHANGE MASTER TO
の設定内容は /var/lib/mysql/master.info
に反映されます。
START SLAVE
でスレーブを開始後、SHOW SLAVE STATUS
でステータスを表示します。
以下のステータスが返ってくれば問題ありません。
Slave_IO_State | Waiting for master to send event |
---|---|
Slave_IO_Running | Yes |
Slave_SQL_Running | Yes |
Last_Errno | 0 |
Last_Error | |
Last_IO_Errno | 0 |
Last_IO_Error | |
Last_SQL_Errno | 0 |
Last_SQL_Error | |
Gtid_IO_Pos | [設定したGTID] |
GTIDの状態は以下の方法でも確認可能です。
SELECT * FROM `mysql`.`gtid_slave_pos`
+-----------+--------+-----------+--------+
| domain_id | sub_id | server_id | seq_no |
+-----------+--------+-----------+--------+
| 0 | 1 | 1 | 1 |
+-----------+--------+-----------+--------+
10. 動作確認して設定完了
マスタ側で適当なUPDATE文を流してみて、更新がスレーブ側にも反映されていれば作業完了です。
【Case1】 マスタが落ちた場合
以降の手順は未検証です。メモ書き程度にご参考ください。
マスタ(192.168.0.1 以降、旧マスタ)が落ちてしまい、
スレーブ(192.168.0.2)を新マスタに昇格させる必要がある場合、
スレーブ群(192.168.0.3〜)にマスタの変更を通知する必要があります。
CHANGE MASTER TO
MASTER_HOST = '新マスタIP(192.168.0.2)',
MASTER_PORT=3307; -- ポート番号の指定が必要な場合
これでスレーブ → マスタ昇格の作業自体は完了ですが、
旧マスタからスレーブに転送し損ねたGTIDが無いか、後々チェックしておく必要があります。
-- 件数が莫大になる可能性もあるのでLIMITは必ず付与する
SHOW BINLOG EVENTS IN 'xxxxx-bin.000001' LIMIT 20 \G
*************************** 1. row ***************************
Log_name: xxxxx-bin.000001
Pos: xxx
Event_type: Gtid
Server_id: 1
End_log_pos: xxx
Info: BEGIN GTID 1-1-4
最後に出力された Info: BEGIN GTID
に記載のGTIDが最新ということになると思います。
mysqlbinlog
を使って確認することもできます。
もし、未転送のGTIDがある場合、新マスタをいったん旧マスタのスレーブ構成にして、そのGTIDでスレーブを開始すると補填できるようです。
正直、ここの流れが具体的によく分かっていません。
→ 新マスタを停止 & 旧マスタ起動
→ SET GLOBAL gtid_slave_pos = '未転送のGTID';
→ CHANGE MASTER TO & START SLAVE
で一時的に旧マスタのスレーブ化
→ 同期できたら STOP SLAVE & CHANGE MASTER TO
の設定をクリアする
という流れでしょうか…。
未転送のGTIDで操作したレコードと同レコードに対して、すでに新マスタ側で何かしらの操作が行われている場合はどうなるの?という疑問があります。
(見当違いなことを言っているかもしれない)
【Case2】 落ちた旧マスタをスレーブ化する
落ちてしまった 旧マスタ(192.168.0.1)が復旧したら、スレーブ化します。
レプリケーション用のユーザは事前作成しておく必要があるので注意してください。
CHANGE MASTER TO
MASTER_HOST = '新マスタIP(192.168.0.2)',
MASTER_USER = 'repl',
MASTER_PASSWORD = '[replユーザのパスワード]',
MASTER_USE_GTID = current_pos;
MASTER_USE_GTID
に slave_pos
ではなく current_pos
を設定している点に注意が必要です。
gtid_slave_pos | スレーブSQLスレッド(*1)が最後に実行したトランザクションのGTID |
---|---|
gtid_current_pos | 最後に処理したトランザクションのGTID(*2) |
(*1)マスタから転送されたトランザクションのうち、最後に実行されたGTID
(*2)スレーブが直接実行したSQL(エラー修復など)も含む、最後に実行されたGTID
-> *2 は自身のサーバのみで実行されたGTID(他のサーバに存在しないGTID)を含んでいる
旧マスタはもともとスレーブではないため、slave_pos 自体をまだ持っていません。
そのため、まずは current_pos
で自身の最新GTIDをセットしているわけです。
START SLAVE
でいったん同期すれば、MASTER_USE_GTID = slave_pos
に変更してOKだと思います。
ただし、最新のGTIDが分かっているなら以下の手順でも構わないようです(手順8〜9と同じ)。
SET GLOBAL gtid_slave_pos = 'x-x-xxx';
CHANGE MASTER TO
-- (...中略...)
MASTER_USE_GTID = slave_pos;