본문 바로가기

데이터 사이언스 DataScience/Data Base 데이터베이스

[MySQL] DB 이중화 1) Replication

Oracle은 RAC라는 공유DB클러스터 기능을 제공해

어느정도 규모가 있으며, 안정성을 추구하는 기업의 DBMS로 널리 쓰이고 있다. 

 

쉽게 말하면 여러 개의 WAS 인스턴스를 LOAD BALANCING 하는 것과 동일하게, 

여러 개의 DB 인스턴스 서버를 LOAD BALANCING 하여 CPU, MEMORY, DB I/O 자원을 분산시키는 것이다.

 

이때 데이터의 정합성, 부하 분산의 안정성, 성능의 우수함 등이 시장에서 증명되었기에 

비싼 라이센스 비용에도 불구하고 널리 쓰이고 있다. 

 

 

하지만, MSA로 서비스가 분산된다면 여러 대의 Active 인스턴스가 아닌

단일 Active 인스턴스 자원만으로 DBMS의 기능을 다 할 수 있다.

 

다만, 1개의 Active 인스턴스로 서비스를 제공하더라도, 

Active 인스턴스 장애시 failover 할 수 있는 DB 시스템을 구성하는 것은 온라인 상용 서비스에서는 필수적이다. 

 

 

 

이 때, MySQL의 이중화는 Master - Slave DB 구조로 Replication을 이용할 수 있다.

MHA 나 Galera Cluster 등을 활용할 경우 더 효과적인 서비스를 제공할 수 있다.

 

처음 구축해보기때문에 다른 솔루션/라이브러리를 붙이기보단, 

 

MySQL 고유의 Replication 기능을 활용해서 

Master (Active)  -  Slave (Passive) DB를 구성했고

아래 그림처럼 여러 디바이스에 마이그레이션할 수 있는 형태로 구축해봤다.

 

 

이렇게 구성한 이유는 

1) 동일 디바이스에서 구현할 경우 이중화, DR 서버의 느낌이 안 살것 같았다. (물리, 네트워크 분리) 

2) 컨테이너(도커) 활용을 통해 OS, 디바이스에 종속되지 않는 이중화 시스템을 만들어보고 싶었다.

3) 외장 SSD를 샀는데 쓸데가 마땅치않아 활용처를 만들어보고 싶었다. 

4) 미래에 맥북을 살 명분이 없는데, 사야하는 이유를 만들고 싶었다.

 

서버 접속 정보는 위와 같이 구성했다.

동일한 스키마, 테이블 이름을 만들어줬고 user이름과 비밀번호도 새로 생성해서 맞춰줬다.

 

MasterDB에서 특정 User, PW만 통해서 권한부여를 한다면 SlaveDB의 IP는 반드시 필요하지는 않았다.

 

* 전체적인 설정은 아래와 같이 했다.

 - DB SCHEMA, TABLE은 동일하게 생성되어있다고 가정.

 

 

1. Master DB (Windows11) 에서의 설정

-- 1) Replication을 수행할 USER 생성, 권한 부여
create user repl_user@'%' identified by 'mariadb';
grant replication slave on *.* to 'repl_user'@'%' identified by 'mariadb';
grant all privileges on subcoding.test1 to repl_user@'%' identified by 'mariadb';

 

2) MySQL 설정 변경 (Windows11)

  설정파일 my.ini 위치 확인을 위해 mysql --help 입력 후 파일 위치 확인.

C:\Program Files\MariaDB 10.5\data\my.ini에서 확인

[mysqld] 항목에 

log-bin=mysql-bin
server-id=1

추가

 

3) MySQL 재시작

net stop mariadb;

net start mariadb;

-- 윈도우의 경우 관리자 권한으로 /MariaDB/bin 에서 실행

 

4) Master 정보 확인 (File, position 확인해서 Slave DB에서 정합성 맞추기)

mysql> show master status;

 

 

2. Slave DB (Ubuntu) 에서의 설정

1) my.cnf 파일 수정, 계정준비

   -- ubuntu, docker 환경

 

sudo vim /etc/mysql/my.cnf에 아래 내용 추가

[mysqld]

server-id=2

replicate-do-db='subcoding'

  -- 특정 db만 replication 할 경우

--  Replication을 수행할 USER 생성, 권한 부여
create user repl_user@'%' identified by 'mariadb';
grant all privileges on subcoding.test1 to repl_user@'%' identified by 'mariadb';

 

 

2) 재시작 후 mysql에서 slave 설정

 

sudo docker stop mariadb

sudo docker start mariadb

 

mysql>
stop slave;



change master to
master_host='172.30.1.2',
master_user='repl_user',
master_password='mariadb',
master_log_file='mysql-bin.000007',
master_log_pos=3321;

-- log_file, log_pos는 master db에서 show master status; 로 확인한 내용

start slave;

 

sudo docker stop mariadb

sudo docker start mariadb

 

 

3) show slave status로 확인

 열심히 일하는 slave의 마음가짐.jpg

 "Waiting for master to send event"

 

가 뜨면 Master DB에서 DML 수행을 통해 정상적으로 Replication 이 되는지 확인.

 

 

 

* 발생했던 문제점들 / 새롭게 알게된점

 - error log는 주로 slave DB instance에서 show slave; 를 통해 확인할 수 있다.

1. Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids;

   - Slave DB의 my.cnf 파일에 server-id=2 를 설정해줬는데 DB 재가동시 반영되지 않아 server-id가 1로 되어있었다. 

      set global server_id = 2;   로 설정을 변경해서 해결

 

 

2. Master DB에서 Insert into (Select MAX + 1) 으로 값 생성시 서로 다른 값의 데이터가 추가됐다.

  예를 들어 아래와 같이 ID에 차이가 있는 테이블에서 

INSERT INTO `subcoding`.`test1`
VALUES 
(
(SELECT ifnull(MAX(a.mem_id)+1, 1)
FROM `subcoding`.`test1` a),
'test123',
'test123'
);
COMMIT;

위 SQL 실행시 Master DB에서는 MEM_ID 4인 데이터가 생성됐지만, 

Slave DB에서는 MEM_ID 3인 데이터가 생성됐다.

추가 확인은 해봐야겠지만, LOG파일로 떨어지는 데이터가 Master DB에서 실행된 DML 그대로일 것으로 추측된다.

 

전반적으로 SCN 기반으로 변경사항을 체크하는 Oracle 로직과 비슷하다는 생각이 들었다. 

OGG의 Extractor, Replicator와도 유사점이 많다는 생각이 든다.

 

 

 

* MySQL 이중화 참고한 글 :

https://rumblekat.github.io/dev/2022/01/11/DB.html

https://server-talk.tistory.com/240

 

* RAC(Real application clusters) 참고 내용:

https://www.oracle.com/database/real-application-clusters/

반응형