본문 바로가기
넓고 얕은 데이터베이스 지식

MySQL Replication : DB 서버 이중화(master - slave)하기

by 팡펑퐁 2024. 1. 10.
728x90

📌 MySQL Replication

  • MySQL Replication은 데이터베이스 서버 간 데이터의 동기화를 위해 사용되는 기술이다.
  • 주 서버에서 변경된 데이터를 다른 서버로 복사하여 데이터의 일관성과 가용성을 보장한다.
  • MySQL Replication의 세 가지 역할
    • 첫째, 마스터 서버(master)는 데이터의 원본이 되는 서버로, 변경된 데이터를 기록하고 복제 로그(binlog)를 생성한다.
    • 둘째, 슬레이브 서버(slave)는 마스터 서버로부터 변경된 데이터를 복사받아 동기화한다.
      • 슬레이브 서버는 읽기 작업에 사용되며 읽기 부하를 분산시킬 수 있다.
    • 셋째, 중간 마스터 서버(Intermediate Master)를 이용하여 복제 체인(replication chain)을 형성해 복제의 유연성을 높일 수 있다.
  • MySQL Replication 설정은 주 서버와 슬레이브 서버 간의 통신을 위해 바이너리 로그와 중재 로그를 사용한다.
  • 주 서버에서 생성된 바이너리 로그는 슬레이브 서버로 전송되어 동기화된다.
  • 슬레이브 서버는 중재 로그를 사용하여 마스터 서버와의 통신 문제나 복제 지연을 처리한다.
  • 장점
    • 첫째, 읽기 작업을 분산시켜 성능을 향상할 수 있다.
    • 둘째, 장애 발생 시 슬레이브 서버로 트래픽을 전환하여 가용성을 보장할 수 있다.
    • 셋째, 마스터 서버의 데이터를 슬레이브 서버에서 백업하거나 복구할 수 있다.

 

📌 Master - Slave로 나누고 연결하는 방법

💡 [MASTER DB]

# 터미널
mysql -u root -p
Enter password: <비번 입력>
  • mysql db에 접속한다.
# mysql
create user <MySQL 유저명>@'%' identified by '<비밀번호>';
grant replication slave on *.* to <MySQL 유저명>@'%';
  • %는 와일드카드로, % 대신에 IP 주소를 입력하면 해당 IP 주소에서만 접속할 수 있도록 제한을 걸 수 있다.

 

master 서버의 my.cnf 파일 설정

# 터미널
vi /etc/my.cnf
  • 터미널(DB 외부)에서 설정할 차례이다.
  • cnf 파일에 들어가면 여러 설정 정보가 나오는데 vi 등 텍스트 편집기를 이용해 master - slave 설정 정보를 입력해야 한다.

 

# my.cnf 내부
[mysqld]
log-bin=mysql-bin  
server-id=1        
binlog-do-db=<DB명> 
  • log-bin : 바이너리 로그 파일이 생성될 path와 파일명을 지정할 수 있다. path가 포함되지 않을 경우 디폴트 경로에 저장된다.
    • /var/log/mysql 등
  • server-id : master와 slave 서버를 구분하는 고유 id 값이다.
  • binlog-do-db : 복제할 DB명이다.
  • i를 눌러 수정한 후 [esc] - [:wq]로 저장한다.

 

# 터미널
sudo systemctl restart mysql
sudo systemctl restart mysqld.service
  • mysql을 재시작하여 변경사항을 반영한다.
    • 만약 mysql 명령어가 작동하지 않는다면 mysqld.service 명령어를 실행하자.

 

# mysql
show master status;
  • DB 내부에서 위 명령어로 master DB상태를 확인한다.

 

# status
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      120 |  데이터베이스 명 |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
  • 여기서 File, Position을 Slave DB에서 Master와 연결할 때 사용하게 된다.
  • Binlong_Do_DB는 master-slave에 사용할 데이터베이스명으로 위의 my.cnf에 설정한 db의 이름이 나온다.

 

💡 [master - slave 간 데이터 복사]

  • 기존 MASTER DB의 데이터를 옮기는 작업을 해야 할 경우에 대한 설명이다.
  • 파일을 dump 하기 위해서는 SCP 명령어로 master와 slave 간의 dump 파일을 복사하여 slave에 파일을 복사한다.

 

데이터베이스의 데이터 dump 하기

# 터미널
# 특정 데이터베이스의 전체 데이터 dump
mysqldump -u <유저명> -p <데이터베이스명> <테이블명> > /경로/<파일명>.sql

# 특정 테이블 dump
mysqldump -u <유저명> -p <데이터베이스명> <테이블명> > /경로/<파일명>.sql

 

scp 명령어로 파일 복사하기

master → slave

# 터미널
scp ./<dump한 파일명>.sql <유저명>@<slave 서버 IP 주소>:/home/mysql/dump/ (저장할 slave 서버 경로)
  • master 서버에서 dump한 파일의 경로로 들어간다.
  • 위 명령어로 master의 dump 파일을 slave 서버에 복사한다.

 

💡 [SLAVE DB]

slave 서버의 my.cnf 파일 설정

# 터미널
vi /etc/my.cnf
  • slave 역할을 할 서버에서의 작업이다.
  • master와 마찬가지로 master - slave 설정을 하고 mysql을 재시작해야 한다.

 

# my.cnf 내부
[mysqld]
log-bin=mysql-bin  
server-id=2            
  • 위 두 내용을 추가하는데 주의해야 할 점은 server-id는 master와 다르게 해야 한다는 것이다.

 

# 터미널
sudo systemctl restart mysql
sudo systemctl restart mysqld.service
  • mysql을 재시작한다.

 

master - slave 연결하기

# mysql
reset slave;
  • 기존 slave 설정을 지워 초기화하는 작업이다.(slave 작업을 한 경우)

 

# master의 mysql에서 show master status;를 입력했을 때의 출력값
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      120 |  데이터베이스 명 |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
  • 위에서 master의 설정이 끝난 후 나온 master status를 다시 가져왔다.
  • 아래의 명령어 입력시 참고하여 적는다.

 

# mysql
change master to master_host='<master db ip>', master_user='<master 유저명>', master_password='<master 유저 비밀번호>', master_log_file='<위의 File 값(mysql-bin.000001)>', master_log_pos=<위의 Position>;
  • slave의 mysql에서 입력한다.
  • master 유저명과 비밀번호는 위에서 create 명령문을 통해 생성한 replication 권한을 가진 유저의 것이다.

 

# mysql
start slave;
start replica;
  • 연결 쿼리가 끝나면 준비 작업은 끝이다.
  • 위 명령어로 slave의 replication 작업을 시작해 보자.
    • mysql 버전마다 다른듯한데 slave or replica 둘 중에 하나이다.(stop도 마찬가지)

 

# mysql
stop slave;
stop replica;
  • 참고로 중지하고 싶다면 위 명령어를 사용하면 된다.

 

연결 상태 확인하기

# mysql
show slave status\\G;
  • 위 명령어로 slave의 상태를 자세히 확인할 수 있다.
  • \G는 줄 바꿈을 통해 보기 편하게 만들기 위한 옵션 명령어이다.

 

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 147.46.161.172
                  Master_User: master7
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 1441
               Relay_Log_File: mysqld-relay-bin.000003
                Relay_Log_Pos: 516
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_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_Master_Log_Pos: 1441
              Relay_Log_Space: 1801
              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: 7a4149d2-1dcd-11ed-ba86-b496918622ec
             Master_Info_File: /var/lib/mysql/master.info
                    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
           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: 
                Auto_Position: 0
1 row in set (0.00 sec)

ERROR: 
No query specified
  • 명령어를 실행하면 여러 설정 정보가 출력되어 나오는데
  • Slave_IO_Running: Yes
  • Slave_SQL_Running: Yes
  • 이 두 정보가 핵심이며 모두 Yes일 경우에만 정상적으로 연결된 것이다.
    • 만약 연결에 실패하여 에러가 발생하면 에러 원인이 출력된다.

 

🚨 에러 발생 시

# 터미널
vi /etc/my.cnf

# my.cnf 내부
[mysqld]
...
slave-skip-errors=all
  • 에러가 발생한 경우 발생 시점 이후의 쿼리는 갱신되지 않기 때문에 이 Error를 넘기기 위해서는 해당 에러를 해결한 뒤 my.cnf에 skip을 위한 설정값을 추가하고 mysql을 restart 해주면 된다.

 

 

 

참고

https://jane096.github.io/project/mysql-master-slave-replication/

https://hnev.tistory.com/50

https://hnev.tistory.com/51

https://hnev.tistory.com/52

728x90