今回はMySQLの機能の1つであるレプリケーションについて、紹介します。
レプリケーションは、データベースの内容を複数のサーバーに複製する機能です。
MySQLの概要については、以下の記事で紹介していますので、ご参考ください。
レプリケーションの概要
レプリケーションは、データベースの内容を複数のサーバーに複製する機能です。
主な特徴は以下の通りです。
- 1台のソース(マスター)サーバと1台以上のレプリカ(スレーブ)サーバで構成される
- ソースサーバでデータ更新が行われ、その内容がレプリカサーバに複製される
- 標準機能のため、追加のミドルウェアなしで利用可能
レプリケーションの目的
MySQLのレプリケーションの主な目的は以下の通りです。
高可用性の実現
負荷分散
- 読み取りクエリをレプリカサーバに振り分けることで、ソースサーバの負荷を軽減し、全体的なパフォーマンスを向上させます。
- 特に読み取りアクセスが多いデータ集計などの処理にレプリカを利用することで効果的です。
バックアップの取得
データ分析環境の構築
地理的な冗長性
スケールアウト
サーバーの役割分担
メンテナンス時の可用性確保
レプリケーションの種類
レプリケーションの仕組み
レプリケーションの流れ
レプリケーションの流れは以下の通りです。
- アプリケーションがソースサーバにデータ更新をリクエストする。
- ソースサーバがデータを更新し、その内容をバイナリログに記録する。
- レプリカサーバのI/Oスレッドがソースのバイナリログを監視し、新しい更新があればリレーログにコピーする。
- レプリカサーバのSQLスレッドがリレーログの内容を読み取り、自身のデータに反映する。
レプリケーションの主な構成要素
レプリケーションの主な構成要素は以下の通りです。
構成要素 | 役割 |
---|---|
バイナリログ | ソースサーバの更新内容を記録するログファイル |
リレーログ | レプリカサーバがソースから取得したバイナリログの内容を一時的に保存するログファイル |
I/Oスレッド | レプリカサーバ上でバイナリログの取得を担当するスレッド |
SQLスレッド | レプリカサーバ上でリレーログの内容をデータに反映するスレッド |
レプリケーションの設定方法
レプリケーション設定手順
MySQLのレプリケーションを設定する基本的な手順を紹介します。
実行環境は以下の通りです。
レプリカサーバのデータベースはソースサーバからデータインポートして作成します。
OS | CentOS Stream release 9 |
MySQL | 8.4.2 MySQL Community Server |
データベース名 | my_database |
サーバの初期設定
最初に、ソース(マスター)サーバ、レプリカ(スレーブ)サーバ側でレプリケーションのための設定を実施します。
ソース(マスター)サーバ側の設定
ソース(マスター)サーバ側で実施する設定は以下の3つです。
- サーバーIDの設定
- バイナリログの有効化
- レプリケーション用ユーザの作成
サーバーIDの設定
my.cnfファイルでserver-idを設定します。
mysqldの配下に属性server-idをします。
値は1を設定します。
[root@master ~]# vi /etc/my.cnf
・・・
[mysqld]
・・・
server-id=1
[root@master ~]#
バイナリログの有効化
my.cnfファイルでlog-binを設定します。
mysqldの配下に属性log-binをします。
特に名前に命名規則はありませんが、わかりやすい名前を設定します。
[root@master ~]# vi /etc/my.cnf
・・・
[mysqld]
・・・
server-id=1
log-bin=mysql-bin
[root@master ~]#
設定反映のためサービスを再起動します。
[root@master ~]# systemctl restart mysqld
[root@master ~]#
レプリケーション用のユーザ作成
レプリケーションで利用するユーザを作成します。
レプリケーション用の専用ユーザーを作成することで、セキュリティを向上させ、レプリケーション関連の操作を他の一般的なデータベース操作から分離することができます。
今回は「repl」という名前で作成します。
mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'pAssw0rd!';
Query OK, 0 rows affected (0.03 sec)
mysql>
mysql> SELECT Host, User FROM mysql.user;
+-----------+------------------+
| Host | User |
+-----------+------------------+
| % | repl |
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
+-----------+------------------+
5 rows in set (0.00 sec)
mysql>
作成したレプリケーション用のユーザに対して、権限を付与します。
この権限により、任意のホストからマスターサーバーへ「repl」
というユーザで接続してバイナリログを読み取り、レプリケーションを実行できるようになります。
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Query OK, 0 rows affected (0.02 sec)
mysql>
mysql> show grants for 'repl'@'%';
+----------------------------------------------+
| Grants for repl@% |
+----------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO `repl`@`%` |
+----------------------------------------------+
1 row in set (0.01 sec)
mysql>
レプリカ(スレーブ)サーバ側の設定
レプリカ(スレーブ)サーバ側で実施する設定は以下です。
- サーバーIDの設定
サーバーIDの設定
my.cnfファイルでserver-idを設定します。
手順はソース(マスター)サーバと同じです。
mysqldの配下に属性server-idをします。
値は2を設定します。(ソースサーバと重複しない値を設定する必要があります。)
[root@slave ~]# vi /etc/my.cnf
・・・
[mysqld]
・・・
server-id=2
[root@slave ~]#
設定反映のためサービスを再起動します。
[root@slave ~]# systemctl restart mysqld
[root@slave ~]#
ソースからレプリカへデータコピー
次に、ソース(マスター)サーバからレプリカ(スレーブ)サーバへDBデータをコピーします。
ソース(マスター)サーバでデータをエクスポートしたのち、レプリカ(スレーブ)サーバへエクスポートしたデータをインポートします。
ソース(マスター)サーバでDBデータのエクスポート
最初にソース(マスター)サーバでDBデータをエクスポートします。
コマンドはmysqldumpを利用します。
実行結果から、正常にDBデータエクスポートが実行されました。
[root@master ~]# mysqldump -u root -p --all-databases --source-data > /tmp/dump.sql
Enter password:
[root@master ~]#
[root@master ~]# ls -l /tmp/dump.sql
-rw-r--r-- 1 root root 1210778 9月 16 15:36 /tmp/dump.sql
[root@master ~]#
レプリカ(スレーブ)サーバへDBデータをインポート
次にエクスポートしたデータをレプリカ(スレーブ)サーバへインポートします。
コマンドはmysqlを利用します。
実行結果から、ソース(マスター)サーバのDBデータをインポートできました。
[root@slave ~]# mysql -u root -p < /tmp/dump.sql
Enter password:
[root@slave ~]#
[root@slave ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 8.4.2 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| my_database |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
mysql>
レプリカ(スレーブ)サーバでマスター情報の設定
レプリカ(スレーブ)サーバでマスタの設定をソース(マスター)サーバに変更します。
CHANGE REPLICATION SOURCE TOコマンドを実行します。
mysql> CHANGE REPLICATION SOURCE TO
-> SOURCE_HOST='ソース(マスター)サーバのIPアドレス',
-> SOURCE_USER='repl',
-> SOURCE_PASSWORD='pAssw0rd!',
-> SOURCE_LOG_FILE='mysql-bin.000001',
-> SOURCE_LOG_POS=1115;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql>
SOURCE_LOG_FILEとSOURCE_LOG_POSはソース(マスター)サーバ側でSHOW BINARY LOG STATUSコマンドを実施した結果の属性Positionを指定します。(SHOW BINARY LOGSコマンドでも確認可能)
mysql> SHOW BINARY LOG STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1115 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql>
レプリカ(スレーブ)サーバでレプリケーションを開始
レプリカ(スレーブ)サーバでレプリケーションを開始します。
コマンドはSTART REPLICAを実行します。
mysql> START REPLICA;
Query OK, 0 rows affected (0.11 sec)
mysql>
レプリカ(スレーブ)サーバのレプリケーションの状態を確認します。
コマンドはSHOW REPLICA STATUSを実行します。
実行結果から、ソース(マスター)サーバをマスタとする設定が完了し、接続状態も問題ない(属性Replica_IO_Running、Replica_SQL_RunningがYesとなっている)ことが確認できました。
mysql> SHOW REPLICA STATUS;
+----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+----------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |
+----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+----------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
| Waiting for source to send event | ソース(マスター)サーバのIPアドレス | repl | 3306 | 60 | mysql-bin.000001 | 1115 | localhost-relay-bin.000002 | 647 | mysql-bin.000001 | Yes | Yes | | | | | | | 0 | | 0 | 1115 | 862 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 96cf0bc4-7367-11ef-b7c7-2a14b1574830 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 10 | | | | | | | | 0 | | | | | 0 | |
+----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+----------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+
1 row in set (0.01 sec)
mysql>
Replica_IO_RunningがNoとなっている場合は、レプリケーションI/Oスレッドが実行されておらず、正常にレプリケーションできない状態です。
原因として、以下の項目を確認してみてください。
- ネットワーク接続の問題
- ソースサーバーへのネットワーク接続が不安定であるか、ファイアウォールなどでブロックされている可能性があります。
- ソースサーバーの設定
- ソースサーバーが正しく起動していないか、バイナリログが有効になっていない場合、接続できない可能性があります。
- 認証情報の誤り
- 使用しているユーザー名やパスワードが間違っている場合、接続が拒否される場合があります。
- ホスト名やポートの誤設定
- ソースサーバーのホスト名やポート番号が正しく設定されていない場合、接続できない場合があります。
- SSL/TLS設定の問題
- SSL/TLSを使用している場合、証明書や鍵の設定に問題があると接続できない場合があります。
以上で、レプリケーション設定が完了しました。
ソース(マスター)サーバからレプリカ(スレーブ)サーバへレプリケーションができていることを確認します。
レプリケーション動作確認
レプリケーションの動作確認を実施します。
ソース(マスター)サーバで特定のテーブルusersへデータを追加し、レプリカ(スレーブ)サーバへ同期されることを確認します。
事前情報として、ソース(マスター)サーバ、レプリカ(スレーブ)サーバどちらもテーブルusersにはデータが登録されていない状態です。
ソース(マスター)サーバ
mysql> select * from users;
Empty set (0.00 sec)
mysql>
レプリカ(スレーブ)サーバ
mysql> select * from users;
Empty set (0.00 sec)
mysql>
ソース(マスター)サーバでデータ追加
最初に、ソース(マスター)サーバでテーブルusersのデータを追加します。
mysql> INSERT INTO users (user_id, name, age, birthplace) VALUES (1, 'user01', 25, 'tokyo');
Query OK, 1 row affected (0.01 sec)
mysql>
mysql> select * from users;
+---------+--------+------+------------+
| user_id | name | age | birthplace |
+---------+--------+------+------------+
| 1 | user01 | 25 | tokyo |
+---------+--------+------+------------+
1 row in set (0.01 sec)
mysql>
レプリカ(スレーブ)サーバの同期確認
レプリカ(スレーブ)サーバのテーブルusersのデータを確認します。
実行結果かから、ソース(マスター)サーバで追加したデータがレプリカ(スレーブ)サーバへ同期されたことが確認できました。
mysql> select * from users;
+---------+--------+------+------------+
| user_id | name | age | birthplace |
+---------+--------+------+------------+
| 1 | user01 | 25 | tokyo |
+---------+--------+------+------------+
1 row in set (0.01 sec)
mysql>
まとめ
今回はMySQLの機能の1つであるレプリケーションについて、紹介しました。
MySQLのレプリケーションは柔軟性が高く、多くの用途で活用できる重要な機能です。
適切に設計・運用することで、可用性とスケーラビリティの向上に大きく貢献します。
参考になれば、幸いです。
以上になります。ありがとうございました。
参考
https://www.system-exe.co.jp/dbexpert34
https://style.potepan.com/articles/19397.html
https://qiita.com/suzuko24/items/ace0a08f2b2aabd95045
https://www.yuus-program.com/2023/05/29/db-2/
https://qiita.com/Tocyuki/items/c224cef57493f536a941
https://www.reddit.com/r/mysql/comments/1d6ysx0/show_master_status_not_working/?rdt=48240
https://dev.mysql.com/doc/refman/8.0/en/start-slave.html
https://dev.mysql.com/doc/refman/8.0/ja/replication-administration-status.html
コメント