재직중인 회사에서 고객사별 데이터베이스 관리에 있어 Master-Slave 패턴을 이용한다.
Master 서버에서는 쓰기 연산이 가능하지만, Slave 서버에서는 읽기 연산만 가능하다. 그래서, 업무 중에 운영 상황에서 필요한 데이터 처리는 쓰기 연산 SQL 쿼리를 작성하여 Master 서버에서 하며, 그 외에 데이터 확인용 단순 Select 쿼리는 Slave 서버에서 한다.
이 방식에 익숙해지기만 하였고 대략 안정성 때문에 도입된 방식이라고만 생각하였는데, 이 개념에 대하여 자세히 정리해보았다.
데이터베이스 다중화와 Replication
많은 데이터베이스 관리 시스템이 다중화를 지원하며, 보통은 서버 사이에 Master-Slave 관계를 설정하고 데이터 원본은 Master 서버에, 사본은 Slave 서버에 저장하는 방식이다. 쓰기 연산은 Master에서만 지원하고, Slave 서버는 Master 서버로부터 그 사본을 전달받으며, 읽기 연산만을 지원한다. 이 방식을 다른 말로 Replication 이라고한다.
왜 Select 작업을 따로 뺄까?
보통 Select 작업이 시간이 많이 걸리기 때문이다. 데이터가 5만개가 있는데 Table Full Scan을 해야 하거나 한다면 시간을 엄청나게 잡아 먹을 것이다. 그리고 이 시간동안 다른 작업을 하지 못하게 되니 병목 현상의 주요 원인이라고 할 수 있다.
또한, 대부분의 애플리케이션은 읽기 연산의 비중이 쓰기 연산보다 훨씬 높다. 따라서, 통상 Slave 데이터베이스의 수가 Master 데이터베이스의 수보다 많다.

Replication은 '바이너리 로그'를 통하여 이루어진다. Slave에 데이터를 복제할 때 로그 기반으로 복제되며, MySQL이 제공하는 바이너리 로그에는 3가지 종류가 있는데 링크를 참고하자.
바이너리 로그란
MySQL 서버에서 Create, Alter, Drop과 같은 작업을 수행하면 MySQL은 그 변화된 이벤트를 기록하는데 이러한 변경사항들에 대한 정보를 담고 있는 이진 파일을 바이너리 로그 파일이라고한다. 이때 show나 select와 같은 조회 문법은 제외된다.
MySQL Replication 동작 원리
MySQL의 Replication은 기본적으로 비동기 복제 방식을 사용하고 있다. Master 서버에서 변경되는 데이터에 대한 이력을 로그에 기록하면 Replication Master Thread가 비동기적으로 이를 읽어서 Slave 쪽으로 전송한다.
MySQL 에서 Replication 을 위해 반드시 필요한 요소는 다음과 같다.
- Master 에서의 변경을 기록하기 위한 Binary Log
- Binary Log 를 읽어서 Slave 쪽으로 데이터를 전송하기 위한 Master Thread
- Slave 에서 데이터를 수신하여 Relay Log 에 기록하기 위한 I/O Thread
- Relay Log 를 읽어서 해당 데이터를 Slave 에 Apply(적용)하기 위한 SQL Thread
위의 구성 요소들은 아래 그림에서 보는 Flow 대로 데이터 복제를 수행한다.

- 클라이언트(Application)에서 Commit 을 수행한다.
- Connection Thead 는 스토리지 엔진에게 해당 트랜잭션에 대한 Prepare(Commit 준비)를 수행한다.
- Commit 을 수행하기 전에 먼저 Binary Log 에 변경사항을 기록한다.
- 스토리지 엔진에게 트랜잭션 Commit 을 수행한다.
- Master Thread 는 시간에 구애받지 않고(비동기적으로) Binary Log 를 읽어서 Slave 로 전송한다.
- Slave 의 I/O Thread 는 Master 로부터 수신한 변경 데이터를 Relay Log 에 기록한다. (기록하는 방식은 Master 의 Binary Log 와 동일하다)
- Slave 의 SQL Thread 는 Relay Log 에 기록된 변경 데이터를 읽어서 스토리지 엔진에 적용한다.
데이터베이스 다중화 장점
- 더 나은 성능 : 모든 데이터 변경 연산은 Master 서버로만 전달되는 반면 읽기 연산은 Slave 서버들로 분산된다. 병렬로 처리될 수 있는 쿼리의 수가 늘어나므로, 성능이 좋아진다.
- 안정성 : 데이터베이스 서버 가운데 일부가 파괴되어도 데이터는 보존될 것이다. 데이터를 지역적으로 떨어진 여러 장소에 다중화시켜 놓을 수 있기 때문이다.
- 가용성 : 데이터를 여러 지역에 복제해 둠으로써, 하나의 서버에 장애가 발생하더라도 다른 서버에 있는 데이터를 가져와 계속 서비스할 수 있게 된다.
Master 서버가 다운되면, 한 대의 Slave 서버만 있는 경우 해당 Slave 서버가 새로운 Master 서버가 될 것이며, 모든 데이터베이스 연산은 일시적으로 새로운 Master 서버에서 수행될 것이다. 그리고 새로운 Slave 서버가 추가될 것이다.
만약, 기존 Slave 서버에 보관된 데이터가 최신 상태가 아닐 경우라면?
없는 데이터는 복구 스크립트를 돌려서 추가해야한다. 이런 문제를 해결하려면 다중 마스터(Multi-Masters), 원형 다중화(Circular Replication) 방식을 생각할 수 있다.
다중 마스터
Master 서버를 두 대 이상 두는 것을 의미한다. 모두가 Master의 권한을 지니며 각 서버별 쓰기 연산이 가능하고, 현 Master에서 업데이트 발생 시 다른 모든 Master 서버에 비동기적으로 전파되어 업데이트, 일관성을 유지한다. 각 Master는 선택적으로 Slave 서버를 생성할 수도 있다.
원형 다중화
각 서버를 Master와 Slave로 설정하는 방식이다. 각 서버를 Master로 설정하고 모든 Master에 Slave가 있을 때까지 다른 Master에 Slave로 설정한다. 이렇게 하면 각 변경 사항이 체인의 다음 서버로 복제됨에 따라 정보의 순환 흐름이 발생한다.
참고 사이트
http://cloudrain21.com/mysql-replication
https://www.jamescoyle.net/how-to/1549-mysql-circular-replication
'CS 공부 > 데이터베이스' 카테고리의 다른 글
레디스(Redis) 란? (0) | 2022.07.23 |
---|---|
이상현상 (Anomaly) (0) | 2022.07.16 |
SQL과 NOSQL의 차이 (0) | 2022.07.10 |