[MySQL] DB 관리를 위한 서버 이중화(Replication) - 1편

선상원·2024년 10월 20일
0

mysql

목록 보기
7/12

작성일: 2023-03-31 (금)


오늘의 주제는 “Replication” 입니다.

Replication 이란 ??

  • 2대 이상의 별도 서버에 DBMS를 나누어 데이터를 저장하는 방식
  • 사용하기 위한 최소 구성은 Master / Slave 구성

MySQL에서는 Replication 기능을 기본적으로 제공하고 있습니다.
그로 인해 많은 기업에서는 On-Premises MySQL 사용 시, 이중화 구성을 통해 데이터를 보호하고 있습니다.

오늘은 MySQL Replication 에서도 가장 기본적인 Master / Slave 구성을 세팅하는 작업을 진행해 보겠습니다.

[MySQL] 데이터 복제 동작 원리

기본적으로 Master 서버에서 데이터 변경이 발생하면 Binary Log 에 해당 내용이 기록됩니다.
내용 기록이 완료된 시점에서 Master 서버는 Slave 서버로 해당 Binary Log 내용을 전달하게 되며, Slave 서버에서는 전달받은 내용을 Relay Log 에 기록한 뒤, 해당 내용을 읽어 데이터 동기화를 진행합니다.

  1. Master 서버 데이터 변경 > 바이너리 로그 저장
  2. Master 서버에서 Slave 서버로 바이너리 로그 파일 전달
  3. 전달받은 바이너리 로그 파일을 Slave 서버에서는 Relay Log 파일에 저장한 후 데이터 동기화 진행

MySQL 이중화 구성 (환경 세팅)

이번 게시글에서는 도커 컨테이너를 사용해 빠르게 이중화를 구성합니다.

  • 운영환경: Docker / MySQL 5.7
  • 마스터DB
    • PORT: 3306
  • 슬레이브DB
    • PORT: 3307

  1. Docker Container 세팅

    # MySQL 5.7 이미지 다운로드 (이미지가 없을 경우, run 명령어를 통해 자동 다운로드 가능)
    docker pull mysql:5.7
    
    # 도커 네트워크 생성 (Master - Slave 서버간의 통신을 위한 내부망 생성)
    docker network create mysql-network
    
    # Master 서버 생성
    docker run -d -p 3306:3306 \
    --platform linux/amd64 \
    -v /home/mysql_user/mysql/data:/var/lib/mysql \
    -v /home/mysql_user/mysql/my.cnf:/etc/my.cnf \
    -e MYSQL_ROOT_PASSWORD=mysql1234 \
    --network mysql-network \
    --name mysql-master mysql:5.7
    
    # Slave 서버 생성
    docker run -d -p 3307:3307 \
    --platform linux/amd64 \
    -v /home/mysql_user/mysql_slave/data:/var/lib/mysql \
    -v /home/mysql_user/mysql_slave/my.cnf:/etc/my.cnf \
    -e MYSQL_ROOT_PASSWORD=mysql1234 \
    --network mysql-network \
    --name mysql-slave mysql:5.7
  2. my.cnf 파일 수정

    # log-bin 옵션의 경우 사용자 별도의 이름 지정 가능
    
    # Master 서버
    [mysqld]
    port      = 3306
    log-bin   = mysql-bin
    server-id = 1
    
    # Slave 서버
    [mysqld]
    port      = 3307
    log-bin   = mysql-bin
    server-id = 2
  3. my.cnf 파일 권한 수정 및 서버 재시작

    # 처음 컨테이너를 생성하여 MySQL 서버를 띄웠을 경우,
    # 마운트한 로컬 my.cnf 파일을 적용하지 않기 때문에 사용자 권한을 수정한 뒤 서버 재시작
    
    # Master & Slave
    chmod 644 /etc/my.cnf
    
    docker restart mysql-master mysql-slave
  4. [Master] 테스트 데이터베이스 및 테이블 생성

    CREATE DATABASE repl;
    
    CREATE TABLE repl.test01 (
    `idx` INT AUTO_INCREMENT NOT NULL COMMENT 'Primary KEY',
    `name` VARCHAR(30) NOT NULL COMMENT 'User Name',
    `wtime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Data Insert Time',
    PRIMARY KEY(idx),
    KEY (`name`),
    KEY (`wtime`)
    ) COMMENT='무중단 REPLICATION TEST TABLE'
    ;

MySQL 이중화 구성 (서버 연결)

  • 마스터DB
    • HOST: mysql-master
    • PORT: 3306
    • User: repl_user
    • PW: mysql1234
  • 슬레이브DB
    • HOST: mysql-slave
    • PORT: 3307
    • User: repl_user
    • PW: mysql1234
# Master DB & Slave DB
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'mysql1234' ;
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%' ;
FLUSH PRIVILEGES;

이중화 전용 서비스 계정에 부여되는 권한을 주의해야 합니다.
권한을 최소화하여 보안을 신경쓰는 습관이 필요합니다.


  1. 마스터DB 서버 정보 확인

    # Master DB
    # File + Position 기록
    mysql> SHOW MASTER STATUS \G;
    *************************** 1. row ***************************
                 File: mysql-bin.000001
             Position: 154
         Binlog_Do_DB:
     Binlog_Ignore_DB:
    Executed_Gtid_Set:
    1 row in set (0.00 sec)
  2. Master - Slave 연결

    # Slave DB
    change master to
    master_host='mysql-master', 
    master_user='repl_user', 
    master_password='mysql1234', 
    master_log_file='mysql-bin.000001', 
    master_log_pos=154 ;
    
    # Slave 정보 확인
    mysql> SHOW SLAVE STATUS \G;
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: mysql-master
                      Master_User: repl_user
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000001
              Read_Master_Log_Pos: 154
                   Relay_Log_File: b18a27af7131-relay-bin.000001
                    Relay_Log_Pos: 320
            Relay_Master_Log_File: mysql-bin.000001
                 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: 154
                  Relay_Log_Space: 534
                  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: 5d485bcf-c6f9-11ed-bae5-0242ac110002
                 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 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: 
                    Auto_Position: 0
             Replicate_Rewrite_DB: 
                     Channel_Name: 
               Master_TLS_Version: 
    1 row in set (0.01 sec)
    • Replication 정상 연결 확인
      • Slave_IO_Running: Yes
        • 마스터 바이너리 로그를 읽기 위한 I/O 스레드가 실행 중인지 여부
        • 아직 복제를 시작하지 않았거나 복제를 중지(STOP SLAVE)한 경우 NO 로 표시
      • Slave_SQL_Running: Yes
        • 릴레이 로그에서 이벤트를 실행하기위한 SQL 스레드가 실행 중인지 여부
        • 로그상태나 복제 상태에 문제가 있을 경우 NO 로 표시
        • 상태가 “NO” 일 경우, Last_Error 내용을 참고하여 해결
      • Seconds_Behind_Master: 0
        • Slave 서버의 SQL 스레드가 Master 서버의 바이너리 로그를 처리하는 시간 (초)
        • 숫자가 지속적으로 늘어날 경우, 해당 현상에 대해서 원인 파악이 중요하며, 순간적인 데이터 로드가 많거나 성능상에 문제는 없는지 확인해야 함

💡 오늘은 MySQL 에서 기본적으로 제공하는 데이터베이스 이중화 작업을 진행해 보았습니다.

서비스의 초기 구축 과정이라면 위의 방법만으로 쉽게 이중화를 구성할 수 있겠지만,
대부분의 기업에서는 서비스 운영 과정에서 이중화 구성을 진행하게 될 것입니다.

이러한 경우 무조건 마스터DB 서버의 데이터를 백업하고, 백업본을 통해 슬레이브DB 서버를 구축해야만 합니다.

다음 시간에는 서비스 운영 과정 과정에서 이중화 구성을 어떻게 진행하는지 살펴보겠습니다.

profile
쉼 없는 고민과 학습을 통해 가장 효율적인 데이터베이스 관리 방안을 찾고자 노력하는 DBA 입니다.

0개의 댓글