MySQL MSR Replication 구성 - Multi Source Replication

Share

Last Updated on 1월 19, 2024 by Jade(정현호)

안녕하세요 
이번 포스팅에서는 MySQL 의 복제 방법 중 N:1 유형의 Multi Source Replication 구성에 대해서 확인해보려고 합니다. 

MSR - Multi Source Replication

Multi Source Replication (MSR) 는 여러 개의 Master DB를 1개의 Slave(Replica) 인스턴스에 연결하여 복제하는 구조로, 여러 개의 Master DB의 내용을 하나의 Slave(Replica) 에 모으는 역할을 하게 됩니다.(Multi source 의 구조)


MySQL 5.7에서 추가된 기능으로 통합, 백업, OLAP 및 배치 작업 등에서 유용하게 사용할 수 있습니다.

Multi Source Replication(MSR) 의 구성시에는 GTID 기반 복제 와 Binary Log Position 기반 복제 둘 다 사용이 가능 합니다.


• 포스팅 환경
버전 : 5.7.33 , 8.0.23
복제 대상
 - Master1 의 DB명 : m1testdb1, m1testdb2  / Channel 명 : ch_master1
 - Master2 의 DB명 : m2testdb1, m2testdb2 / Channel 명 : ch_master2
        

파라미터 변경

MySQL 의 MSR 구성 시 Slave(Replica) 에서는 connection metadata repository 와 applier metadata repository 에 대한 정보가 TABLE 에 저장이 되어야 합니다. 그래서 master_info_repository 와 relay_log_info_repository 파라미터를 TABLE 로 설정해야 합니다(기본값 : FILE)

Note

master_info_repository 과 relay_log_info_repository 의 기본값은 기존까지는 FILE 이었고, MySQL 8.0.23 버전 부터 시스템 변수가 Deprecated 가 되었으며, 이 시스템 변수에 대한 값은 MySQL 8.0.23 버전 부터는 TABLE 이 기본값으로 사용되게 됩니다.


그 외 Replication 에서 제외할 Metadata 관련된 데이터베이스와 복제가 수행될 Database에 대해서 명시적으로 지정하도록 하겠습니다.

Slave(Replica) 에서 my.cnf 에 아래의 내용 입력 후 MySQL 재시작 합니다.

• MySQL 5.7 기준

[root]# vi /etc/my.cnf


[mysqld]
master_info_repository = 'TABLE'
relay_log_info_repository = 'TABLE'
replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = sys
# 5.7
replicate-do-db = m1testdb1
replicate-do-db = m1testdb2
replicate-do-db = m2testdb1
replicate-do-db = m2testdb2


[참고] 테이블별 복제 설정은 replicate-do-table 을 이용하시면 됩니다.
replicate-do-table = 데이터베이스명.테이블명
* MySQL 5.7 기준 설정임

• MySQL 8.0 기준

[root]# vi /etc/my.cnf

[mysqld]
master_info_repository = 'TABLE'
relay_log_info_repository = 'TABLE'
replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = sys
# mysql 8.0
replicate-do-db = ch_master1:m1testdb1
replicate-do-db = ch_master1:m1testdb2
replicate-do-db = ch_master2:m2testdb1
replicate-do-db = ch_master2:m2testdb2


[참고] MySQL8.0 부터 채널별 replicate-do-db 설정이 가능하고 채널명:DB명 으로 입력하면 됩니다.


• MySQL 재시작(Slave/Replica)

[root]# systemctl restart mysqld

      

유저 생성 및 데이터 load

복제를 구성하기 위해서 복제 전용 유저 및 복제 초기 데이터 추출 과 적재를 수행하도록 하겠습니다.
          

복제 전용 유저 생성

복제에 사용할 유저는 아래와 같이 생성하도록 하겠습니다.

mysql> create user 'repl_user'@'%' identified by 'Repl_user1234!@#$';
mysql> grant replication slave,replication client on *.* to 'repl_user'@'%';
mysql> flush privileges;



[참조] 포스팅 환경에서 Master 서버의 복제 대상 database

## Master 1
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| m1testdb1          |
| m1testdb2          |
+--------------------+

mysql> SELECT TABLE_SCHEMA,TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA LIKE '%testdb%'
order by 1,2;
+--------------+------------+
| TABLE_SCHEMA | TABLE_NAME |
+--------------+------------+
| m1testdb1    | tb_test1   |
| m1testdb2    | tb_test2   |
+--------------+------------+


## Master 2 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| m2testdb1          |
| m2testdb2          |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

mysql> SELECT TABLE_SCHEMA,TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA LIKE '%testdb%'
order by 1,2;
+--------------+------------+
| TABLE_SCHEMA | TABLE_NAME |
+--------------+------------+
| m2testdb1    | tb_test1   |
| m2testdb2    | tb_test2   |
+--------------+------------+

.          

dump 수행

2개의 Master DB에서 각각 dump 를 수행합니다

• Master 1 에서 수행

mysql> mysqldump -u아이디 -p패스워드 -v --databases m1testdb1 m1testdb2 \
 --quick --single-transaction --routines --set-gtid-purged=OFF \
 --triggers --extended-insert --master-data=2 \
 | gzip > /root/db_backup/master1_db.sql.gz

or 

## login-path 이용시
mysql> mysqldump --login-path=dba -v --databases m1testdb1 m1testdb2 \
 --quick --single-transaction --routines --set-gtid-purged=OFF \
 --triggers --extended-insert --master-data=2 \
 | gzip > /root/db_backup/master1_db.sql.gz


• Master 2 에서 수행

mysql> mysqldump -u아이디 -p패스워드 -v --databases m2testdb1 m2testdb2 \
 --quick --single-transaction --routines --set-gtid-purged=OFF \
 --triggers --extended-insert --master-data=2 \
 | gzip > /root/db_backup/master2_db.sql.gz

or 

## login-path 이용시
mysql> mysqldump --login-path=dba -v --databases m2testdb1 m2testdb2 \
 --quick --single-transaction --routines --set-gtid-purged=OFF \
 --triggers --extended-insert --master-data=2 \
 | gzip > /root/db_backup/master2_db.sql.gz


[참고] --login-path 관련해서는 아래 포스팅을 참조하시면 됩니다.

.        

데이터 load

마스터 서버에서 추출한 데이터를 전송 후 slave(replica) 에서 load를 진행합니다.

파일 전송

# Master 1
rsync -avzr --progress master1_db.sql.gz msr-replica:~/

# Master 2
rsync -avzr --progress master2_db.sql.gz msr-replica:~/

* 포스팅 환경에서  Slave(Replica) 서버의 hosts 는 msr-replica 입니다.


압축 해제 및 데이터 입력

# 압축 해제 
[root]# gunzip master1_db.sql.gz
[root]# gunzip master2_db.sql.gz


# 데이터 입력
[root]# mysql --login-path=dba < master1_db.sql
[root]# mysql --login-path=dba < master2_db.sql


추가된 데이터베이스 확인

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| m1testdb1          |
| m1testdb2          |
| m2testdb1          |
| m2testdb2          |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

        

복제 설정

이전 단계에서 복제 전용 유저 및 초기 데이터 추출 및 적재(load) 를 완료한 상태입니다.
이제 change master 명령어를 통해서 복제 설정을 진행하도록 하겠습니다.
      

Master 정보 확인

먼저 Master binlog 파일명 과 Binlog 로그 위치를 확인해야 합니다. 해당 정보는 이전의 mysqldump 에서 확인할 수 있습니다.

[root]# grep MASTER_LOG_FILE master1_db.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='wmp-binlog.000010', MASTER_LOG_POS=1649;

[root]# grep MASTER_LOG_FILE master2_db.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=2702;

          

Replication 설정

아래와 같이 channel 구문을 사용한 복제 설정을 합니다.

CHANGE MASTER (MySQL 5.7)

## binlog,log pos 정보 이용시
mysql> CHANGE MASTER TO MASTER_HOST='master1', 
MASTER_USER='repl_user', MASTER_PASSWORD='Repl_user1234!@#$',
MASTER_LOG_FILE='wmp-binlog.000010', 
MASTER_LOG_POS=1649 FOR CHANNEL 'ch_master1';

mysql> CHANGE MASTER TO MASTER_HOST='master2', 
MASTER_USER='repl_user', MASTER_PASSWORD='Repl_user1234!@#$',
MASTER_LOG_FILE='binlog.000001', 
MASTER_LOG_POS=2702 FOR CHANNEL 'ch_master2';


## GTID 이용시
mysql> CHANGE MASTER TO MASTER_HOST='master1', 
MASTER_USER='repl_user',MASTER_PASSWORD='Repl_user1234!@#$',
MASTER_AUTO_POSITION=1 FOR CHANNEL 'ch_master1';

mysql> CHANGE MASTER TO MASTER_HOST='master2',
MASTER_USER='repl_user',MASTER_PASSWORD='Repl_user1234!@#$',
MASTER_AUTO_POSITION=1 FOR CHANNEL 'ch_master2';


[참고1] GTID 모드 Replication 에서는 MASTER_AUTO_POSITION=1 를 사용 합니다.
[참고2] GTID 이용한 Replication 설정,구성은 아래 포스팅을 참조하시면 됩니다.



Binlog Position 방식과 GTID 모드 혼용을 할 경우

MSR 구성 시, 1번 마스터 서버는 Binlog Position 방식으로 되어 있고 2번 마스터 서버는 GTID 사용할 경우 2번 마스터 서버의 GTID 모드를 고려하여 Slave(Replica) 에서 gtid_mode=on 으로 GTID 를 활성화 하게 되면 Binlog Position 으로 동기화하는 채널은 아래와 같이 에러가 발생합니다.

Last_IO_Error: The replication receiver thread cannot start because the master has GTID_MODE = OFF and this server has GTID_MODE = ON.


이럴 경우 gtid_mode=off_permissive 으로 설정하면 Binlog Position 방식과 GTID 방식의 마스터 Source 를 같이 혼용(Mixed) 하여 설정할 수 있습니다.

   Master 입장에서의 동작

 Slave 입장에서의 동작

 OFF

 트랜잭션에 Global Trx ID 값을 부여하지 않음

 복제된 트랜잭션에 Global Trx ID가 부여되어 있으면 처리불가

 OFF_PERMISSIVE

 복제된 트랜잭션이 어떤 방식이든지 처리 가능

 (Anonymous / GTID 둘다 처리 가능)

 ON_PERMISSIVE

 트랜잭션에 Global Trx ID 값을 부여

 ON

 복제된 트랜잭션에 반드시 Global Trx ID가 부여되어 있어야 처리 가능

[표 출처: blog.naver.com/seuis398]



CHANGE MASTER (MySQL 8.0 ~ 8.0.22)

8.0.22 까지는 아래 명령을 통해서 수행을 합니다.

## binlog,log pos 정보 이용시
mysql> CHANGE MASTER TO MASTER_HOST="master1", 
MASTER_USER="repl_user", MASTER_PASSWORD="Repl_user1234!@#$",
GET_MASTER_PUBLIC_KEY=1,
MASTER_LOG_FILE='wmp-binlog.000005',
MASTER_LOG_POS=196 FOR CHANNEL "ch_master1";

mysql> CHANGE MASTER TO MASTER_HOST="master2", 
MASTER_USER="repl_user", MASTER_PASSWORD="Repl_user1234!@#$",
GET_MASTER_PUBLIC_KEY=1,
MASTER_LOG_FILE='binlog.000006', 
MASTER_LOG_POS=1990 FOR CHANNEL "ch_master2";

mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (m1testdb1,m1testdb2) FOR CHANNEL 'ch_master1';
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (m2testdb1,m2testdb2) FOR CHANNEL 'ch_master2';

* GTID 사용은 위의 내용을 참조하시면 됩니다.


CHANGE MASTER (MySQL 8.0.23)

8.0.23 부터는 아래 명령을 통해서 수행을 합니다.
CHANGE REPLICATION SOURCE TO .. 로 구문이 변경되었습니다.

## binlog,log pos 정보 이용시
mysql> CHANGE REPLICATION SOURCE TO SOURCE_HOST="master1", 
SOURCE_USER="repl_user", SOURCE_PASSWORD="pasRepl_user1234!@#$sword",
GET_SOURCE_PUBLIC_KEY=1,
MASTER_LOG_FILE='wmp-binlog.000005',
MASTER_LOG_POS=196 FOR CHANNEL "ch_master1";

mysql> CHANGE REPLICATION SOURCE TO SOURCE_HOST="master2", 
SOURCE_USER="repl_user", SOURCE_PASSWORD="Repl_user1234!@#$",
GET_SOURCE_PUBLIC_KEY=1,
SOURCE_LOG_FILE='binlog.000006', 
SOURCE_LOG_POS=1990 FOR CHANNEL "ch_master2";

mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (m1testdb1,m1testdb2) FOR CHANNEL 'ch_master1';
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (m2testdb1,m2testdb2) FOR CHANNEL 'ch_master2';


[참조] REPLICATION FILTER는 Dynamic 적용을 위하여 실행하는 것이며 my.cnf 에서 설정한 replicate-do-db 는 MySQL 재시작을 고려하여 설정하였습니다.


기존의 CHANGE MASTER 구문을 사용하면 가능하지만 아래처럼 Warning 메세지가 발생합니다.

Warning (Code 1287): 'CHANGE MASTER' is deprecated and will be removed in a future release. Please use CHANGE REPLICATION SOURCE instead
Warning (Code 1287): 'MASTER_HOST' is deprecated and will be removed in a future release. Please use SOURCE_HOST instead
Warning (Code 1287): 'MASTER_USER' is deprecated and will be removed in a future release. Please use SOURCE_USER instead
Warning (Code 1287): 'MASTER_PASSWORD' is deprecated and will be removed in a future release. Please use SOURCE_PASSWORD instead
Warning (Code 1287): 'MASTER_LOG_FILE' is deprecated and will be removed in a future release. Please use SOURCE_LOG_FILE instead
Warning (Code 1287): 'MASTER_LOG_POS' is deprecated and will be removed in a future release. Please use SOURCE_LOG_POS instead


GET_SOURCE_PUBLIC_KEY 와 GET_MASTER_PUBLIC_KEY 는 caching_sha2_password 관련하여 에러 발생 방지를 위해서 추가한 옵션입니다. 미사용시 아래와 같이 에러가 발생합니다.

Last_IO_Error: error connecting to master 'repl_user@master1:3306' 
- retry-time: 60 retries: 4 message: Authentication plugin 'caching_sha2_password' 
reported error: Authentication requires secure connection.



Replication 시작

• MySQL 5.7

# 각 채널별로 시작
mysql> START SLAVE FOR CHANNEL "ch_master1";
mysql> START SLAVE FOR CHANNEL "ch_master2";

or

# 모든 채널에 대해서 모두 시작
mysql> START SLAVE;


• MySQL 8.0

# 각 채널별로 시작 
mysql> START REPLICA FOR CHANNEL "ch_master1";
mysql> START REPLICA FOR CHANNEL "ch_master2"; 

or 
# 모든 채널에 대해서 모두 시작 
mysql> START REPLICA;


MySQL 8.0에서 부터는 SLAVE 용어에서 REPLICA 로 변경되었으며 명령어도 slave 대신 replica 로 변경하여 사용하면 대부분 실행됩니다.

Replication 상태 확인

# 채널별 Slave 상태 조회
mysql> SHOW SLAVE STATUS FOR CHANNEL "ch_master1"\G
mysql> SHOW SLAVE STATUS FOR CHANNEL "ch_master2"\G

or

# 전체 조회
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master1
                  Master_User: repl_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: wmp-binlog.000008
          Read_Master_Log_Pos: 194
               Relay_Log_File: relay_log-ch_master1.000005
                Relay_Log_Pos: 409
        Relay_Master_Log_File: wmp-binlog.000008
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: testdb1,testdb2,testdb1,testdb2
          Replicate_Ignore_DB: mysql,test,information_schema,performance_schema,sys,mysql,test,information_schema,performance_schema,sys
           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: 194
              Relay_Log_Space: 4344
              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: 1
                  Master_UUID: 1f3b100f-8275-11eb-b444-08002761d7ed
             Master_Info_File: mysql.slave_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: 1f3b100f-8275-11eb-b444-08002761d7ed:1412-1417
            Executed_Gtid_Set: 1f3b100f-8275-11eb-b444-08002761d7ed:1-1417,
706aaace-11d5-11eb-8127-0800279c8b61:1-678
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: ch_master1
           Master_TLS_Version: 
*************************** 2. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master2
                  Master_User: repl_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000076
          Read_Master_Log_Pos: 154
               Relay_Log_File: relay_log-ch_master2.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: binlog.000076
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: testdb1,testdb2,testdb1,testdb2
          Replicate_Ignore_DB: mysql,test,information_schema,performance_schema,sys,mysql,test,information_schema,performance_schema,sys
           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: 573
              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: 2
                  Master_UUID: 43828b8f-65cc-11eb-b96d-080027bf7f98
             Master_Info_File: mysql.slave_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: 1f3b100f-8275-11eb-b444-08002761d7ed:1-1417,
706aaace-11d5-11eb-8127-0800279c8b61:1-678
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: ch_master2
           Master_TLS_Version: 

       

관련된 추가 정보

먼저 문제 발생시 트랜잭션의 Skip은 아래 포스팅에서 3번 항목을 보시면 됩니다.


[참조] MySQL 8.0 에서는 SLAVE 대신 REPLICA 사용하면 됩니다.
             

Replication 시작

# 채널별 시작
mysql> START SLAVE FOR CHANNEL "ch_master1";
mysql> START SLAVE FOR CHANNEL "ch_master2";

or

# 모든 채널에 대해서 모두 시작
mysql> START SLAVE;

          

Replication 중지

# 채널별 중지
mysql> STOP SLAVE FOR CHANNEL "ch_master1";
mysql> STOP SLAVE FOR CHANNEL "ch_master2";

or

# 모든 채널에 대해서 모두 시작
mysql> START SLAVE;

          

Slave 상태 조회

mysql> SHOW SLAVE STATUS FOR CHANNEL "ch_master1"\G
mysql> SHOW SLAVE STATUS FOR CHANNEL "ch_master2"\G

or

# 전체 조회
mysql> show slave status\G

          

Reset Multi-Source Replicas

설정된 복제 설정 정보는 reset all 로 삭제할 수 있습니다.

# 채널별 Reset
mysql> RESET SLAVE ALL FOR CHANNEL "ch_master1";
mysql> RESET SLAVE ALL FOR CHANNEL "ch_master2";

or

# 모든 채널 Reset
mysql> RESET SLAVE ALL;

        

모니터링 채널 - Performance Schema

replication_connection_status 테이블을 사용하여 채널을 모니터링 할 수 있으며 전체 또는 채널 별로 조회할 수 있습니다.

mysql> SELECT * 
FROM performance_schema.replication_connection_status\G;

or

mysql> SELECT * 
FROM performance_schema.replication_connection_status 
WHERE CHANNEL_NAME='ch_master1'\G

           

Reference

Reference Link
 • dev.mysql.com/5.7/replication-multi-source

 • dev.mysql.com/8.0/replication-multi-source
 • dev.mysql.com/5.7/change-replication-filter
 • dev.mysql.com/8.0/change-replication-filter
 • blog.naver.com/seuis398


이어지는 글



관련된 다른글

 

 

 

 

 

 

12
0
글에 대한 당신의 생각을 기다립니다. 댓글 의견 주세요!x