gtidを使用した環境でのmysqldump
以前の日記Global Transaction IDを使ってレプリケーション構成とした際の制限でmysqldumpから新規にスレーブを作ろうとするとgtidが記録されなくてバイナリログ使わないとダメ、と書いたんだけど、5.6.10で試したら普通にスレーブを作成可能だったので訂正も含めて書きます。
よくあるmysqldump
MySQL5.5系まででgtidが存在しない環境では良く以下のようにmysqldumpを実行しているかと思います(InnoDBのみ利用の場合)。
# mysqldump --all-databases --single-transaction --master-data=2 > /path/to/dir/dump または # mysqldump --all-databases --single-transaction --master-data=2 | gzip > /path/to/dir/dump.gz イベントスケジューラーとかその他色々使ってる場合 # mysqldump --all-databases --single-transaction --master-data=2 --triggers --routines --events > /path/to/dir/dump
なお、gtidを利用した環境では--triggers --routines --eventsオプションを使用しない場合は以下のようにWarningが出力されます。
# mysqldump --all-databases --single-transaction --master-data=2 > /tmp/dump Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. #
gtid環境でmysqldumpを取得した場合のダンプファイル
上記のmysqldump実行例の以下内容でダンプを取得します。
# mysqldump --all-databases --single-transaction --master-data=2 --triggers --routines --events > /path/to/dir/dump
ダンプファイルの中身を覗いてみます。
# mysqldump --all-databases --single-transaction --master-data=2 --triggers --routines --events > /tmp/dump # head -30 /tmp/dump -- MySQL dump 10.13 Distrib 5.6.10, for Linux (x86_64) -- -- Host: localhost Database: -- ------------------------------------------------------ -- Server version 5.6.10-log /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN; SET @@SESSION.SQL_LOG_BIN= 0; -- -- GTID state at the beginning of the backup -- SET @@GLOBAL.GTID_PURGED='71803be2-7816-11e2-8c99-5254003e1cec:1-665'; -- -- Position to start replication or point-in-time recovery from -- -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=197930;
ここで見慣れない以下内容が記録されています。
SET @@GLOBAL.GTID_PURGED='71803be2-7816-11e2-8c99-5254003e1cec:1-665';
gtid関連のパラメータとして、MySQL5.6.10では以下パラメータが存在しています。以下はMaster側のダンプを取得したMySQLの内容です。
mysql> show global variables like '%gtid%'; +--------------------------+--------------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------------+ | enforce_gtid_consistency | ON | | gtid_executed | 71803be2-7816-11e2-8c99-5254003e1cec:1-665 | | gtid_mode | ON | | gtid_owned | | | gtid_purged | | +--------------------------+--------------------------------------------+ 5 rows in set (0.00 sec) mysql> show variables like '%gtid%'; +--------------------------+-----------+ | Variable_name | Value | +--------------------------+-----------+ | enforce_gtid_consistency | ON | | gtid_executed | | | gtid_mode | ON | | gtid_next | AUTOMATIC | | gtid_owned | | | gtid_purged | | +--------------------------+-----------+ 6 rows in set (0.00 sec) mysql>
global無しを書いたのはgtid_nextはsessionのみのパラメータのためです。
リストアしてみる
今回ポイントとなるのはgtid_executedとgtid_purgedの2つ。先に記載のダンプファイルの内容から、リストアした場合はgtid_purgedに値が設定されることが分かります。実際に空の、新しく立ち上げたMySQLへリストアを行います。
まずはリストア前のgtid関連のパラメータの状態
mysql> show global variables like '%gtid%'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | enforce_gtid_consistency | ON | | gtid_executed | | | gtid_mode | ON | | gtid_owned | | | gtid_purged | | +--------------------------+-------+ 5 rows in set (0.00 sec) mysql>
リストアを行って確認します。
# mysql < /tmp/dump # mysql mysql> show global variables like '%gtid%'; +--------------------------+--------------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------------+ | enforce_gtid_consistency | ON | | gtid_executed | 71803be2-7816-11e2-8c99-5254003e1cec:1-665 | | gtid_mode | ON | | gtid_owned | | | gtid_purged | 71803be2-7816-11e2-8c99-5254003e1cec:1-665 | +--------------------------+--------------------------------------------+ 5 rows in set (0.00 sec) mysql>
gtid_executedをgtid_purgedがセットされました。ダンプファイルに書いてあったのはgtid_purgedだけだったのに?
では公式ドキュメントのgtid_purgedとgtid_executedを見てみましょう。以下ざっくりと。
- gtid_executed
- 適当にまとめると、globalスコープの場合はgtid_executedに書かれてるgtidまでバイナリログに書いてあるよ、って事だと思います。read_onlyなパラメータで空にしたいならreset master;実行してね。5.6.9より前はgtid_doneってパラメータ名だったよ。
- gtid_purged
- こちらも適当にまとめると、gtid_purgedに書かれているgtidまではバイナリログから削除されてるよ。5.6.9より前はgtid_lostってパラメータ名。gtid_executedが空の場合だけset可能だよ。
なんか訳すと矛盾してるような気分になりますが、gtid_executedは設定されているgtidまでは実行済みだよってことだし、新規にダンプファイルから上記の流れでスレーブを作った場合はバイナリログにリストアされた内容は記録されていなかったりします。
# mysqlbinlog ./mysql-bin.000004 /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; # at 4 #130309 2:22:35 server id 239 end_log_pos 120 CRC32 0x4fbf920d Start: binlog v 4, server v 5.6.10-log created 130309 2:22:35 # Warning: this binlog is either in use or was not closed properly. BINLOG ' Wx46UQ/vAAAAdAAAAHgAAAABAAQANS42LjEwLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAQ2S v08= '/*!*/; # at 120 #130309 2:22:35 server id 239 end_log_pos 191 CRC32 0x28155e76 Previous-GTIDs # 71803be2-7816-11e2-8c99-5254003e1cec:1-665 DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; #
なんで?と思われた方、上の方で書いたダンプファイルのhead -30の結果を再度見てみましょう。必要なポイントだけ抜粋したのが以下になります。
SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN; SET @@SESSION.SQL_LOG_BIN= 0;
SQL_LOG_BIN=0が発行されています。よってリストアで発行された更新処理はバイナリログに記録されません。gtid_purgedがgtid_executedが同じなのは間違いではないことが分かります。
ということでスレーブではgtid_executedに設定されているgtidまで更新内容が反映済みという状態となります。この状態でchange master toでmaster_auto_position=1でレプリケーションを開始します。
mysql> change master to master_host='192.168.1.237', master_user='repl', master_password='repl-pw', master_auto_position=1; Query OK, 0 rows affected, 2 warnings (0.03 sec) mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.1.237 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: Read_Master_Log_Pos: 4 Relay_Log_File: mysql-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 0 Relay_Log_Space: 151 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0 Master_UUID: Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:1-665 Auto_Position: 1 1 row in set (0.00 sec) mysql>
正しくExecuted_Gtid_Setにgtidが設定されている事が分かります。
Executed_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:1-665
ではstart slave;を行いましょう。
mysql> start slave; Query OK, 0 rows affected (0.02 sec) mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.237 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000006 Read_Master_Log_Pos: 200338 Relay_Log_File: mysql-relay-bin.000007 Relay_Log_Pos: 2816 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 200338 Relay_Log_Space: 3230 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 237 Master_UUID: 71803be2-7816-11e2-8c99-5254003e1cec Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:666-673 Executed_Gtid_Set: 71803be2-7816-11e2-8c99-5254003e1cec:1-673 Auto_Position: 1 1 row in set (0.00 sec) mysql>
問題無くレプリケーションが開始されました。良いですね。gtid環境でもmysqldumpが普通に使えます。
その他
今回は書きませんが、gtidを使ったSlaveサーバから--dump-slave=2とかでダンプを取った場合も同様に新しいSlaveを作成可能です。但し、その場合はリストアするMySQLは極力真っ新な状態の物を使う事を推奨します。クラッシュセーフなSlaveにするために以下パラメータをTABLEにしてる場合、バイナリログ、リレーログファイルの情報がダンプ元のサーバの情報になってしまうためです。
master_info_repository=TABLE relay_log_info_repository=TABLE
--dump-slaveを使う事が最初から予定されている場合は全てのMaster, Slaveで以下のようにバイナリログ、リレーログファイル名を統一しておくと良いでしょう。手間が掛からなくなります。
log-bin=mysql-bin relay_log=mysql-relay-bin
まぁ"ホスト名"-binとかの形には本来はしない方が良い(個人的にホスト名が付くのは非推奨)ので、既にちゃんと指定してるよ、という方も多いかと思います。
また、gtidを利用してない環境にリストアするためにダンプを取得する場合はmysqldumpに--set-gtid-purged=OFFを付けます。あまり無いだろうけど、あえて5.5系とか。このオプションを付ける事でgtidを使用した環境からのダンプファイルに以下内容が出力されなくなります。
SET @@GLOBAL.GTID_PURGED='71803be2-7816-11e2-8c99-5254003e1cec:1-665';
終わりに
MySQL 5.6.10ではgtidを利用した環境でもgtidを特に意識せず、mysqldumpによるダンプファイルから新規にSlaveが作成出来ます。gtid環境でネックだなぁ、と思ってた内容が一つ解消したのは個人的には嬉しい所です。