MySQLでわざとレプリケーションを遅延させる方法

# 概要
2016年11月17日のお話。

[前回](https://qiita.com/KensukeSakakibara/items/bf055e6dadd370f1fd0f)1台のサーバでレプリケーション設定をしました。
レプリケーションを想定した開発環境を作る事が目的なのですが、そうであればわざとレプリケーションを遅延させることで問題がちゃんと出るようにしておく必要があるかと思います。

遅延のさせ方はMySQL5.6以前と以降で大きく2通りありまして、それぞれ違っています。
MySQL5.6以降はどれだけ遅延させるかという設定がMySQL自体に備わっていますのでとても簡単に実現できますが、MySQL5.6より前になってしまうとそのような機能がありませんので、STOP SLAVEとSTART SLAVEを繰り返すことによって遅延しているような感じを作り出すスクリプトを使う事になります。

# 作業手順
## MySQL5.6以降の場合
まずはMySQL5.6以降の場合の設定方法、前回のレプリケーション設定を行っている前提になります。
スレーブにアクセスしてCHANGE MASTERを行います。
この設定例の場合は、10秒遅延することになります。

```
$ mysql -u root -h 127.0.0.1 -P 3307 -p
mysql> STOP SLAVE;
Query OK, 0 rows affected (0.10 sec)
 
mysql> CHANGE MASTER TO MASTER_DELAY = 10;
Query OK, 0 rows affected (0.17 sec)
 
mysql> START SLAVE;
Query OK, 0 rows affected (0.06 sec)
```

そして状態と遅延を確認します。
SQL_Delay: 10 になってますね。

```
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: localhost
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000009
          Read_Master_Log_Pos: 811526263
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 240143
        Relay_Master_Log_File: mysql-bin.000009
             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: 811523403
              Relay_Log_Space: 243176
              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: 4
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1001
                  Master_UUID: b2e1a379-a554-11e6-88f4-9ca3ba01ee48
             Master_Info_File: /var/lib/mysql2/master.info
                    SQL_Delay: 10
          SQL_Remaining_Delay: 1
      Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
1 row in set (0.00 sec)
```

これでMaster更新の10秒後にSlaveへデータが反映される動きになります。
具体的な例ではこんな感じです。
(1) 0:00 MasterでテーブルAを作成
(2) 0:05 MasterでテーブルBを作成
(3) 0:10 SlaveでテーブルAが作成される
(4) 0:15 SlaveでテーブルBが作成される

slave2の方でも同じように設定しておきましょう。

## MySQL5.6よりも前のバージョンの場合
次に、MySQL5.6よりも前のバージョンの場合ですが、MySQLの機能ではサポートされていません。
そのため疑似的に遅延しているような感じにするPercona Toolkitに含まれているpt-slave-delayというPerlスクリプトを使います。
Percona Toolkit
https://www.percona.com/downloads/percona-toolkit/LATEST/

```
$ cd /usr/local/src/
$ mkdir PerconaToolkit
$ cd PerconaToolkit
$ wget https://www.percona.com/downloads/percona-toolkit/2.2.19/RPM/percona-toolkit-2.2.19-1.noarch.rpm
$ su -
# yum install perl-DBI perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL ←pt-slave-delayにはこれが必要
# rpm -ivh percona-toolkit-2.2.19-1.noarch.rpm
```

私の設定の場合はMySQLのrootでレプリケーション設定を行っていますので、STOP SLAVEやSTART SLAVEをするにはルートでアクセスする必要があります。
そのため次のようなコマンドになるはず。（↓叩いた事無いので本当に動くのか見てませんが）

```
$ pt-slave-delay --delay 10s --interval 1s --run-time 10m -u root -P 3307 -p 127.0.0.1
```

pt-slave-delayのマニュアル
https://www.percona.com/doc/percona-toolkit/2.1/pt-slave-delay.html#

ただ、このスクリプトは次のような動きになり、MySQL5.6で設定した挙動とは異なります。
(1) 0:00 STOP SLAVE
(2) 0:04 MasterでテーブルAを作成
(3) 0:08 MasterでテーブルBを作成
(4) 0:10 START SLAVE
(5) 0:10 SlaveでテーブルAが作成される
(6) 0:10 SlaveでテーブルBが作成される

という感じになりますのでなかなか使い辛いですね・・・。
これを頑張って使うよりも、素直にMySQL5.6の機能を使った方が簡単だと思います。