以前の記事 mysqlのレプリケーションを使う で mysqlを使ったレプリケーションの設定を行ってみました。
今回は、そのmysqlのレプリケーションでも、マルチマスター型レプリケーションの設定を行ってみます。
( 以前の記事 mysqlのレプリケーションを使う で 設定したのは、マスタースレーブ型レプリケーションなどと言われています。 )
直訳のとおり複製を意味します。(レプリカ(replica)と語源は一緒なので、こちらがピンとくるかもしれません)
一般的に、mysqlでレプリケーションと言うと、マスタースレーブ型のレプリケーションをさすことが多いです。
その場合、マスター1台に対して、スレーブ複数台というのが一般的な mysqlサーバーの構成になります。
以下の図のように ユーザは、1台のサーバーにアクセスしているつもりですが、実際のデータベースへの書き込み処理は、バックにあるマスターサーバー側で処理され、データベースの読み込み処理は、フロントのスレーブサーバーで処理されます。
これに対してマルチマスター型のレプリケーションというのがあります。
これは、先のマスタースレーブ型のように1台の書き込み用マスターサーバーがあるのではなく、すべてのサーバーがマスターでありスレーブである構成を言います。
上の図は、その典型的なレプリケーションの例を示したものです。
通常、2台で説明することが多いですが、ここでは先にマスタースレーブ型と比較しやすいように複数台にしています。 マスタースレーブ型でスレーブサーバーとしてフロントで読み込み処理を担当していたサーバーが、全てマスター兼スレーブサーバーとしてフロントで処理されます。 そのため、書き込みも読み込みをすべてのサーバーで行います。ただ、レプリケーションなので、コピー作業が、バックグランドで実行されます。 ここでは、複数台あるのでサークル上にリレー的な動作でコピー処理が実行されています。
マスタースレーブ型では、 台数が増えていくとマスターサーバーの負荷がかなり高くなることが予想されますが、マルチマスター型では、その負荷が軽減されることは想像できるでしょう。
ただ、マルチマスター型は、mysqlでは、台数が増えていくとかなりメンテナンスが複雑となり、障害が発生した時のリカバリも難しくなるので推奨されていません。
今回は、マルチマスター型のレプリケーション設定について、簡単に解説してみたいと思います。
- 目次
- 履歴
2012年11月22日 初版
マルチマスターの考え方
マルチマスター型レプリケーションの設定の考え方は、mysqlの場合、非常にシンプルです。
マルチスレーブ型レプリケーションのマスタ、スレーブ双方をそれぞれのサーバーに設定することで対応します。
この図のように双方で読み書きできるので、双方がマスターでありスレーブとなるような動作が要求されます。
これを実現するために、先に書いたように
マルチスレーブ型レプリケーションのマスタ、スレーブ双方をそれぞれのサーバーに設定することになります。
mysqlのバージョンを合わせる
マスター、スレーブにかかわらず全てのレプリケーション設定を行うmysqlのバージョンをすべて同じにします。
mysqlのバージョンを合わせるためには、基本的に最新バージョンに合わせると良いでしょう。
やり方は、
CentOS ScientificLinux なら、yumでアップデートして最新にします。( 参照 : yumでmysql5.1系を最新版へアップデートする)
Debian Ubuntu なら、apt (apt-get ot aptitude)でアップデートして最新にします。
mysqlのレプリケーション設定を行う
今回のマルチマスター型レプリケーションの設定では、サーバーID(server-id)と自動更新オフセット値(auto_increment_offset)以外は、全て同じ設定になります。
ただ、どちらのデータベースを元にするか?で多少の違いがあります。
そこでマスター#1とマスター#2とし、基本となるデータベースは マスター#1とし、
マスター#2へコピーするものとして 以降 解説します。
- mysqlの設定ファイル(my.cnf)を編集します。
設定ファイルのデフォルトディレクトリはOSによって異なります。
CentOS ScientificLinux : /etc/my.cnf
Debian Ubuntu : /etc/mysql/my.cnf
この設定ファイルを以下のように編集します。
マスター#1
... [mysqld] ... # Replication server-id = 101 log-bin = /var/lib/mysqllogs/bin-log ... # Auto Increment auto_increment_increment=5 auto_increment_offset=1 ...
マスター#2
... [mysqld] ... # Replication server-id = 102 log-bin = /var/lib/mysqllogs/bin-log ... # Auto Increment auto_increment_increment=5 auto_increment_offset=2 ...
server-idサーバー種別番号
※1,2 という番号については、mysqlのデフォルト値として用いられる場合があるので、できれば避けた方が良いでしょう。
log-binバイナリログファイルサフィックス名
※この設定例では、/var/lib/mysqllogs/というディレクトリ配下に、bin-log.xxxの名前でバイナリログファイルが作成されていきます。
auto_increment_increment自動更新更新値
auto_increment_offset自動更新オフセット値
上記の2つの値は、ペアで用いられ、テーブルのAUTO_INCREMENT カラムの操作の制御に使用されます。
例えば、以下のようなテーブルがあったといましょう。
CREATE TABLE autoinc1( col INT NOT NULL AUTO_INCREMENT PRIMARY KEY );
colは、AUTO_INCREMENTで定義されていますから、insertされたら自動的に数値が振られていきます。
そこで、以下のようなinsert文を発行したとします。
INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
これで、selectで参照してみると以下のようになります。
> select * from autoinc1; +-----+ | col | +-----+ | 1 | | 6 | | 11 | | 16 | +-----+
つまり、最初の値は1(auto_increment_offset=1の場合)となり、次に自動で振られる値は、+5(auto_increment_increment=5の場合)=6となります。
マスター#1とマスター#2とでは、auto_increment_offsetの値を異にし、同じ値にならないように設定します。
- マスター#1 : mysqlの書き込みを一時停止してバックアップを作成する。
まず 元となるデータベースサーバーであるマスター#1 の mysqlの更新を一時停止する。
$ mysql -uroot -p -Dmysql password : mysql> FLUSH TABLES WITH READ LOCK; Query OK, 0 rows affected (0.01 sec)
別のシェルからtarでmysqlのバックアップファイルを作成する。
$ cd /var/lib $ tar cvfz /tmp/mysql-bin.tar.gz mysql ...
tarで丸めてしまうのは、mysqlのデータディレクトリになります。
ここでは、そのディレクトリが、/var/lib/mysql としています。
mysqlのデータディレクトリは、mysqlの設定ファイル(/etc/my.cnf)を確認するとわかります。
この例では、ディレクトリは、/var/lib/mysql です。datadir = /var/lib/mysql
- マスター#1 : mysqlのバックアップした状態を確認する。
ここでマスター#1 の バックアップした状態が、mysqlのどのような状態だったか確認しておきます。
後に、ここで表示された情報を元にスレーブ側の設定が必要となりますので、表示された情報は、すべて書きとめておきましょう。
先にmysqlの更新を一時停止したシェルを使います。
mysql> SHOW MASTER STATUS; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | mysql-bin.003 | 73 | test | manual,mysql | +---------------+----------+--------------+------------------+
ここで、以下のように表示されることがあります。
これは、何も情報がないと言っているだけでエラーではありません。mysql> SHOW MASTER STATUS; Empty set (0.02 sec)
※まだ、バイナリログを使用していない場合は、このように表示されます。
Emptyだったことを書きとめておきましょう。
- マスター#1 : mysqlの更新を再開させる。
先にmysqlの更新を一時停止したシェルを使い、更新を再開させます。
mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.00 sec)
- マスター#1 : 外部サーバーから の mysqlへのアクセスするためのユーザを作成する。
先にmysqlの更新を一時停止したシェルを使い、ユーザを作成します。
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave-user'@'%' IDENTIFIED BY 'slave-password';
ここでは、
ユーザ名:slave-user
パスワード:slave-password
としています。
必要に応じて変更しましょう。
ユーザ名の後に‘@’%’を付加することで、どのサーバーからもアクセスを可能としています。
もし、ドメイン名などで限定したい場合は、‘@’%.example.com’などとし、example.comのサブドメインはすべて可能なように設定することもできます。
- マスター#1 : 外部サーバーからの mysqlへのアクセスするためのポートをオープンする。
外部サーバーからmysqlをアクセスできるようにTCPポートをオープンします。
$ /sbin/iptables -A INPUT -s 111.111.111.111 -p tcp --dport 3306 -j ACCEPT
IPアドレス”111.111.111.111″から、ポート番号 3306 (mysqlのデフォルトポート番号) へのアクセスを許可するようにしています。
環境に合わせて書き換えましょう。
- マスター#1 : mysqlサーバーを再起動して、マスターサーバーとする。
先にmysqlの更新などを行ったシェルでmysqlを閉じます。
mysql> exit $
mysqlを再起動します。
$ /etc/init.d/mysqld restart mysqld を停止中: [ OK ] mysqld を起動中: [ OK ]
- マスター#2 : mysqlを停止してリストアする。
まず 先のマスター#1 でバックアップしたデータベースを マスター#2へコピー(リストア)するために マスター#2のmysqlを停止する。
$ /etc/init.d/mysqld stop mysqld を停止中: [ OK ] $
tarでマスタ側で作成したmysqlのバックアップファイルからリストアする。
$ cd /var/lib $ tar xvfz /tmp/mysql-bin.tar.gz mysql ..
tarで解凍・展開するのは、mysqlのデータディレクトリになります。
ここでは、そのディレクトリが、/var/lib/mysql としています。
mysqlのデータディレクトリは、mysqlの設定ファイル(/etc/my.cnf)を確認するとわかります。
この例では、ディレクトリは、/var/lib/mysql です。datadir = /var/lib/mysql
mysqlを起動する。
$ /etc/init.d/mysqld start mysqld を起動中: [ OK ]
- マスター#2 : mysqlのスレーブ設定を行う。
$ mysql -uroot -p -Dmysql password : mysql> CHANGE MASTER TO MASTER_HOST='111.111.111.111', # マスターのホスト名/IPアドレス MASTER_USER='slave-user', # マスター接続に使用するユーザー名 MASTER_PASSWORD='slave-password', # パスワード MASTER_LOG_FILE='mysql-bin.003', # マスター側設定の3項で確認したFile MASTER_LOG_POS=73; # マスター側設定の3項で確認したPosition Query OK, 0 rows affected (0.01 sec)
マスター側設定の3項で確認した情報がEmptyだった場合、
MASTER_LOG_FILE : ”
MASTER_LOG_POS : 4
とします。
mysql> CHANGE MASTER TO MASTER_HOST='111.111.111.111', MASTER_USER='slave-user', MASTER_PASSWORD='slave-password', MASTER_LOG_FILE='', MASTER_LOG_POS=4;
- マスター#2 : mysqlのスレーブを起動する。
mysql> START SLAVE;
これで、スレーブとして起動完了のはずです。
mysqlにエラーが発生していないか確認しておきましょう。
mysqlのエラーログの出力先は、以下のように設定したファイルにログが出力されます。また、syslogへ出力する場合は、以下のように設定します。[mysqld_safe] ... # 最近は、log-error -> log_error と記述するようです。 log-error = /var/log/mysqld.log ...
[mysqld_safe] ... syslog ...
のように出力されていればOKです。$ cat /var/log/mysqld.log ... 101226 17:22:16 [Note] Slave SQL thread initialized, starting replication in log 'FIRST' at position 0, relay log './mysqld-relay-bin.000001' position: 4 101226 17:22:16 [Note] Slave I/O thread: connected to master 'slave-user@10.0.0.11:3306',replication started in log 'FIRST' at position 4 ...
のようにERRORが出力されていれば、そのエラーを取り除きましょう。... 101226 17:19:45 [ERROR] Error reading packet from server: Binary log is not open ( server_errno=1236) 101226 17:19:45 [ERROR] Slave I/O: Got fatal error 1236 from master when reading data from binary log: 'Binary log is not open', Error_code: 1236 ...
※上記のエラーは、マスター側にデータがない・・・というエラーで、正しくマスターが動作していないことが考えられます。
- マスター#2 : mysqlの書き込みを一時停止して現在の状態を確認する。
次に、マスター#1 の スレーブ設定のために、マスター#2 のマスターとしての状態を確認するために、マスター#2 のmysqlの更新を一時停止する。
$ mysql -uroot -p -Dmysql password : mysql> FLUSH TABLES WITH READ LOCK; Query OK, 0 rows affected (0.01 sec) mysql> SHOW MASTER STATUS; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | mysql-bin.001 | 9859 | test | manual,mysql | +---------------+----------+--------------+------------------+
ここで、以下のように表示されることがあります。
これは、何も情報がないと言っているだけでエラーではありません。mysql> SHOW MASTER STATUS; Empty set (0.02 sec)
※まだ、バイナリログを使用していない場合は、このように表示されます。
Emptyだったことを書きとめておきましょう。
- マスター#1 : mysqlのスレーブ設定を行う。
$ mysql -uroot -p -Dmysql password : mysql> CHANGE MASTER TO MASTER_HOST='222.222.222.222', # マスターのホスト名/IPアドレス MASTER_USER='slave-user', # マスター接続に使用するユーザー名 MASTER_PASSWORD='slave-password', # パスワード MASTER_LOG_FILE='mysql-bin.001', # マスター側設定の3項で確認したFile MASTER_LOG_POS=9859; # マスター側設定の3項で確認したPosition Query OK, 0 rows affected (0.01 sec)
マスター側設定の3項で確認した情報がEmptyだった場合、
MASTER_LOG_FILE : ”
MASTER_LOG_POS : 4
とします。
mysql> CHANGE MASTER TO MASTER_HOST='222.222.222.222', MASTER_USER='slave-user', MASTER_PASSWORD='slave-password', MASTER_LOG_FILE='', MASTER_LOG_POS=4;
- マスター#1 : mysqlのスレーブを起動する。
mysql> START SLAVE;
これで、スレーブとして起動完了のはずです。
mysqlにエラーが発生していないか確認しておきましょう。
mysqlのエラーログの出力先は、以下のように設定したファイルにログが出力されます。また、syslogへ出力する場合は、以下のように設定します。[mysqld_safe] ... # 最近は、log-error -> log_error と記述するようです。 log-error = /var/log/mysqld.log ...
[mysqld_safe] ... syslog ...
のように出力されていればOKです。$ cat /var/log/mysqld.log ... 101226 17:22:16 [Note] Slave SQL thread initialized, starting replication in log 'FIRST' at position 0, relay log './mysqld-relay-bin.000001' position: 4 101226 17:22:16 [Note] Slave I/O thread: connected to master 'slave-user@10.0.0.11:3306',replication started in log 'FIRST' at position 4 ...
のようにERRORが出力されていれば、そのエラーを取り除きましょう。... 101226 17:19:45 [ERROR] Error reading packet from server: Binary log is not open ( server_errno=1236) 101226 17:19:45 [ERROR] Slave I/O: Got fatal error 1236 from master when reading data from binary log: 'Binary log is not open', Error_code: 1236 ...
※上記のエラーは、マスター側にデータがない・・・というエラーで、正しくマスターが動作していないことが考えられます。
- マスター#2 : mysqlの更新を再開させる。
先にmysqlの更新を一時停止したシェルを使い、更新を再開させます。
mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.00 sec)
ここ設定からもわかるように3台以上になった場合は、これをサークル上にリレー的なネットワークを組み込むことになります。そうなると、ちょっとメンテナンスは大変になるかもしれません。 このマルチマスター型は、2台、3台が限度かもしれませんね。でも、おもしろい構成ではありますね。少ない台数なら、ちょっと試したいかな。
このサイトでは、コンテンツの一部が非表示、あるいは、コメント、お問い合わせの投稿ができない、検索ができないことがあります。
コメントを投稿 :