"데이터 복제는 조직 내에서 데이터의 가용성, 신뢰성 및 내구성을 보장하기 위한 방법으로, 동일한 데이터의 여러 복사본을 다른 위치에 생성하고 유지하는 과정입니다."
데이터베이스 리플리케이션(Replication)은 실시간 복제본 데이터베이스 서버를 운용하는 것을 의미한다. 기준이 되는 서버를 마스터 서버라 하고, 마스터 서버와 동일한 내용을 갖는 또 다른 서버를 ‘리플리카(Replica)’라 한다.
어플리케이션은 데이터베이스에 SQL 명령을 보내 데이터를 삽입/변경/삭제하게 되는데, 마스터 서버는 SQL 명령을 수신하면 그 SQL 명령을 리플리카 서버에도 똑같이 보낸다. 이렇게 되면 마스터 서버와 리플리카 서버의 데이터가 동일한 상태로 유지된다.
데이터베이스 리플리케이션의 목적은 크게 실시간 Data 백업과 부하 분산으로 볼 수 있다.

Master 서버에 DBMS의 INSERT/UPDATE/DELETE가 생기면 Slave 서버에 변경된 데이터를 전달하게 된다. 이러한 과정으로 데이터의 백업을 할수 있으며, Master 서버의 장애가 생겼을 경우 Slave 서버로 변경하여 사용할 수 있다.

Master 서버를 INSERT/UPDATE/DELETE를 사용하는 서버로 사용하고, Slave 서버를 데이터를 읽는 용도로 사용하게 되면 DBMS의 부하를 분산하는 용도로 사용할 수 있다.
이외에도 분석용 쿼리들을 실행하기 위한 리플리카 서버를 구축하는 데이터 분석용 목적, 어플리케이션 서버와 DB 서버가 서로 떨어져 있는 경우 두 서버 간 통신 시간이 거리에 비례해 늘어나 서비스 응답 속도에도 영향을 끼치므로 어플리케이션 서버 위치에 리플리카 서버를 구축함으로써 응답 속도를 개선하는 데이터의 지리적 분산 목적 등이 있다.
MySQL에서 복제 동기화가 처리되는 전반적인 과정은 다음과 같다.

MySQL의 복제는 세 개의 스레드에 의해 작동한다. 스레드 하나는 소스 서버에 존재하고, 나머지 두 개는 리플리카 서버에 존재한다.
바이너리 로그 덤프 스레드: 바이너리 로그의 내용을 소스 서버에서 리플리카 서버로 전송한다. 리플리카 서버로 보낼 각 이벤트를 읽을 때 일시적으로 바이너리 로그에 잠금을 수행하며, 이벤트를 읽고난 후에 잠금을 해제한다.
리플리케이션 I/O 스레드: 복제가 시작되면 생성되어 소스 서버의 바이너리 로그 덤프 스레드로부터 바이너리 로그 이벤트를 가져와 로컬 서버의 파일로 저장한다. 복제가 멈추면 종료된다.
리플리케이션 SQL 스레드: I/O 스레드에 의해 작성된 릴레이 로그 파일의 이벤트들을 읽고 실행한다.
MySQL의 복제는 소스 서버의 바이너리 로그에 기록된 변경 내역들을 식별하는 방식에 따라 바이너리 로그 파일 위치 기반 복제와 글로벌 트랜잭션 ID 기반 복제로 나뉜다.

각 방식의 동작원리를 살펴보자.

바이너리 로그 파일 위치 기반 복제는 MySQL에 복제 기능이 처음 도입됐을 때부터 제공된 방식으로, 리플리카 서버에서 소스 서버의 바이너리 로그 파일명과 파일 내에서의 위치로 개별 바이너리 로그 이벤트를 식별해서 복제가 진행되는 형태를 말한다.
이 방식은 다음과 같은 단점이 존재한다.
소스 서버에서만 유효한 식별 방식이라는 단점이 존재한다.
소스 서버에 문제가 생겨 다른 리플리카 서버가 소스 서버로 승격이 되면, 이 복제에 참여하는 다른 데이터베이스 서버들은 이 위치를 다시 찾아야 하기 때문에 복구에 시간이 걸린다.
동일한 이벤트가 레플리카 서버에서도 동일한 파일명의 동일한 위치에 저장된다는 보장이 없다.
이로 인해 복제의 토폴로지 변경이 어려워 복제를 이용한 장애 복구가 어렵다.
MySQL 5.6 버전부터는 이러한 단점을 해결하기 위해 글로벌 트랜젝션 아이디 기반 복제를 기본 복제 방식으로 사용하고 있다.

글로벌 트랜잭션 아이디 기반 복제는 복제에 참여한 전체 MySQL 서버들에서 고유하도록 각 이벤트에 부여된 식별 값인 GTID를 기반으로 복제가 진행되는 형태다. 이 값들은 모두 동일하기 때문에 동일한 이벤트에 대해서 동일한 글로벌 트랜젝션만 읽어오면 반영할 수 있다.
바이너리 로그에 이벤트가 어떤 포맷으로 기록되는지는 복제가 처리되는 과정에 영향을 준다.
MySQL에서는 다음과 같은 두 종류의 바이너리 로그 포맷을 제공한다.
사용자는 binlong_format 시스템 변수를 통해 이 두 가지 종류 중 하나로 설정하거나 혼합된 형태로 사용할 수 있다.
각 포맷 방식에 대해 살펴보자.

Statement 기반 바이너리 로그 포맷은 변경 이벤트에 대해 이벤트를 발생시킨 SQL문을 바이너리 로그에 기록하는 방식이다.
이러한 단점들을 해결하기 위해 MySQL 5.7.7 버전부터는 Row기반 바이너르 로그 포맷을 기본으로 사용하고 있다.

Row 기반 바이너리 로그 포맷 방식은 MySQL 서버에서 데이터 변경이 발생했을 때 변경된 값 자체가 바이너리 로그에 기록되는 방식이다.
MySQL 서버가 두 가지 바이너리 로그 포맷을 혼합해서 사용하도록 설정할 수 있다.

MySQL에서는 소스 서버와 레플리카 서버 간의 복제 동기화에 대해 다음과 같은 두 가지 방식을 제공한다.
각 방식의 동작 방식과 장단점에 대해 살펴보자.

비동기 복제는 MySQL의 기본적 동작 방식으로 소스 서버가 자신과 복제 연결된 리플리카 서버에서 변경 이벤트가 정상적으로 전달되어 적용되었는지를 확인하지 않는 방식이다.

반동기 복제는 비동기 복제보다 좀 더 향상된 데이터 무결성을 제공하는 복제 동기화 방식이다.
반동기 복제에서 소스 서버는 리플리카 서버가 소스 서버로부터 전달받은 변경 이벤트를 릴레이 로그에 기록 후 응답(ACK)을 보내면 그때 트랜잭션을 완전히 커밋시키고 클라이언트에 결과를 반환한다.
반동기 복제 방식은 리플리카 서버에 전송됐음을 보장하지만, 실제로 복제된 트랜잭션이 리플리카 서버에 적용되는 것까지는 보장하지 않는다.
MySQL의 여러 복제 토폴로지를 살펴보자.





우아한테크코스 테코톡 앤지의 DB Replication
Real MySQL 8.0 - 2