こんにちはCTOの田中(巧)です。
今回は、MySQLのレプリケーション設定について書こうと思います。

レプリケーション概要

Wikipediaでは小難しい表現がされていますが今回の場合は単純な遅延コピーです。
ほぼリアルタイムですが、負荷状況等によってコピーされる側は遅延します。

MySQLのレプリケーションは次の内容が理由でよく利用されています。

可用性

MasterがダウンしてもSlave側が代替動作することができます。

パフォーマンス耐性

DB単位に役割を分ける事ができるため、負荷が分散できます。
例えば、SQLのwriteは一般的に処理が重たいため、それに引っ張られてread性能が落ちやすくなります。
これを避けるために、Master側をデータ更新用、
Slave側を参照専用にする構成にするように使う事でResponsibilityを保ちます。

バックアップ運用

コピーが作成されるため、即時性のある利用可能なDBにバックアップしているのと同様の運用が可能です。

構築

今回の構成内容

2台での[Master – Slave]構成、データコピーは非同期です。

手順1.Master側のDBの設定(my.cnf)

Master側での設定は「レプリケーション用のユーザの作成」とmy.cnfへの「レプリケーションのためのサーバ設定」を行います。

レプリケーション用ユーザの作成

基本的には一般的な、MySQLのユーザ作成と同一です。

GRANT REPLICATION SLAVE ON {object_type} TO {user}@'{access_network}' IDENTIFIED BY '{password}';

特徴的な部分を説明します。

  • REPLICATION SLAVE
    レプリケーション用の接続許可の指定です。
  • object_type
    レプリケーション時の対象です。
  • user
    MySQL上でのユーザ名です
  • access_network
    アクセス元のネットワークです。
  • password
    アクセス時のパスワードです。

これによって、Master DBへのレプリケーション専用のユーザが作成されます。

レプリケーションのためのサーバ設定(Master)

レプリケーションそのものの設定はサーバ全体設定になるためmysql.cnf へ行います。
ex) /etc/my.cnf 等
必須での設定項目は[mysqld]セクション内で2点です。

  • server-id
    レプリケーションを行う上でサーバのユニークな識別を設定します。
  • log-bin
    更新が行われた場合、MySQLではここで指定されたファイルを元にSlaveへ通知されます。
    このファイルにはDBへの更新差分が含まれています。

また、必須ではありませんがファイルがたまり続けてしまうため、自動的に削除されるように設定します。

  • set-variable=expire_logs_days=3
    ログファイルが保持される期間の設定です。この例では3日で設定していますが、用途やポリシーに応じて設定します。

サンプルリスト(my.cnf)

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1

# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0

server-id=1
log-bin=mysql-bin
set-variable=expire_logs_days=3

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

mysqlの再起動

サーバの設定が終わった後は、mysqldの再起動を行います。

$ service mysqld restart

手順2.Slave側DBの設定

MasterからSlaveへDBをコピーする

方法は特に問いませんが、MasterのDBからレプリケーションを行いたいMySQLのDBをコピーします。
・例
Slave側で取り込みたいDBをcreate database [db_name] 等で作成します。

mysql> create database example;

その後、MySQLを停止します。

$ service mysqld stop

Master側でMySQLが利用しているディレクトリ(/var/lib/mysql等)の直下に、DB名でディレクトリが作成されていることを確認します。
Slave側でも同様に同名のディレクトリが作成されていることを確認します。
※Slave側は必要があればバックアップを取ります。
Master側のディレクトリに入っている内容をそのままコピーします。

このとき、Permissionも正確にとる必要があるため、tarコマンド等を利用しましょう。
※Permissionが復元されないと、TableがRead Onlyになってしまう等の弊害が発生します。

レプリケーションのためのサーバ設定(Slave)

レプリケーションそのものの設定はサーバ全体設定になるためmysql.cnf へ行います。
ex) /etc/my.cnf 等
必須での設定項目は[mysqld]セクション内での[server-id]のみです。

  • server-id
    レプリケーションを行う上でサーバのユニークな識別を設定します。
    Masterの設定に被らないように設定します。

サンプルリスト(my.cnf) 

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1

# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0

server-id=2

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

Slave側からMaster側のDBを見えるようにする。

まず、Master側でレプリケーションのMaster側の情報を表示します。

mysql(master)> show master status;

+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |       98 |              |                  |
+------------------+----------+--------------+------------------+

次に、Slave側にMasterで設定したものと、前段で確認した内容を元にDBのMaster設定を行います。
この設定は「今からレプリケーションを始めますよ~」という意味合いになるため、これ以前に実行されていたSQL等は無視されることに注意してください。

mysql(slave)> CHANGE MASTER TO
-> MASTER_HOST = ‘{host name|ip address}’,
-> MASTER_USER = ‘{user}’,
-> MASTER_PASSWORD = ‘{password}’,
-> MASTER_LOG_FILE = ‘{log-bin file name}’,
-> MASTER_LOG_POS = {log position};

  • host name|ip address
    Master DBのホスト名もしくは、IPアドレスを指定します。
  • user
    Masterで作成したReplication用のユーザを指定します。
  • password
    userと同様にパスワードを指定します。
  • log-bin file name
    更新が記録されたファイル内のどのファイルを読み取るかを指定します。
    ※前段で取得した内容のうち、Fileと記載されている部分です。
  • log position
    更新が記録されたファイル内のどこの位置から読み取るかを指定します。
    ※前段で取得した内容のうち、Positionと記載されている部分です。

mysqlを起動する

サーバの設定が終わった後は、mysqldの起動をしなおします。

$ service mysqld start

レプリケーションの設定そのものはこれで完了です。
設定後、MasterのDBへDMLやDDLを実行してみてください。
Slaveへも反映されているはずです。

運用Tips

レプリケーションの運用に役立つコマンドをいくつかご紹介します。

同期が外れてしまった場合に再度再開する。

mysql(master)> show master status\G;

mysql(slave)> CHANGE MASTER TO MASTER_LOG_FILE='{file}’,MASTER_LOG_POS={position};

現在のレプリケーションの状態を確認する

何か動きが怪しいと考えたらまずSlave側のDBに次のコマンドを実行しましょう。
(下記例は正常な例です)

mysql(slave)> show slave status\G;

*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.86
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 698
Relay_Log_File: mysqld-relay-bin.000008
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000001
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: 698
Relay_Log_Space: 235
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

最後に

MySQLのレプリケーションは設定事態はそれほど難しい操作を必要としません。
みなさんもぜひぜひ試してみてください。