これは、なにをしたくて書いたもの?
MySQL 8.4になってからレプリケーションを行う環境を作ったことがなかったので、設定しておこうということで。
MySQLのレプリケーション
MySQL 8.4のレプリケーションに関するドキュメントはこちら。
MySQL :: MySQL 8.4 Reference Manual :: 19 Replication
MySQLのレプリケーションには、バイナリーログのポジションにもとづくものと、
Global Transaction Identifiers(GTID)を使ったものの2種類があります。
- MySQL :: MySQL 8.4 Reference Manual :: 19.1.1 Binary Log File Position Based Replication Configuration Overview
- MySQL :: MySQL 8.4 Reference Manual :: 19.1.3 Replication with Global Transaction Identifiers
今回はGTIDを使ったレプリケーションで構成します。
レプリケーションの設定方法はこちら。
MySQL :: MySQL 8.4 Reference Manual :: 19.1.3.4 Setting Up Replication Using GTIDs
MySQL :: MySQL 8.4 Reference Manual :: 15.4 Replication Statements
このあたりは実際にレプリケーションを構成する時に出てきますが、ここではGTIDを使ったレプリケーションでの
制限事項を見ておきます。
MySQL :: MySQL 8.4 Reference Manual :: 19.1.3.7 Restrictions on Replication with GTIDs
GTIDを使ったレプリケーションでは、以下の制限があるとされています。
- 非トランザクショナルなストレージエンジンのテーブルの更新と、トランザクショナルなストレージエンジンのテーブルの更新を同じステートメントまたはトランザクションで行えない
- アトミックDDLをサポートするストレージエンジン(InnoDB)の場合、
CREATE TABLE ... SELECTはひとつのトランザクションとしてバイナリーログに記録される binlog_formatがSTATEMENTに設定されていて、サーバー上でGTIDを使用している場合、トランザクション内でCREATE TEMPORARY TABLEおよびDROP TEMPORARY TABLEの使用不可- サポートされていないSQLの実行をエラーで失敗させる
sql_replica_skip_counterを使用したイベント数を指定したスキップの不可IGNORE_SERVER_IDSの使用不可
アトミックDDLとは?という気になりましたが、データディクショナリーの更新、ストレージエンジンの操作、
バイナリーログの操作を単一のアトミック操作とするDDLのことらしいです。
MySQL :: MySQL 8.4 Reference Manual :: 15.1.1 Atomic Data Definition Statement Support
また、アトミックDDLはトランザクションDDLではないため、使用するとその時点でアクティブなトランザクションが
あると暗黙的にコミットします。
見てみると、よく使うようなDDLはアトミックDDLのようですね…。
第93回 MySQL8.0のデータディクショナリー | gihyo.jp
DDLの実行途中で中断したりした場合に、中途半端な状態にならないようにする仕組みのようです。
それではドキュメントを見るのはこれくらいにして、実際にGTIDを使ったレプリケーションを構築してみましょう。
環境
今回の環境はこちら。2つのUbuntu Linux 24.04 LTSのサーバーを用意します。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 24.04.2 LTS Release: 24.04 Codename: noble $ uname -srvmpio Linux 6.8.0-57-generic #59-Ubuntu SMP PREEMPT_DYNAMIC Sat Mar 15 17:40:59 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
IPアドレスはそれぞれ192.168.33.10、192.168.33.11とします。
192.168.33.10はSource、192.168.33.11はReplicaにすることにします。
MySQLをインストールする
ひとまずMySQLをインストールしましょう。
$ curl -LO https://dev.mysql.com/get/mysql-apt-config_0.8.33-1_all.deb $ sudo dpkg -i mysql-apt-config_0.8.33-1_all.deb $ sudo apt update $ sudo apt install mysql-server
操作はMySQL Shellから行うことにします。
$ sudo apt install mysql-shell
今回はMySQL 8.4.4がインストールされました。
$ mysqlsh --version mysqlsh Ver 8.4.4 for Linux on x86_64 - for MySQL 8.4.4 (MySQL Community Server (GPL)) $ mysqlsh root@localhost MySQL localhost:33060+ ssl SQL > select version(); +-----------+ | version() | +-----------+ | 8.4.4 | +-----------+ 1 row in set (0.0008 sec)
GTIDレプリケーションを構成する
では、レプリケーションを構成していきましょう。
最初にMySQLサーバーは、2つとも停止しておきます。
$ sudo systemctl stop mysql
MySQLの設定を変更します。デフォルトの設定はこんな感じです。
$ grep -v '#' /etc/mysql/mysql.conf.d/mysqld.cnf [mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql log-error = /var/log/mysql/error.log
Sourceのセットアップ
Sourceの設定はこのようにしました。
[mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql log-error = /var/log/mysql/error.log character_set_server = utf8mb4 collation_server = utf8mb4_0900_bin transaction_isolation = READ-COMMITTED gtid_mode = on enforce_gtid_consistency = on log_bin = binlog sync_binlog = 1 binlog_expire_logs_seconds = 864000 server_id = 1
ちなみに、この部分はレプリケーションに関係ありません。
character_set_server = utf8mb4 collation_server = utf8mb4_0900_bin transaction_isolation = READ-COMMITTED
またbinlog_expire_logs_secondsを設定したのはなんとなくです。
MySQLを起動。
$ sudo systemctl start mysql
レプリケーション用のユーザーを作成。
$ mysqlsh root@localhost
MySQL localhost:33060+ ssl SQL > create user repl_user@'%' identified by 'password'; Query OK, 0 rows affected (0.0633 sec) MySQL localhost:33060+ ssl SQL > grant replication slave on *.* to 'repl_user'@'%'; Query OK, 0 rows affected (0.0179 sec)
権限については、未だに"slave"のようです。
バイナリーログの確認。
MySQL localhost:33060+ ssl SQL > show binary log status\G
*************************** 1. row ***************************
File: binlog.000003
Position: 700
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: c6a5cdba-17a7-11f0-aaeb-525400d48b63:1-2
1 row in set (0.0014 sec)
これでSourceのセットアップは完了です。
Replicaのセットアップ
続いてはReplicaのセットアップです。
[mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql log-error = /var/log/mysql/error.log character_set_server = utf8mb4 collation_server = utf8mb4_0900_bin transaction_isolation = READ-COMMITTED gtid_mode = on enforce_gtid_consistency = on log_bin = binlog sync_binlog = 1 binlog_expire_logs_seconds = 864000 server_id = 2 read_only = on relay_log = relay-binlog
Sourceとの違いはserver_idの値と、read_onlyですね。
MySQLを起動。
$ sudo systemctl start mysql
MySQLに接続します。
$ mysqlsh root@localhost
レプリケーションの設定。
MySQL localhost:33060+ ssl SQL > change replication source to source_host = '192.168.33.10', source_port = 3306, source_auto_position = 1, source_ssl = 1; Query OK, 0 rows affected (0.0593 sec)
MySQL :: MySQL 8.4 Reference Manual :: 15.4.2.2 CHANGE REPLICATION SOURCE TO Statement
この時点ではレプリケーションは動作していません。
MySQL localhost:33060+ ssl SQL > show replica status\G *************************** 1. row *************************** Replica_IO_State: Source_Host: 192.168.33.10 Source_User: Source_Port: 3306 Connect_Retry: 60 Source_Log_File: Read_Source_Log_Pos: 4 Relay_Log_File: relay-binlog.000001 Relay_Log_Pos: 4 Relay_Source_Log_File: Replica_IO_Running: No Replica_SQL_Running: No 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_Source_Log_Pos: 0 Relay_Log_Space: 158 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Source_SSL_Allowed: Yes Source_SSL_CA_File: Source_SSL_CA_Path: Source_SSL_Cert: Source_SSL_Cipher: Source_SSL_Key: Seconds_Behind_Source: NULL Source_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Source_Server_Id: 0 Source_UUID: Source_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Replica_SQL_Running_State: Source_Retry_Count: 10 Source_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Source_SSL_Crl: Source_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Source_TLS_Version: Source_public_key_path: Get_Source_public_key: 0 Network_Namespace: 1 row in set (0.0020 sec)
Replicaの開始。
MySQL localhost:33060+ ssl SQL > start replica user = 'repl_user' password = 'password'; Query OK, 0 rows affected, 1 warning (0.1097 sec) Note (code 1759): Sending passwords in plain text without SSL/TLS is extremely insecure.
MySQL :: MySQL 8.4 Reference Manual :: 15.4.2.4 START REPLICA Statement
ドキュメントのようにchange replication source to 〜にユーザー名とパスワードを含めると、以下のように
start replicaに含めるように警告されるのですが。
Note (code 1760): Storing MySQL user name or password information in the connection metadata repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START REPLICA; see the 'START REPLICA Syntax' in the MySQL Manual for more information.
start replicaに入れたら入れたで、やっぱり警告されるのですが…。
Note (code 1759): Sending passwords in plain text without SSL/TLS is extremely insecure.
レプリケーションステータスの確認。
MySQL localhost:33060+ ssl SQL > show replica status\G *************************** 1. row *************************** Replica_IO_State: Waiting for source to send event Source_Host: 192.168.33.10 Source_User: repl_user Source_Port: 3306 Connect_Retry: 60 Source_Log_File: binlog.000003 Read_Source_Log_Pos: 700 Relay_Log_File: relay-binlog.000002 Relay_Log_Pos: 911 Relay_Source_Log_File: binlog.000003 Replica_IO_Running: Yes Replica_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_Source_Log_Pos: 700 Relay_Log_Space: 1119 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Source_SSL_Allowed: Yes Source_SSL_CA_File: Source_SSL_CA_Path: Source_SSL_Cert: Source_SSL_Cipher: Source_SSL_Key: Seconds_Behind_Source: 0 Source_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Source_Server_Id: 1 Source_UUID: c6a5cdba-17a7-11f0-aaeb-525400d48b63 Source_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates Source_Retry_Count: 10 Source_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Source_SSL_Crl: Source_SSL_Crlpath: Retrieved_Gtid_Set: c6a5cdba-17a7-11f0-aaeb-525400d48b63:1-2 Executed_Gtid_Set: c6a5cdba-17a7-11f0-aaeb-525400d48b63:1-2 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Source_TLS_Version: Source_public_key_path: Get_Source_public_key: 0 Network_Namespace: 1 row in set (0.0017 sec)
レプリケーションが開始されたようです。
確認
最後に動作確認。
Sourceに接続して、データベース、ユーザーを作成。
$ mysqlsh root@localhost MySQL localhost:33060+ ssl SQL > create database example; Query OK, 1 row affected (0.0318 sec) MySQL localhost:33060+ ssl SQL > create user kazuhira@'%' identified by 'password'; Query OK, 0 rows affected (0.0490 sec) MySQL localhost:33060+ ssl SQL > grant all privileges on example.* to 'kazuhira'@'%'; Query OK, 0 rows affected (0.0252 sec) MySQL localhost:33060+ ssl SQL > flush privileges; Query OK, 0 rows affected (0.0149 sec)
作成したユーザーで接続しなおし。
$ mysqlsh kazuhira@localhost/example
テーブルとデータの作成。
MySQL localhost:33060+ ssl example SQL > create table t1(c1 varchar(20)); Query OK, 0 rows affected (0.1023 sec) MySQL localhost:33060+ ssl example SQL > insert into t1(c1) values('foo'); Query OK, 1 row affected (0.0328 sec) MySQL localhost:33060+ ssl example SQL > insert into t1(c1) values('bar'); Query OK, 1 row affected (0.0218 sec) MySQL localhost:33060+ ssl example SQL > select * from t1; +-----+ | c1 | +-----+ | foo | | bar | +-----+ 2 rows in set (0.0015 sec)
Replicaに接続。
$ mysqlsh kazuhira@localhost/example
データがレプリケーションされていることが確認できます。
MySQL localhost:33060+ ssl example SQL > select * from t1; +-----+ | c1 | +-----+ | foo | | bar | +-----+ 2 rows in set (0.0019 sec)
なお、ReplicaはRead Onlyです。
MySQL localhost:33060+ ssl example SQL > create table t2(c2 varchar(20)); ERROR: 1290: The MySQL server is running with the --read-only option so it cannot execute this statement
これで確認できました。
おわりに
MySQL 8.4でGTIDレプリケーションの設定をしてみました。
8.0の時と変わっていませんでしたが、時々こういうのを確認しないとな、と思います。