0
0

Master & Slave DB 構成する方法について調べる

Posted at

はじめに

レプリケーションとは、2台以上のDBMSにデータを分けて配置する構成であり、Master/Slaveの構成で成り立っています。

  • Master DBMS : データの登録、修正、削除要求時にバイナリログを生成し、Slaveサーバーに送信します。(高い同時性が求められるトランザクション部分を担当します)
  • Slave DBMS : Master DBMSから受信したバイナリログを利用して、データに反映します。(データの要求時に使用され、読み取り専用です)

活用方法

  • Master DBMSに障害が発生した場合、代わりにSlave DBMSを使用することが可能です(フェイルオーバー)。
  • DBMSの負荷分散を目的とし、ユーザーの急増により1台のDBサーバーが対応しきれなくなった場合に使用します。

注意事項

  • 互換性を確保するために、レプリケーションに使用するMySQLのバージョンは同一にしてください。
  • バージョンが異なる場合、Slaveを上位バージョンで設定してください。
  • レプリケーションの起動時には、MasterからSlaveの順で起動してください。

Dockerを活用したMySQLレプリケーション

ディレクトリの構成は以下の通りです。

master/Dockerfile

FROM mysql:5.7
ADD ./master/my.cnf /etc/mysql/my.cnf

master/my.cnf

[mysqld]
log_bin = mysql-bin
server_id = 10
default_authentication_plugin=mysql_native_password

slave/Dockerfile

FROM mysql:5.7
ADD ./slave/my.cnf /etc/mysql/my.cnf

slave/my.cnf

[mysqld]
log_bin = mysql-bin
server_id = 11
relay_log = /var/lib/mysql/mysql-relay-bin
log_slave_updates = 1
read_only = 1
default_authentication_plugin=mysql_native_password

docker-compose.yml

version: "3"
services:
  db-master:
    build: 
      context: ./
      dockerfile: master/Dockerfile
    restart: always
    environment:
      MYSQL_DATABASE: 'db'
      MYSQL_USER: 'user'
      MYSQL_PASSWORD: 'password'
      MYSQL_ROOT_PASSWORD: 'password'
    ports:
      - '3306:3306'
    # Where our data will be persisted
    volumes:
      - my-db-master:/var/lib/mysql
      - my-db-master:/var/lib/mysql-files
    networks:
      - net-mysql
  
  db-slave:
    build: 
      context: ./
      dockerfile: slave/Dockerfile
    restart: always
    environment:
      MYSQL_DATABASE: 'db'
      MYSQL_USER: 'user'
      MYSQL_PASSWORD: 'password'
      MYSQL_ROOT_PASSWORD: 'password'
    ports:
      - '3307:3306'
    # Where our data will be persisted
    volumes:
      - my-db-slave:/var/lib/mysql
      - my-db-slave:/var/lib/mysql-files
    networks:
      - net-mysql
  
# Names our volume
volumes:
  my-db-master:
  my-db-slave: 

networks: 
  net-mysql:
    driver: bridge

image.png

実行手順

  1. master-slaveの2つのサーバーを起動します。
docker-compose up -d
  1. internal IPを探します。
  • まず、ネットワークIDを見つけます。
❯ docker network ls
NETWORK ID     NAME                    DRIVER    SCOPE
c936b9b7cc42   repli_net-mysql         bridge    local
  • docker inspect {NETWORK ID}を使用して、IPv4Addressに該当する値を確認します。
❯ docker inspect c936b9b7cc42

[
    {
        "Name": "repli_net-mysql",
        "Id": "c936b9b7cc4214b978aa64d7397d218c0fe62dd76389971ef2134ea8a8560765",
        "Created": "2022-01-11T14:36:21.9461848Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "31b2a62702a6249c666076d7182a34c30ac3e2939ea6924b84b237fb6a57e915": {
                "Name": "repli_db-slave_1",
                "EndpointID": "afbd9ee57c687c50fab1b39be1b97919229fff04fc418269612c058cbff06554",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "43bb2e42864eaa10c730ae53c01ab9817a49c5c34db2eba62ce3e14f92779cdb": {
                "Name": "repli_db-master_1",
                "EndpointID": "6e2d8cc63e3fc5d6322ab2de3d6bf414ee49a885ded7e26d66b4afb9188e6090",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "net-mysql",
            "com.docker.compose.project": "repli",
            "com.docker.compose.version": "1.29.0"
        }
    }
]
  1. SlaveからMasterに接続します。

実際、この部分で多少苦労しました。直面したエラーは「Error 1236 - 'Could not find first log file name in binary log index file'」というものでしたが、slaveサーバーでMASTER_LOG_FILEを設定する際に、masterサーバーに存在するログファイルを基準に設定する必要がありました。

これを確認するためには、masterサーバーで以下のコマンドを入力します。

mysql> SHOW BINARY LOGS;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       177 |
| mysql-bin.000002 |   3072319 |
| mysql-bin.000003 |       177 |
| mysql-bin.000004 |       154 |
+------------------+-----------+

存在しないログファイルインデックスを選択すると、エラーが発生します。
その後、以下のように設定を合わせました。結論として、Slave_IO_Running: Yes / Slave_SQL_Running: Yesと表示されれば同期が完了したことになります。

mysql> CHANGE MASTER TO MASTER_HOST='172.19.0.3', MASTER_USER='root', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=0;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

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

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

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.19.0.3
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 154
               Relay_Log_File: mysql-relay-bin.000004
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000004
             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: 154
              Relay_Log_Space: 787
              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
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: 10
                  Master_UUID: fd513db6-72eb-11ec-890b-0242ac130002
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           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
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

テスト

最終的にテストを行うために、DBとテーブルにデータを直接投入してみました。

Master DB

mysql> use bootex;
Database changed

mysql> create table Member (ID int not null primary key, name varchar

(100));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into Member(id, name)  values (1,"song");
Query OK, 1 row affected (0.01 sec)

Slave DB

mysql> show tables;
+------------------+
| Tables_in_bootex |
+------------------+
| Member           |
+------------------+
1 row in set (0.00 sec)

mysql> select * from Member;
+----+------+
| ID | name |
+----+------+
|  1 | song |
+----+------+
1 row in set (0.00 sec)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0