今回は、いわゆるMySQLでレプリケーションを行う方法を記してみます。非常に今更感がありますが、自分にとってかゆいところに手が届く文献がなかったので、自分でも一度まとめてみようと思いました。
【MySQLにおけるレプリケーションとは】
MySQLにおけるレプリケーションとは、マスターサーバでの更新情報がほぼリアルタイムにスレーブサーバに同期化される仕組みのことを指します。
マスターサーバ上で更新が起こると、バイナリログ(更新ログとも呼ばれる)に更新情報が記録されていきます。スレーブサーバは随時マスターサーバ上の更新情報を追いかけることでマスターサーバ上のデータをスレーブサーバ上で再現していきます。
レプリケーションにはシングルマスタ構成とマルチマスタ構成があり、通常はシングルマスタ構成を使います。シングルマスタ構成は1台のマスターサーバの下に複数台のスレーブサーバがぶらさがっているイメージです。selectなどの参照系SQLコマンドはマスターサーバでもスレーブサーバでも受け付けることができますが、insert、update、deleteといった更新系SQLコマンドはマスターサーバ上で行う必要があります。万が一更新系SQLコマンドをスレーブサーバで実行するとそのスレーブサーバにデータ不整合が起きます。
一方マルチマスタ構成は、各サーバがマスタとスレーブを兼ねるというもので、どのサーバで更新系SQLコマンドを実行しても大丈夫という仕組みです。これだけ聞くとマルチマスタ構成のほうが使い勝手が良さそうですが、シングルマスタ構成と比較すると動作が不安定とのことであまり推奨されていないようです。ですので今回はマルチマスタ構成は無視し、シングルマスタ構成についてのみ記していきます。
【レプリケーションを行う手順】
MySQLでレプリケーションを行う手順はちょっと面倒くさいです。
(1) マスタサーバ上でレプリケーションを許可するスレーブサーバの権限を付与する。
(2) マスタサーバ上でバイナリログを書き出す設定を行う。
(3) マスタサーバのテーブルへの書き込みを止め、現在のバイナリログのファイル名や位置を記録する。
(4) スレーブサーバ上で、マスターサーバを参照する設定を行う。
(5) マスタサーバのデータを、新しく構築するスレーブサーバにコピーする。
(6) スレーブサーバ上で、現在のバイナリログのファイル名や位置を先ほどコピーしたデータと合わせる。
(7) マスタサーバのテーブルへの書き込みを再開する。
(8) スレーブサーバを有効にする。
といった作業が必要になります。
ところで(2)と(3)はマスターサーバからデータや位置情報を持ってきてもいいですが、他のスレーブサーバから持ってきても良いです。稼働中のマスターサーバを止めるのは大変ですが、他のスレーブサーバであれば少しは気が楽です。
【マスターサーバからデータをコピーしてくる場合の手順】
(1) マスタサーバ上でレプリケーションを許可するスレーブサーバの権限を付与する。
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%' IDENTIFIED BY '';
もしくは接続を許可するIPを制限したい場合は以下のようになります。
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'192.168.0.0/255.255.255.0' IDENTIFIED BY '';
(2) マスタサーバ上でバイナリログを書き出す設定を行う。
/etc/my.cnfファイルに下記を追記します。
[mysqld]
log-bin
server-id=1
(3) マスタサーバを止め(もしくはテーブルへの書き込みを止めるだけでもOK)、現在のバイナリログのファイル名や位置を記録する。
mysql> FLUSH TABLES WITH READ LOCK;
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000039 | 17510192 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
画面に出力された現在のバイナリログのファイル名(File)や位置(Position)をメモしておきます。
(4) スレーブサーバ上で、マスターサーバを参照する設定を行う。
スレーブサーバの/etc/my.cnfファイルに下記を追記します。(※server-idは他のマスター、スレーブで設定した数とは異なった数にする必要があります。1以上の整数が有効となります)
[mysqld]
server-id=2
(5) マスタサーバのデータを、新しく構築するスレーブサーバにコピーし、スレーブサーバ上で展開する。
マスターサーバ上で以下の手順を行う。
# cd /var/lib/
# tar cvf /tmp/mysql.tar mysql
# scp /tmp/mysql.tar username@slave.example.com:/tmp/
# rm -f /tmp/mysql.tar
そしてスレーブサーバ上で以下の手順を行う。
# service mysqld stop
# cd /var/lib
# mv mysql mysql_old
# tar xvf /tmp/mysql.tar
# rm -f /tmp/mysql.tar
# service mysqld start
(6) スレーブサーバ上で、スレーブサーバのステータスを確認します。
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 10.0.0.1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 17510192
Relay_Log_File: mysqld-relay-bin.000024
Relay_Log_Pos: 80878039
Relay_Master_Log_File: mysql-bin.000039
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: 17510192
Relay_Log_Space: 80878039
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
この中の特に以下の内容が(3)でメモした内容と一致しているか確認します。
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 17510192
一致していなければ、現在のバイナリログのファイル名や位置を先ほどコピーしたデータと合わせます。
mysql> CHANGE MASTER TO
MASTER_HOST='10.0.0.1',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000039',
MASTER_LOG_POS=17510192;
エラーが出たら適切に対応します。
ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log
mysql> reset slave;
の後、「CHANGE MASTER TO~」を再度実行する。
(7) マスタサーバのテーブルへの書き込みを再開する。
mysq> UNLOCK TABLES;
(8) スレーブサーバを有効にする。
mysql> START SLAVE;
そしてスレーブサーバの動作を確認します。
mysql> show slave status \G
~中略~
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
~中略~
両方ともYesであれば成功です。
【スレーブサーバからデータをコピーしてくる場合の手順】
さて、次はスレーブサーバからデータをコピーしてくる場合の手順を記します。この手順が他のホームページやブログにはなかなか載ってなかったのです。とは言っても手順はほぼ同じです。違うところだけ記していきます。
(1) マスタサーバ上でレプリケーションを許可するスレーブサーバの権限を付与する。
同じ
(2) マスタサーバ上でバイナリログを書き出す設定を行う。
同じ
(3) 他のスレーブサーバを止め、現在のバイナリログのファイル名や位置を記録する。
mysql> stop slave;
mysql> show slave status;
~中略~
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 17510192
~中略~
画面に出力された現在のバイナリログのファイル名(File)や位置(Position)をメモしておきます。
(4) スレーブサーバ上で、マスターサーバを参照する設定を行う。
同じ
(5) 他のスレーブサーバのデータを、新しく構築するスレーブサーバにコピーし、スレーブサーバ上で展開する。
他のスレーブサーバ上で以下の手順を行う。
# service mysqld stop
# cd /var/lib/
# tar cvf /tmp/mysql.tar mysql
# scp /tmp/mysql.tar username@slave.example.com:/tmp/
# rm -f /tmp/mysql.tar
# service mysqld start
そしてスレーブサーバ上で以下の手順を行う。
# service mysqld stop
# cd /var/lib
# mv mysql mysql_old
# tar xvf /tmp/mysql.tar
# rm -f /tmp/mysql.tar
# service mysqld start
(6) スレーブサーバ上で、現在のバイナリログのファイル名や位置を先ほどコピーしたデータと合わせる。
同じ。ただ多分この作業は必要ないです。
(7)は必要なし
(8) スレーブサーバを有効にする。
同じ
【余談】
多くのサイトではマスターサーバ1台+スレーブサーバ1台の2台構成となっていると思います。しかし予備のスレーブサーバを1台足して3台構成としておくと便利です。
もし予備のスレーブサーバあると、スレーブサーバを増強しようとしたときに、本稼働中のスレーブサーバを止めずとも増強を行うことが可能となります。またバックアップや集計といったサービスとは関係ないけれども重いDB処理を行いたいときには重宝します。
Recent Comments