Featured image of post 16.5 복제 - 복제 동기화 방식

16.5 복제 - 복제 동기화 방식

Real MySQL 8.0

MySQL 서버에서는 소스 서버와 레플리카 서버 간의 복제 동기화에 대해 두가지 방식을 제공한다.

  • 비동기 복제(Asynchronous replication): 오래전부터 사용되어왔다.
  • 반동기 복제(Semi-synchronous replication): MySQL 5.5 버전부터 도입되었다.

비동기 복제

MySQL 복제는 기본적으로 비동기 방식으로 동작한다.

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

소스 서버에서 커밋된 트랜잭션은 바이너리 로그에 기록되며, 레플리카 서버에서는 주기적으로 신규 트랜잭션에 대한 바이너리 로그를 소스 서버에 요청한다.

비동기 복제 방식에서 소스 서버는 레플리카 서버로 변경 이벤트가 잘 전달됐는지, 실제로 적용됐는지 알지 못하며 이에 대한 어떠한 보장도 하지 않는다.

이로 인해 소스 서버에 장애가 발생하면 소스 서버에서 최근까지 적용된 트랜잭션이 레플리카 서버로 전송되지 않아 누락된 트랜잭션이 발생할 수 있다.

만약 소스 서버 장애로 인해 레플리카 서버를 새로운 소스 서버로 승격시키는 경우 사용자는 이 레플리카 서버가 소스 서버로부터 전달받지 못한 트랜잭션이 있는지 직접 확인하고 그런 것들이 있다면 필요 시 레플리카 서버에 수동으로 다시 적용해야 한다.


이처럼 비동기 복제는 소스 서버가 레플리카 서버의 동기화 여부를 보장하지 않는다는 것이 가장 큰 단점이지만 소스 서버가 각 트랜잭션에 대해 레플리카 서버로 전송되는 부분을 고려하지 않기 때문에 몇가지 장점이 있다.

  • 트랜잭션 처리시 좀 더 빠른 성능을 보인다.
  • 레플리카 서버에 문제가 생기더라도 소스 서버에는 아무런 영향도 받지 않는다.
  • 비동기 복제 방식은 소스 서버에 레플리카 서버를 여러 대 연결한다고 해도 소스 서버에서 큰 성능 저하가 없다.
    • 10대 이상 연결하는 경우 성능 저하가 있을 수 있다.
  • 레플리카 서버에 무거운 쿼리가 실행되어 성능 저하가 있더라도 소스 서버와는 관계가 없으므로 분석 용도 등으로 사용하기 좋다.

이러한 장점으로 인해 레플리카 서버를 확장해서 읽기 트래픽을 분산하는 용도로 사용하기 적합하다.

반동기 복제

반동기 복제는 비동기 복제보다 좀 더 향상된 데이터 무결성을 제공하는 복제 동기화 방식이다.

  1. 소스 서버가 레플리카 서버에 변경 이벤트를 보냄
  2. 레플리카 서버가 전달받은 변경 이벤트를 릴레이 로그에 기록 후 응답(ACK)을 보냄
  3. 소스 서버가 레플리카 서버에게 응답을 받으면 트랜잭션을 완전히 커밋
  4. 클라이언트에 결과를 반환

이러한 과정을 통해 소스 서버에서 커밋되어 정상적으로 결과가 반환된 모든 트랜잭션들에 대해 적어도 하나의 레플리카 서버에는 해당 트랜잭션들이 전송되었음을 보장한다.

하지만 레플리카 서버에 전송이 되었음을 보장한다는 것이지, 실제로 복제된 트랜잭션이 레플리카 서버에 적용된 것까지 보장하는 것은 아니다.

반동기 복제에서는 소스 서버가 트랜잭션 처리 중 어느 지점에서 레플리카 서버의 응답을 기다리느냐에 따라 소스 서버에서 장애가 발생했을 때 사용자가 겪을 수 있는 문제 상황이 조금 다를 수 있다.

사용자는 rpl_semi_sync_master_wait_point 시스템 변수를 통해 소스 서버가 레플리카 서버의 응답을 기다리는 지점을 제어할 수 있다.

  • AFTER_SYNC:

    • 소스 서버에서는 각 트랜잭션을 바이너리 로그에 기록하고 난 후 스토리지 엔진에 커밋하기 전 단계에서 레플리카 서버의 응답을 기다리게 된다.
    • 레플리카 서버로부터 정상적으로 응답이 내려오면 소스 서버는 그때 스토리지 엔진을 커밋해서 트랜잭션에 대한 처리를 완전히 끝내고 트랜잭션을 실행한 클라이언트에 그 처리 결과를 반환한다.
  • AFTER_COMMIT

    • 소스 서버에서 트랜잭션을 바이너리 로그에 기록하고 스토리지 엔진에서의 커밋도 진행하고 나서 최종적으로 클라이언트에 결과를 반환하기 전에 레플리카 서버의 응답을 기다린다.
    • 레플리카 서버로부터 응답이 내려오면 그때 클라이언트는 처리 결과를 얻고 그 다음 쿼리를 실행할 수 있다.

처음 반동기 복제가 도입됐을 때는 스토리지 엔진 커밋까지 완료 후 대기하는 AFTER_COMMIT 방식으로만 동작했으나, MySQL 5.7 버전에서 AFTER_SYNC 방식이 도입된 후 MySQL 8.0 버전에서 기본 동작 방식으로 채택되었다.

AFTER_SYNCAFTER_COMMIT 비교

AFTER_SYNC 방식은 AFTER_COMMIT보다 무결성이 강화된 방식으로 다음과 같은 장점이 있다.

팬텀 리드

AFTER_COMMIT에서는 트랜잭션이 스토리지 엔진 커밋까지 처리된 후 레플리카 서버의 응답을 기다리는데, 스토리지 엔진 커밋까지 완료된 데이터는 다른 세션에서도 조회가 가능하다.

따라서 소스 서버가 어떤 트랜잭션에 대해 스토리지 엔진 커밋 후 레플리카 서버로부터 응답을 기다리고 있는 상황에서 소스 서버의 장애가 발생한 경우, 사용자는 이후 새로운 소스 서버로 승격된 레플리카 서버에서 데이터를 조회할 때 자신이 이전 소스 서버에서 조회했던 데이터를 보지 못할 수도 있다.

AFTER_SYNC는 소토리지 엔진 커밋 전에 레플리카 서버의 응답을 기다리므로 응답을 기다리던 중에 소스 서버에 장애가 발생하더라도 팬텀 리드 현상을 겪지 않게 한다.

장애 복구

AFTER_COMMIT은 소스 서버에서 커밋되었으나 레플리카 서버로 복제는 되지 않은 상황에서 장애가 발생한 소스 서버를 재사용하는 경우, 사용자가 수동으로 트랜잭션들을 롤백시켜야한다.

AFTER_SYNC 방식은 레플리카 서버에 복제되지 않았지만 소스 서버에는 커밋되어 실제 데이터에 반영된 트랜잭션들이 존재하는 경우가 발생하지 않기 때문에 별도 롤백 처리를 하지 않아도 된다.

반동기 복제라 하더라도 소스 서버에 장애가 발생했을 때 소스 서버의 데이터와 레플리카 서버의 데이터가 달라지는 경우가 발생할 수 있으므로 장애가 발생한 소스 서버를 바로 재사용하지 않는 것이 좋다.

유입된 트랜잭션의 수가 많다면 레플리카 서버의 트랜잭션 반영 여부를 확인하는 것은 거의 불가능하므로, 백업된 데이터를 새로 구축해 사용하는 것이 좋다.

성능 및 주의사항

  • 반동기 복제는 트랜잭션을 처리하는 중에 레플리카 서버의 응답을 기다리므로 비동기 방식과 비교했을 때 트랜잭션의 처리 속도가 더 느릴 수 있다.
    • 최소 레플리카 서버로 응답을 요청하고 전달받기 까지의 네트워크 왕복 시간만큼 더 걸림
    • 레플리카 서버에서 응답이 늦어지는 경우 더 큰 지연 발생
    • 이처럼 네트워크 통신으로 인한 지연을 예방하기 위해 레플리카 서버 물리적으로 가깝게 위치하는게 유리할 수 있다.
  • 소스 서버에서 설정된 타임아웃 시간을 초과하면 자동으로 비동기 복제 방식으로 전환한다.

반동기 복제 설정 방법

MySQL 서버에서 반동기 복제 기능은 플러그인 형태로 구현돼 있으므로 이를 사용하려면 먼저 관련 플러그인을 설치해야 한다.

1
2
3
4
5
/* 소스 서버 */
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_mastser.so';

/* 레플리카 서버 */
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

플러그인이 정상적으로 설치됐는지는 information_schema.PLUGINS 테이블을 조회하거나 SHOW PLUGINS 명령을 통해 확인할 수 있다.

1
2
3
4
5
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM information_schema.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';

SHOW PLUGINS;

반동기 복제 사용을 위해 관련 시스템 변수들을 적절히 설정해야 하는데, 이 시스템 변수들은 플러그인이 정상적으로 설치된 이후 SHOW GLOBAL VARIABLES 명령 등에서 확인할 수 있다.

  • rpl_semi_sync_master_enabled:
    • 소스 서버에서 반동기 복제 활성화 여부를 제어한다. ON(1), OFF(0)
  • rpl_semi_sync_master_timeout:
    • 소스 서버에서 레플리카 서버의 응답이 올 때까지 대기하는 시간으로, 밀리초 단위로 설정할 수 있다.
    • 레플리카 서버의 응답이 지정된 시간을 초과하면 비동기 복제로 전환한다. 기본값: 10000 (10초)
  • rpl_semi_sync_master_trace_level:
    • 소스 서버에서 반동기 복제에 대해 디버깅 시 출력되는 로그 수준에 대한 레벨을 지정한다.
    • 1, 16, 32, 64 지정 가능
  • rpl_semi_sync_master_wait_for_slave_count:
    • 소스 서버에서 반드시 응답을 받아야하는 레플리카 수를 결정한다.
    • 기본값: 1, 설정 가능 값: 1 ~ 655535
    • 응답을 받아야 하는 레플리카 수가 많을수록 소스 서버에서의 처리 성능은 저하될 수 있다.
  • rpl_semi_sync_master_wait_no_slave:
    • 설정된 타임아웃 시간 동안 소스 서버에서 반동기 복제로 연결된 레플리카 서버 수가 지정된 수 보다 적어졌을 때 어떻게 처리할것인지 결정한다.
    • ON(1): 반동기 복제를 그대로 유지, OFF(0): 즉시 비동기 복제로 전환
  • rpl_semi_sync_master_wait_point:
    • 소스 서버가 트랜잭션 처리 단계 중 레플리카 서버의 응답을 대기하는 지점을 설정.(AFFTER_SYNC(기본값), AFFTER_COMMIT)
  • rpl_semi_sync_slave_enabled:
    • 레플리카 서버에서 반동기 활성화 여부를 제어. ON(1), OFF(0)
  • rpl_semi_sync_slave_trace_level:
    • 레플리카 서버에서 반동기 복제에 대한 디버깅 수준 레벨을 설정한다.
    • 1, 16, 32, 64 지정 가능

rpl_semi_sync_master_wait_point 시스템 변수는 MySQL 5.7.2 버전에서 AFFTER SYNC 방식이 도입되며 추가된 변수로, 이전 버전과 이후 버전 간의 반동기 복제시 설정시 반동기 복제가 제대로 동작하지 않을 수 있다.

소스 서버와 레플리카 서버가 기존에 복제가 실행 중인 상태라면 반동기 복제 적용을 위해 다음과 같이 레플리카 서버에서 레플리케이션 I/O 스레드를 재시작 해야한다.

반동기 복제가 잘 적용되었는지는 SHOW GLOBAL STATUS 명령을 통해 확일할 수 있다.