既存レプリケーション環境に新スレーブ追加
MySQL Casual Advent Calendar 2011の27日目として更新します。
皆さんがまったくcasualじゃないので、バシッとコンセプト通りの記事をあげます。
ちなみに今日は熱出して会社を休んでおります。
アタマがぼーっとしている中書いてますので、変な事書いてたらスミマセン・・・
マスタ-スレーブ-スレーブ構成のMySQLで、サービスを停止せずにスレーブを追加する方法を紹介します。
参照が多くなってきたなーってときに、ピークタイムを避けて作業すればメンテナンスを入れなくてもスレーブを増やせます。
環境、構成
この構成に、スレーブCを追加する
【MySQLマスタ】ー【MySQLスレーブA】
|
【MySQLスレーブB】
サービスからMySQLスレーブAを切り離す
スレーブAのコネクションをモニタ
netstatコマンドで、スレーブAのmysqlコネクションをモニタリングしておく
この間に、スレーブAへのselectがすべてスレーブBに向くようにする
[root@slaveA ~]# watch 'netstat|grep mysql' tcp 0 0 slaveA:mysql web01:34586 ESTABLISHED tcp 0 0 slaveA:mysql web05:40998 ESTABLISHED tcp 0 0 slaveA:mysql web02:57635 ESTABLISHED tcp 0 0 slaveA:34660 master:mysql ESTABLISHED ・ ・ ・
select先の変更作業が終わったら、以下のようにマスタとの間でのみmysqlセッションが張られている状態になるまでモニタリング
[root@slaveA ~]# watch 'netstat|grep mysql' tcp 0 0 slaveA:34660 master:mysql ESTABLISHED
念のための確認
しばらくモニタリングして新規の接続が来ないことを確認できたら、今度はtcpdumpコマンドで通信をモニタリング
[root@slaveA ~]# tcpdump port 3306|grep -v master tcpdump: WARNING: eth0: no IPv4 address assigned tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
何も出力されないことを確認したら、以下コマンドでカレントコネクション数が1であることを確認
[root@slaveA ~]# mysqladmin -u root extended-status | grep Threads_connected | Threads_connected | 1 | [root@slaveA ~]#
スレーブAを停止し、スレーブAのデータをスレーブCにコピーする
スレーブAを停止
以下のコマンドを発行
[root@slaveA ~]# mysqladmin --password='rootパスワード' shutdown [root@slaveA ~]#
スレーブAからスレーブCにデータディレクトリごとコピーする
同時にbinlogとrelaylogもコピーしておく~
回線が弱い環境では、scpの帯域を制限して転送する~
※tarで固めてから送ったほうがいいかも?
[root@slaveC ~]# cd /var/lib/mysql [root@slaveC mysql]# scp -pr -l 30000 slaveA:/var/lib/mysql/* ./ & [1] 17855 [root@slaveC mysql]# cd ../mysql-bin/ [root@slaveC mysql-bin]# scp -pr -l 5000 slaveA:/var/lib/mysql-bin/* ./ mysql-bin.000013 100% 117 0.1KB/s 00:00 mysql-bin.000014 100% 117 0.1KB/s 00:00 mysql-bin.index 100% 72 0.1KB/s 00:00 mysql-relay-bin.000715 100% 105MB 484.8KB/s 03:41 mysql-relay-bin.index 100% 42 0.0KB/s 00:00 [root@slaveC mysql-bin]# jobs [1]+ Running scp -pr -l 30000 slaveA:/var/lib/mysql/* ./ & (wd: /var/lib/mysql) [root@slaveC mysql-bin]# fg %1 scp -pr -l 30000 slaveA:/var/lib/mysql/* ./ (wd: /var/lib/mysql) tbl.ibd 34% 2709MB 3.1MB/s 28:06 ETA ・ ・ ・ [root@slaveC mysql-bin]#
スレーブA再開、スレーブC起動
スレーブA再開
mysqldを起動して、以下のシェルスクリプトを実行する
#!/bin/bash echo "`date` START SLAVE" mysql -e "START SLAVE" sleep 1 BEHIND=1 while [ ${BEHIND} -gt 0 ] do echo "`date` STOP SLAVE" mysql -e --password='rootパスワード' "STOP SLAVE IO_THREAD" sleep 5 echo "`date` START SLAVE"; mysql -e --password='rootパスワード' "START SLAVE IO_THREAD" sleep 1 BEHIND=`mysql -e --password='rootパスワード' "show slave status\G" |grep Seconds_Behind_Master|cut -f 2 -d ':'` echo "`date` Seconds_Behind_Master:${BEHIND}" done
'START SLAVE'して1秒後に'STOP SLAVE IO_THREAD'、5秒後にまた'START SLAVE'する処理が、'Seconds_Behind_Master'が0になるまで繰り返される
こうすることで、スレーブが停止していた間に発生したマスタの更新をゆっくり追いかけるので、マスタへの負荷を最小限に抑えることができる
'STOP SLAVE IO_THREAD'の場合、'Slave_SQL_Running'は継続されるので、マスタの更新イベントの反映は止まらない
つまり、'START SLAVE'している1秒間の間に取得した更新クエリは止まることなく実行され続ける
※'Seconds_Behind_Master'は'show slave status\G'で得られる、レプリケーションの遅延秒数
スレーブC起動
スレーブAと同じ手順で行う~
このとき、設定ファイルでユニークなserver_idを割り当てた状態で起動すること
master.info、relay.infoファイルのルールでレプリケーション プロセスが開始されるので、'CHANGE MASTER TO ・・・'でマスタ情報を登録する作業は不要
advent calendarは初参戦で、かつ、エンジニアとしても雑魚の極みですが、27日目はこんな感じです。。
myfinderさんのお計らいで記事をあげる機会をいただいて感謝です。