Mysql의 모든 변경 사항은 바이너리 로그(Binary log)라는 곳에 순서대로 기록됩니다. 이곳에 저장된 각 변경 정보를 이벤트라고 합니다. Mysql의 복제는 이 바이너리 로그를 기반으로 구현됐습니다. 바이너리 로그가 소스서버에서 레플리카 서버로 전달되고, 레플리카 서버가 이를 로컬 디스크에 저장 후 내용을 반영하는 구조입니다.
레플리카 서버에서 읽어들인 바이너리 로그를 디스크에 저장해둔 파일을 릴레이 로그(Relay log)라 합니다.
Mysql의 복제는 세 개의 스레드에서 동작합니다. 트랜잭션 처리 스레드(바이너리 로그 스레드)를 제외하고, 소스 서버에 존재하는 바이너리 로그 덤프 스레드와 레플리카 서버에 존재하는 레플리케이션 I/O 스레드와 레플리케이션 SQL 스레드가 존재합니다.
레플리카 서버가 소스 서버에 접속해 데이터 동기화를 요청하면, 소스 서버는 바이너리 로그 덤프 스레드를 생성해서 바이너리 로그 내용을 레플리카 서버로 전송합니다.
바이너리 로그 덤프 스레드는 레플리카 서버로 보낼 각 이벤트를 읽을 때, 일시적으로 바이너리 로그에 잠금을 걸고, 이벤트가 끝나면 잠금을 해제합니다.
show processlist
명령어를 통해 스레드를 확인할 수 있습니다.
복제가 시작되면 레플리카 서버는 I/O 스레드를 생성하고, 복제가 멈추면 종료시킵니다. I/O 스레드는 소스 서버의 바이너리 로그 덤프 스레드로부터 바이너리 로그 이벤트를 가져와, 로컬 서버의 파일(릴레이 로그)에 저장합니다.
show replica status
명령의 결과에서 Replica_IO_Running
명령어를 통해 확인할 수 있습니다.
SQL 스레드는 I/O 스레드에 의해 작성된 릴레이 로그 파일의 이벤트들을 읽고 실행합니다.
show replica status
명령의 결과에서 Replica_SQL_Running
명령어를 통해 확인할 수 있습니다.
레플리카 서버에서 I/O 스레드와 SQL 스레드는 서로 독립적으로 동작해서, SQL 스레드의 이벤트 적용이 느려도 I/O 스레드는 소스 서버에서 빠르게 이벤트를 읽어올 수 있습니다. 레플리카 서버의 변경 사항 적용은 소스 서버의 동작과 별개로 일어나므로, 레플리카 서비스의 문제에 소스 서버는 영향을 받지 않습니다. 하지만 소스 서버의 문제 발생으로 레플리카 서버의 I/O 스레드가 정상적으로 동작하지 않으면, 에러가 발생하고 복제가 중단됩니다.
하지만 이는 복제 기능만 중단됐을 뿐, 레플리카 서버의 쿼리 처리에는 문제가 없습니다. 다만 레플리카 서버는 동기화되지 못해 예전 상태의 데이터를 보유하게 됩니다.
복제가 시작되면, 레플리카 서버는 릴레이 로그를 비롯해 기본적으로 세 가지 유형의 복제 관련 데이터를 생성 및 관리합니다.
I/O 스레드에 의해 작성되는 파일입니다. 소스 서버의 바이너리 로그에서 읽어온 이벤트(트랜잭션) 정보가 저장됩니다.
릴레이 로그는 바이너리 로그와 마찬가지로, 현재 존재하는 릴레이 로그 파일들의 목록이 담긴 인덱스 파일과, 실제 이벤트 정보가 저장돼 있는 로그 파일로 구성됩니다.
이곳에 저장된 트랜잭션 이벤트들은, SQL 스레드에 의해 레플리카 서버에 적용됩니다.
I/O 스레드에서 소스 서버에 연결할 때 사용되는 정보들이 담기는 곳입니다.
db계정, 현재 읽고 있는 소스 서버의 바이너리 파일명과 파일 내 위치 값 등이 있습니다.
위 정보는 mysql.slave_master_info
테이블에 저장됩니다.
SQL 스레드에서 릴레이 로그에 저장된 소스 서버의 이벤트들을, 레플리카 서버에 적용하는 컴포넌트를 어플라이어라고 합니다.
어플라이어 메타데이터는 최근 적용된 이벤트에 대해, 해당 이벤트가 저장돼 있는 릴레이 로그 파일명과 파일 내 위치 정보 등을 담고 있습니다. SQL 스레드는 이 정보를 바탕으로 레플리카 서버에 나머지 이벤트를 저장합니다.
위 정보는 slave_relay_log_info
테이블에 저장됩니다.
커넥션 및 어플라이어 메타데이터는 파일 형식으로 저장할지, 테이블 형식으로 저장할지 선택할 수 있는데, MYSQL 8.0.2 버전부터 기본값이 테이블로 변경됐습니다. 파일 설정 시 I/O 스레드와 SQL 스레드가 동작할 때 동기화되지 않는 경우가 발생했기 때문이라 합니다.
테이블로 설정하면 모두 InnoDB 기반 테이블로 관리되고, SQL 스레드가 트랜잭션을 적용할 때 slave_relay_log_info
테이블(어플라이어 메타데이터)의 데이터도 atomic 하게 업데이트 되므로, 예기치 않게 MYSQL이 종료될 때에도 트랜잭션이 보장되어 재구동시 복제가 문제없이 진행됩니다. 이를 크래시-세이프 복제라고 합니다.
다음 포스팅에서는 복제 타입에 대해서 알아보도록 하겠습니다.