공부/프로그래밍

[docker] MariaDB replication(master-slave) 설정

demonic_ 2018. 10. 25. 15:00



이 글을 작성하는 컴퓨터는 Mac을 사용해 공용폴더인 /Users/Shared 에 설정했습니다.

실행하기 앞서 도커가 설치 & 실행되어 있어야 합니다


참조글: 

[docker] MariaDB + 로컬에 데이터저장소 연결

http://lemontia.tistory.com/740




# mariadb 실행시 참조파일 생성

docker 에서 mariadb를 올릴때 환경설정을 참조할 수 있도록 파일을 생성합니다.

bin 로그를 이용하여 replication을 하기 때문에 관련 설정을 해주어야 하고, service-id 를 지정해줍니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /Users/Shared/data/maria/conf/ 아래 각각 폴더에 다음의 mysql.cnf 파일 생성 및 작성합니다
## master 서버용
vi /Users/Shared/data/maria/conf/master/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1
 
## slave 서버용
vi /Users/Shared/data/maria/conf/slave/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=2
relay-log=relaylog
log-slave_updates=1
cs



# mariadb 설정파일 적용하여 실행

도커를 실행할 떄 위의 설정파일을 참조하도록 옵션을 추가합니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## master 컨테이너 띄울 때
docker container run --13306:3306   \
-e MYSQL_ROOT_PASSWORD=pwd123   \
-/Users/Shared/data/maria/master:/var/lib/mysql   \
-/Users/Shared/data/maria/conf/master:/etc/mysql/conf.d   \
--name maria-master mariadb
 
## slave 컨테이너 띄울 때
## 도커가 컨테이너를 띄울때 내부IP를 사용하는데 이 아이피가 고장되어 있지 않기 때문에 컨테이너 간의 접근할 때 아이피로 접근이 가능한 것도 추후 다시 띄웠을때 달라지는 경우가 있습니다. 그렇기 때문에 컨테니어 연결이 필요할 때에는 link를 통해 미리 지정하는게 좋습니다.
docker container run --23306:3306   \
-e MYSQL_ROOT_PASSWORD=pwd123   \
-/Users/Shared/data/maria/slave:/var/lib/mysql      \
-/Users/Shared/data/maria/conf/slave:/etc/mysql/conf.d      \
--link maria-master   \
--name maria-slave mariadb
cs


-p 13306:3306     << 포트포워딩 합니다

-e MYSQL_ROOT_PASSWORD      << root 패스워드를 설정합니다.

-v /Users/Shared/data/maria/master:/var/lib/mysql      << volume 를 지정합니다.(저장소)

-v /Users/Shared/data/maria/conf/master:/etc/mysql/conf.d     << volume 를 지정합니다.(설정파일위치)

--name maria-master     << docker container 이름을 지정합니다

--link maria-master   << link 를 이용해 IP뿐 아니라 별칭연결도 가능하도록 합니다.


1
2
3
4
# master 서버 접속
mysql -u root -ppwd123 --port 13306 --host 127.0.0.1
# slave 서버 접속
mysql -u root -ppwd123 --port 23306 --host 127.0.0.1
cs




# master 상태 확인

master, slave의 mysql에 접속하여 각각 아래명령어를 입력해 봅니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SHOW MASTER STATUS\G 
 
### master 부분
*************************** 1. row ***************************
            File: mysql-bin.000002
        Position: 328
    Binlog_Do_DB: 
Binlog_Ignore_DB: 
1 row in set (0.001 sec)
 
### slave 부분
*************************** 1. row ***************************
            File: mysql-bin.000001
        Position: 328
    Binlog_Do_DB: 
Binlog_Ignore_DB: 
1 row in set (0.001 sec)
cs



# master 에서 database 및 User 생성

데이터베이스 생성(User도 자동으로 생성됩니다)


1
2
3
4
5
6
7
8
9
10
11
12
13
create database repldb;
grant all privileges on repldb.* to repldb@'%' identified by 'replpw';
# slave 서버에서 master 서버에 접속할 수 있도록 권한 추가
grant replication slave on *.* to 'repldb'@'%';
flush privileges;
 
# 테이블을 생성해둡니다
use repldb;
create table repltable ( no int(8), primary key (no) ); 
 
## 생성된 유저 확인
use mysql;
select user, host from user;
cs



# Master 서버에서 DB dump(호스트에서 dump.sql 로 저장)

replication 을 등록하기 전에 둘의 데이터를 맞춰두기 위해 dump를 이용합니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 데이터 dump
docker exec maria-master mysqldump -uroot -ppwd123 repldb > dump.sql
cat dump.sql
 
# slave 서버에 dump 파일 옮기고 롤백
docker cp dump.sql maria-slave:.
docker exec -it maria-slave bash
mysql -uroot -ppwd123
CREATE DATABASE repldb;
exit
mysql -uroot -ppwd123 repldb < dump.sql
 
 
# slave에 유저를 생성합니다.(root로만 접근할 거라면 이 부분은 생략해도 됩니다)
# slave 서버 root 로 접근합니다
mysql -u root -ppwd123 --port 23306 --host 127.0.0.1
CREATE USER 'repldb'@'%' IDENTIFIED BY 'replpw'
grant all privileges on repldb.* to repldb@'%' identified by 'replpw';
flush privileges;
cs



# slave 서버에서 master 서버 등록하기

마스터와 슬레이브가 서로 다른 position과 file을 볼 수 있으므로 마스터에서 확인해야 합니다


1
2
3
4
5
6
7
8
mysql -u root -ppwd123 --port 13306 --host 127.0.0.1
SHOW MASTER STATUS\G 
*************************** 1. row ***************************
            File: mysql-bin.000002
        Position: 2264
    Binlog_Do_DB: 
Binlog_Ignore_DB: 
1 row in set (0.001 sec)
cs


slave 에서 아래 명령어를 입력하여 등록합니다.

- 명령어를 작성할때 MASTER_LOG_FILE 과 MASTER_LOG_POS 를 위의 정보와 일치시킵니다.

- 도커를 띄울때 --link  로 연결해 두었다면 별칭으로도 접속이 가능합니다.

- 만약 --link 를 이용하지 않았다면 master 의 ip 정보가 필요합니다.


1
2
3
4
5
6
7
## docker의 link 옵션을 사용했을 경우
CHANGE MASTER TO MASTER_HOST='maria-master',
MASTER_USER='repldb', MASTER_PASSWORD='replpw', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1223;
 
## docker의 link 옵션을 사용하지 않았을 경우 IP 등록
CHANGE MASTER TO MASTER_HOST='172.17.0.2',
MASTER_USER='repldb', MASTER_PASSWORD='replpw', MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=2809;
cs


slave 를 시작하고 제대로 연결되었는지 확인합니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
start slave;
 
SHOW SLAVE STATUS\G  
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: maria-master
                   Master_User: repluser
                   Master_Port: 3306
                 Connect_Retry: 60
               Master_Log_File: mysql-bin.000004
           Read_Master_Log_Pos: 2809
                Relay_Log_File: relaylog.000002
                 Relay_Log_Pos: 555
         Relay_Master_Log_File: mysql-bin.000004
              Slave_IO_Running: Yes
             Slave_SQL_Running: Yes
               Replicate_Do_DB: repldb
           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: 2809
               Relay_Log_Space: 857
               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_SSL_Crl: 
            Master_SSL_Crlpath: 
                    Using_Gtid: No
                   Gtid_IO_Pos: 
       Replicate_Do_Domain_Ids: 
   Replicate_Ignore_Domain_Ids: 
                 Parallel_Mode: conservative
                     SQL_Delay: 0
           SQL_Remaining_Delay: NULL
       Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
              Slave_DDL_Groups: 0
Slave_Non_Transactional_Groups: 0
    Slave_Transactional_Groups: 0
cs


Last_Errno 와 Last_IO_Error 필드에 0이면 성공적으로 구성된 것입니다.




# Replication 테스트하기

마스터에 접속 => 연결된 스키마(repldb)에 접속 => 데이터 삽입


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# master 에서 실행합니다
mysql -u root -ppwd123 --port 13306 --host 127.0.0.1
use repldb
insert into repltable values (1), (2);
Query OK, 2 rows affected (0.004 sec)
Records: 2  Duplicates: 0  Warnings: 0
 
select * from repltable;
+----+
| no |
+----+
|  1 |
|  2 |
+----+
2 rows in set (0.001 sec)
 
 
## 슬레이브에 접속해서 데이터를 확인해 봅니다
select * from repltable;
+----+
| no |
+----+
|  1 |
|  2 |
+----+
2 rows in set (0.001 sec)
cs


이로서 구성이 완료되었습니다.


replication은 bin로그를 기준으로 추후 쌓이는 정보에 대해서만 데이터를 복제합니다. 만약 master에 데이터가 있었는데, 이후 change master 명령어를 이용해 새로설정한다면 이후부터 쌓이는 데이터만 저장이 되고 이전의 정보는 저장되지 않아 100% 싱크되진 않습니다. 즉 엮인 시점부터 DB 의 변화를 동기화 합니다. 만약 이것을 맞춰주고 싶다면 물리적으로 데이터를 복사해주거나 dump 등을 이용해야 합니다.


그리고 slave를 끈 상태로(docker stop) 데이터를 삽입하고 다시 slave 를 실행하면(docker run) 데이터복사를 자동으로 합니다.

복사대상은 DDL(create, alter, drop)문과 DML(insert, update, delete)문 등이 기록됩니다.


그리고 위의 세팅의 경우 DBMS 전체의 로그를 복사하는 것이므로 database 등을 추가해도 복제가 됩니다. 만약 특정 스키마만 복사하고 싶을경우 아래와 같이 작성합니다.


설정은 둘중 하나만 하면 되는데, 개인적인 의견으로는 슬레이브에 추천합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
### my.cnf 파일을 엽니다.
# database 를 동기화 할 경우
[mysqld]
...
replicate-do-db = DB1
 
table 을 동기화 할 경우
replicate-do-table = DB1.table
 
 
# 여기서는 repldb 를 연결했기 때문에 slave 에 다음과 같이 설정했습니다.
여기서 적용하기 위해 slave의 my.cnf 파일을 다음과 같이 추가
[mysqld]
log-bin=mysql-bin
relay-log=relaylog
log-slave_updates=1
server-id=2
replicate-do-db = repldb
cs




참조:
https://jupiny.com/2017/11/07/docker-mysql-replicaiton/

https://javalove93.postach.io/post/mac-docker-gibaneuro-mysql-replication-guseong-teseuteu

http://whiterussian.tistory.com/44

http://horae.tistory.com/entry/MySQL-Mysql-%EB%A6%AC%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98Replication-%EC%8B%A4%EC%8B%9C%EA%B0%84-DB-%EB%8F%99%EA%B8%B0%ED%99%94