MySQL5でレプリケーションをする

MySQLサーバを二重化し、マスター機からスレーブ機へレプリケーションする。MySQLでは、1台のマスタと複数台のスレーブの間でレプリケーションをすることができる。更新処理はマスタで行い、検索処理はマスタとスレーブで行えるが、普通はパフォーマンスを上げるためにマスタは更新専用にする。データの更新は非同期なので、スレーブの台数やパフォーマンスにマスタの動作が引っ張られることはない。そのかわり常にすべてのサーバで同じ情報があることは保障されない。

まず、マスターの設定をする。

[root@db1 ~]# vi /etc/my.cnf
...
[mysqld]
log-bin = mysql-bin
server-id = 1
...

マスターは更新処理の内容をバイナリログというファイルに書き込み、スレーブはそのファイルを読み込んで自分のデータを更新する。server-idは何でもよいが、ユニークな値を付与する。

マスターでMySQLを再起動し、レプリケーション用のユーザを追加する。

mysql>root@db1 ~]# service mysqld restart
Stopping MySQL:                                            [  OK  ]
Starting MySQL:                                            [  OK  ]

[root@db1 ~]# mysql -u root -p
Enter password:
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.grandarbre.net' IDENTIFIED BY 'PASSWORD123';
Query OK, 0 rows affected (0.00 sec)

次にマスターでレプリケーション情報を取得する。まずすべてのデータをフラッシュし、書き込みステートメントをブロックする。

[root@db1 ~]# mysql -u root -p
Enter password:
mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.00 sec)

次に現在のバイナリログ名とオフセットを調べる。

mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |   158995 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

mysql>

そうして、スレーブに初期同期させるためのデータダンプを取得する。

[root@db1 ~]#  mysqldump --all-databases --lock-all-tables -u root -p > /tmp/dbdump.db
Enter password:

次にスレーブの設定をする。

[root@db2 ~]# vi /etc/my.cnf
...
[mysqld]
server-id=2
...

設定例によっては、my.cnfにマスターのホスト名や認証情報などを書いている場合もある。しかしいったんスレーブが設定されると、これらの情報は/var/lib/mysql/master.infoに保存されてmy.cnfは無視されるので、my.cnfに書く必要はない。

ここでスレーブのMySQLを再起動する。

[root@db2 ~]# service mysqld restart
Stopping MySQL:                                            [  OK  ]
Starting MySQL:                                            [  OK  ]

先ほどマスターで取得したダンプをFTPなどでスレーブにコピーし、MySQLに読み込ませる。

[root@db2 ~]# mysql -u root -p < /tmp/dbdump.db
Enter password:

スレーブのDBをマスターに接続する。

[root@db2 ~]# mysql -u root -p
Enter password:
mysql> CHANGE MASTER TO
    -> MASTER_HOST='db1',
    -> MASTER_USER='repl',
    -> MASTER_PASSWORD='replpass123',
    -> MASTER_LOG_FILE='mysql-bin.000001',
    -> MASTER_LOG_POS=158995;
Query OK, 0 rows affected (0.16 sec)

スレーブを開始する。

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

ここまでの作業でレプリケーションはできているはず。

マスターの状態を表示する。

mysql> show master status\G
*************************** 1. row ***************************
            File: mysql-bin.000002
        Position: 186113
    Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

スレーブの状態を表示する。Slave_IO_Running:とSlave_SQL_Running:がyesだとslaveとして動いている。

mysql>
mysql> show slave status\G
*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: db1
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysql-bin.000002
        Read_Master_Log_Pos: 186113
             Relay_Log_File: db2-relay-bin.000004
              Relay_Log_Pos: 186250
      Relay_Master_Log_File: mysql-bin.000002
           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: 186113
            Relay_Log_Space: 186250
            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
1 row in set (0.00 sec)

mysql>

マスターでプロセスを見てみる。Binlog Dumpがあればよい。

mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
     Id: 22
   User: root
   Host: localhost
     db: mt
Command: Query
   Time: 0
  State: NULL
   Info: SHOW PROCESSLIST
*************************** 2. row ***************************
     Id: 41
   User: repl
   Host: db2.grandarbre.net:56174
     db: NULL
Command: Binlog Dump
   Time: 323
  State: Has sent all binlog to slave; waiting for binlog to be updated
   Info: NULL
2 rows in set (0.00 sec)

mysql>

スレーブでもプロセスを見ると、2つのConnectがある。

mysql> show processlist\G
*************************** 1. row ***************************
     Id: 2
   User: root
   Host: localhost
     db: mt
Command: Query
   Time: 0
  State: NULL
   Info: show processlist
*************************** 2. row ***************************
     Id: 3
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 191
  State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 4
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 11
  State: Has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL
3 rows in set (0.00 sec)

mysql>