MySQL Master-Slave Replication 구성 및 테스트
이번 글에서는 Docker Compose를 이용해 MySQL Master-Slave 구조를 구성하고, 복제가 제대로 작동하는지 확인하는 방법을 소개한다.
1. docker-compose.yml 구성
version: '3.8'
services:
master:
image: mysql:5.7
platform: linux/amd64
container_name: mysql-master
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./master/my.cnf:/etc/mysql/conf.d/my.cnf
- ./master/init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3307:3306"
slave:
image: mysql:5.7
platform: linux/amd64
container_name: mysql-slave
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./slave/my.cnf:/etc/mysql/conf.d/my.cnf
depends_on:
- master
ports:
- "3308:3306"
- platform: linux/amd64 -> mysql:5.7 이미지는 ARM 아키텍처(macOS M1/M2 등)에서 작동하지 않기 때문에 설정을 추가
- master와 slave 컨테이너는 각각 3307, 3308 포트를 통해 접근할 수 있다.
- 초기 설정 및 복제 유저 생성은 master/init.sql에서 수행된다.
- 설정 파일은 각각 my.cnf로 분리되어 server-id, log-bin 등의 복제 설정을 포함한다.
2. Master 상태 확인
docker exec -it mysql-master mysql -uroot -proot
이 명령어는 Master에서 현재 바이너리 로그 파일명(File)과 복제를 시작할 위치(Position)를 확인하는 데 사용된다.
binlog가 정상적으로 동작한느지 확인할 수 있다.
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 154 | testdb | | |
+------------------+----------+--------------+------------------+-------------------+
3. Slave 복제 설정
docker exec -it mysql-slave mysql -uroot -proot
mysql> CHANGE MASTER TO
-> MASTER_HOST='mysql-master',
-> MASTER_USER='replica',
-> MASTER_PASSWORD='replica_pass',
-> MASTER_LOG_FILE='mysql-bin.000003',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql>
mysql> START SLAVE;
- MASTER_HOST는 docker-compose 내 서비스 이름(mysql-master)을 그대로 사용한다.
- MASTER_LOG_FILE, MASTER_LOG_POS는 앞서 Master에서 확인한 값을 입력한다.
- MASTER_LOG_POS는 offset으로 master에서 확인한 현재 지점이 154로, 지금부터 복제하겠다는 뜻이 된다. (처음부터 복제한다면 0)
4. 복제 상태 확인
mysql> SHOW SLAVE STATUS;
+----------------------------------+--------------+-------------+-------------+---------------+------------------+---------------------+------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+----------------------------+-----------+---------------------+--------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+
| Slave_IO_State | Master_Host | Master_User | Master_Port | Connect_Retry | Master_Log_File | Read_Master_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Master_Log_File | Slave_IO_Running | Slave_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_Master_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Master_SSL_Allowed | Master_SSL_CA_File | Master_SSL_CA_Path | Master_SSL_Cert | Master_SSL_Cipher | Master_SSL_Key | Seconds_Behind_Master | Master_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Master_Server_Id | Master_UUID | Master_Info_File | SQL_Delay | SQL_Remaining_Delay | Slave_SQL_Running_State | Master_Retry_Count | Master_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Master_SSL_Crl | Master_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Master_TLS_Version |
+----------------------------------+--------------+-------------+-------------+---------------+------------------+---------------------+------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+----------------------------+-----------+---------------------+--------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+
| Waiting for master to send event | mysql-master | replica | 3306 | 60 | mysql-bin.000003 | 154 | relay-log.000004 | 367 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 154 | 1559 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 130f7fd1-743d-11f0-ad75-aa9c922af0ab | /var/lib/mysql/master.info | 0 | NULL | Slave has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | |
+----------------------------------+--------------+-------------+-------------+---------------+------------------+---------------------+------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+----------------------------+-----------+---------------------+--------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+
출력 결과에서 아래 두 항목이 모두 Yes여야 정상적으로 복제가 시작된 상태다.
Slave_IO_Running: Yes, Slave_SQL_Running: Yes 이면 복제 시작
이외에도 Slave_SQL_Running_State가 Slave has read all relay log; waiting for more updates처럼 나오는 경우, 현재 Master에서 더 이상 새로운 변경 사항이 없다는 의미다.
5. Master에 데이터 삽입
docker exec -it mysql-master mysql -uroot -proot
mysql> use testdb;
Database changed
mysql> CREATE TABLE users (
-> id INT AUTO_INCREMENT PRIMARY KEY,
-> name VARCHAR(100),
-> email VARCHAR(100)
-> );
', 'alice@example.com');
INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');
SELECT * FROM users;
Query OK, 0 rows affected (0.06 sec)
mysql>
mysql> INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> SELECT * FROM users;
+----+-------+-------------------+
| id | name | email |
+----+-------+-------------------+
| 1 | Alice | alice@example.com |
| 2 | Bob | bob@example.com |
+----+-------+-------------------+
2 rows in set (0.01 sec)
- users 테이블을 생성하고 데이터를 두 건 추가한다.
- 추가한 결과 조회
6. Slave에서 복제된 데이터 확인
docker exec -it mysql-slave mysql -uroot -proot
mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> SELECT * FROM users;
+----+-------+-------------------+
| id | name | email |
+----+-------+-------------------+
| 1 | Alice | alice@example.com |
| 2 | Bob | bob@example.com |
+----+-------+-------------------+
2 rows in set (0.01 sec)
- Master에서 입력한 users 테이블의 데이터가 동일하게 Slave에서도 조회되어야 한다.
- 복제가 성공적으로 수행 완료
'Database > DB' 카테고리의 다른 글
| [논문] Presto: SQL on Everything / A Decade of SQL Analytics at Meta / History-based Query Optimizer (2) | 2025.08.27 |
|---|---|
| 3. MySQL CDC 데이터를 Debezium을 통해 Pub/Sub으로 전송하기 (1) | 2025.08.17 |
| 1. mysql binlog (0) | 2025.08.11 |
| [논문] The Log-Structured Merge-Tree (LSM-Tree) (5) | 2025.08.09 |
| postgreSQL wal_level (0) | 2025.01.10 |