DBMS 2

DA, SQL, DB보안 등 실무자를 위한 위한 DB기술 바이블!

리플리케이션

DBMS 2
MySQL 가이드
리플리케이션
작성자
admin
작성일
2021-02-19 10:55
조회
1398

리플리케이션 소개

MySQL은 단 방향, 즉 비동기 리플리케이션 (asynchronous replication)을 지원하는데, 하나의 서버는 마스터로 동작하고, 나머지 한 개 이상의 다른 서버들은 슬레이브로 동작한다. 이것은 MySQL클러스터의 특징인 동기화 (synchronous) 리플리케이션과는 반대되는 개념이다. ( Chapter 15, MySQL 클러스터)를 참조할 것.

싱글-마스터 리플리케이션에서, 마스터 서버는 업데이트를 자신의 바이너리 로그 파일에 작성하고 로그 로테이션의 트레이스 (trace)를 유지하기 위해 이 파일의 인덱스를 유지 관리 한다. 바이너리 로그 파일은 다른 슬레이브 서버에 전달되는 업데이트 레코드 역할을 한다. 슬레이브가 자신의 마스터에 연결이 될 때, 마스터 정보를 자신이 마지막으로 업데이트가 성공했을 때 읽었던 로그에 전달한다. 슬레이브는 그 시간 이후에 발생한 모든 사항에 대한 업데이트를 전달 받고, 블록 (block)을 한 후에 마스터가 새로운 업데이트를 알려 주기를 기다리게 된다.

슬레이브 서버를 체인드 리플리케이션 서버 (chained replication server)로 설정하면, 자신이 마스터 역할을 하게 된다.

다중-마스터 (Multiple-master) 리플리케이션은 가능 하기는 하지만, 싱글-마스터 리플리케이션에서는 발생하지 않는 문제들이 나타나게 된다. Section 6.13, “다중 마스터 리플리케이션에서 자동 인크리먼트”를 참조.

리플리케이션을 사용하는 경우, 복제된 테이블에 대한 모든 업데이트는 마스터 서버에서 실행 되어야 한다. 그렇지 않으면, 사용자가 마스터에 있는 테이블에서 행하는 업데이트와 슬레이브에서 행하는 업데이트간의 충돌을 피하도록 항상 주의해야만 한다.

리플리케이션은 견고성, 속도, 그리고 시스템 관리에 많은 혜택을 제공한다:


  • 견고성 (Robustness)은 마스터/슬레이브 설정을 가지고 증가된다. 마스터에서 문제가 발생하면, 백업 형태의 슬레이브로 전환할 수 있다.
  • 마스터와 슬레이브 서버 간에 클라이언트 쿼리 처리를 분산함으로써 클라이언트에 대해 보다 개선된 응답 시간을 제공해 줄 수 있다. 슬레이브에 SELECT 쿼리를 전달해서 마스터의 쿼리 처리 업무를 줄여 줄 수 있다. 마스터와 슬레이브의 동기화가 끊어지지 않도록 하기 위해 데이터를 수정하는 명령문들은 여전히 마스터에 전달 된다. 이러한 로드 밸런싱 전략은 업데이트 하지 않는 (non-updating) 쿼리가 압도적으로 많은 경우에는 효과적이다.
  • 또 다른 리플리케이션 이점은 마스터의 방해 없이 슬레이브 서버를 사용해서 데이터베이스 백업을 실행할 수 있다는 것이다. 마스터는 백업이 진행되는 동안에도 업데이트 프로세스를 계속 한다. Section 5.10.1, “데이터 베이스 백업”을 참조할 것.

리플리케이션 구현 개론

MySQL 리플리케이션의 기본 메커니즘은 마스터 서버의 바이너리 로그에 있는 데이터 베이스의 모든 변경 (업데이트, 삭제, 등) 사항에 대한 마스터 서버 유지 트랙에 기초를 하고 있다. 따라서, 리플리케이션을 사용하기 위해서는, 마스터 서버 바이너리 로깅을 활성화 시켜야 한다. Section 5.12.3, “바이너리 로그”를 참고할 것.

마스터 서버에 연결된 각 슬레이브 서버는 마스터 서버가 자신의 바이너리 로그에 기록해둔 업데이트 사항을 전달 받으며, 따라서 슬레이브는 데이터 복사본에서 동일한 업데이트를 실행할 수 있게 된다.

바이너리 로그는 단순히 바이너리 로깅을 활성화 시킨 시점부터 시작된 기록에 불과하다는 것을 이해하는 것이 절대적으로 중요하다. 여러분이 설정한 모든 슬레이브는 여러분이 마스터 서버에서 바이너리 로깅을 활성화 시켰던 시점에 존재 했던 것과 같은 마스터 서버 데이터 베이스 복사본을 필요로 한다. 만약에 바이너리 로그가 시작될 때 마스터에 있었던 것과 같은 상태의 데이터 베이스가 아닌 다른 것을 가지고 슬레이브를 시작한다면, 여러분은 슬레이브 구동에 실패를 할 것이다.

마스터 데이터를 슬레이브로 복사하는 한 가지 방법은 LOAD DATA FROM MASTER 명령문을 사용하는 것이다. 하지만, LOAD DATA FROM MASTER는 마스터에 있는 모든 테이블이 MyISAM 스토리지 엔진을 사용할 때에만 제대로 동작한다. 부가적으로, 이 명령문은 글로벌 읽기 잠금 (read lock)을 갖기 때문에, 테이블이 슬레이브로 전달되는 동안에는 마스터에서는 어떠한 업데이트도 할 수 없게 된다. 잠금 -해제 핫 테이블 (lock-free hot table) 백업을 실행하면, 이 글로벌 읽기 잠금 기능은 더 이상 필요 없게 된다.

이러한 제약으로 인해, 마스터에 있는 데이터 셋이 상대적으로 작거나, 또는 마스터에서 연기된 읽기 잠금이 수용될 때에만 LOAD DATA FROM MASTER를 사용하기를 권장한다. 비록 LOAD DATA FROM MASTER의 실제 속도가 시스템에 따라 다양하다고 하더라도, 경험적으로는 1MB의 데이터 당 1초가 걸린다. 이것은 대략적인 측정값이지만, 마스터와 슬레이브가 둘 다 동일하게700MHz 팬티엄 CPU를 가지고 있고 100Mbps 네트워크에 연결되어 있는 경우에 거의 정확하다는 것을 알게 될 것이다.

슬에이브가 마스터의 데이터 복사본을 가지고 설정이 되면, 슬레이브는 마스터에 접속을 하고 업데이트가 진행되기를 기다리게 된다. 만약에 마스터가 실패 (fail)를 하거나 또는 슬레이브가 마스터와 접속이 끊어지게 되면, 슬레이브는 업데이트에 대한 정보를 다시 들을 수 있을 때까지 주기적으로 접속을 시도하게 된다. --master-connect-retry 옵션은 재시도 간격을 제어한다. 디폴트 값은 60초이다.

각 슬레이브는 자신의 마스터로부터 마지막으로 업데이트를 읽었을 때 어디에서 중단 되었는지에 대한 트랙을 유지한다. 마스터는 자신이 얼마나 많은 슬레이브를 가지고 있는지 또는 어느 것이 주어진 시간에서 갱신 되었는지 알지 못한다.


리플리케이션 구현 상세 설명

리플리케이션 마스터 쓰레드 상태
‘리플리케이션 슬레이브 I/O 쓰레드 상태
리플리케이션 슬레이브 SQL 쓰레드 상태
리플리케이션 릴레이 및 상태 파일

MySQL 리플리케이션은 세 개의 쓰레드를 사용해서 구현된다 (하나는 마스터에서 구현되며 나머지 두 개는 슬레이브에서 구현된다). START SLAVE 명령문이 슬레이브 서버에 입력되면, 슬레이브 서버는 하나의 I/O 쓰레드를 생성하는데, 이 쓰레드는 마스터에 접속하여 마스터 바이너리 로그에 기록되어 있는 업데이트 사항을 요청한다. 마스터는 쓰레드를 하나 생성해서 바이너리 로그의 내용을 슬레이브에 보낸다. 이 쓰레드는 마스터 서버에서 실행되는 SHOW PROCESSLIST 결과에서 Binlog Dump 쓰레드 형태를 갖게 된다. 슬레이브 I/O 쓰레드는 마스터 Binlog Dump 쓰레드가 로컬 파일로 보내서 복사본을 만드는 릴레이 로그라는 업데이트 내용을 슬레이브 데이터 디렉토리에서 읽는다. 세 번째 쓰레드는 SQL 쓰레드이며, 이것은 슬레이브가 릴레이 로그를 읽고 그 안에 있는 것들을 실행하기 위해 생성하는 쓰레드다.

앞에서 설명을 하였듯이, 마스터/슬레이브 접속 별로 세 개지고 있는 하나의 마스터는 현재 접속되어 있는 각각의 슬레이브 별로 하나의 쓰레드를 생성하고, 각 슬레이브는 자신만의 I/O 와 SQL 쓰레드를 가지게 된다.

슬레이브는 마스터에서 업데이트된 것을 읽고 이것들을 실행시키기 위해 서로 별도의 일을 처리하는 두 개의 쓰레드를 사용한다. 따라서, 명령문을 읽는 업무는, 설사 명령문을 실행하는 속도가 느리다고 하더라도, 느려 지지 않는다. 예를 들면, 슬레이브 서버가 한동안 구동 되지 않았다면, 슬레이브 I/O쓰레드는, 비록 SQL쓰레드의 속도가 꽤 느리다고 하더라도, 슬레이브가 구동될 때 마스터로부터 재빠르게 모든 바이너리 로그 내용을 읽어 온다. 만약에 SQL쓰레드가 읽어온 모든 명령문을 실행하기 전에 슬레이브 서버가 멈추게 된다면, I/O 쓰레드는 명령문 복사본을 슬레이브 릴레이 로그에 로컬로 안전하게 저장할 수 있고, 슬레이브가 다시 구동될 때 실행을 계속할 수 있는 최소한의 것들을 갖게 된다. 이를 통해 마스터는 더 이상 슬레이브가 자신의 업데이트를 읽도록 기다릴 필요가 없기 때문에 마스터 서버 자신의 바이너리 로그를 잠시 후에 깨끗이 지울 수 있게 된다.

SHOW PROCESSLIST 명령문은 리플리케이션에 관련하여 마스터와 슬레이브 서버에서 어떤 일이 있었는지를 보여 준다. 아래의 SHOW PROCESSLIST 명령문은 세 개의 쓰레드가 어떻게 보여지는지를 나타내고 있다.

마스터 서버의 경우, SHOW PROCESSLIST의 결과는 아래처럼 보인다:



mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost:32931
db: NULL
Command: Binlog Dump
Time: 94
State: Has sent all binlog to slave; waiting for binlog to
be updated
Info: NULL


여기에서, 쓰레드 2는 접속 슬레이브의 Binlog Dump 리플리케이션 쓰레드다. State 정보는 모든 업데이트 사항이 슬레이브에 전달 되었으며 마스터는 다른 업데이트가 발생하는 것을 대기하고 있다는 것을 알려준다. 마스터 서버에서 Binlog Dump 쓰레드를 볼 수 없다면, 그것은 리플리케이션이 구동 되지 않고 있음을 의미하는 것이다 - 즉, 현재 어떠한 슬레이브로 연결되어 있지 않다.

슬레이브 서버의 경우, SHOW PROCESSLIST 실행 결과는 다음과 같다:



mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 10
User: jake
Host:
db: NULL
Command: Connect
Time: 11
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 11
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Has read all relay log; waiting for the slave I/O
thread to update it
Info: NULL


위에서는 쓰레드 10이 마스터 서버와 통신을 하는 I/O 쓰레드이고, 쓰레드 11은 릴레이 로그에 저장되어 있는 업데이트 사항을 실행하는 SQL 쓰레드라는 것을 알려 준다. SHOW PROCESSLIST 가 실행 되었을 때에는 양쪽 쓰레드 모두 아이들 (idle) 상태였으며, 또 다른 업데이트를 기다리고 있는 중이었다.

Time 컬럼에 있는 값은 슬레이브가 마스터와 비교해서 얼마나 늦는지를 알려주는 것이다.


리플리케이션 마스터 쓰레드 상태

아래의 리스트는 마스터 서버의 Binlog Dump 쓰레드에 대해 State 컬럼에서 가장 흔히 볼 수 있는 것들이다. 마스터 서버에서 Binlog Dump 쓰레드를 볼 수 없다면, 리플리케이션이 구동 되지 않은 것이다- 즉, 어떠한 슬레이브 서버도 연결이 되어 있지 않다는 것이다.


  • Sending binlog event to slave
    바이너리 로그는 이벤트 (events)로 구성이 되며, 일반적으로 하나의 이벤트는 여러 개의 정보를 가지고 있는 하나의 업데이트 항목이 된다. 쓰레드는 바이너리 로그에서 이벤트를 읽었으며 이제 이것을 슬레이브에 전달한다.
  • Finished reading one binlog; switching to next binlog
    쓰레드는 바이너리 로그를 읽는 것을 마쳤으며, 슬레이브에 보낼 바로 다음 이벤트를 열고 있다.
  • Has sent all binlog to slave; waiting for binlog to be updated
    쓰레드는 모든 업데이트 항목을 바이너리 로그에서 읽었으며 그것들을 슬레이브에 전달했다. 쓰레드는 현재 아이들 (idle)상태이며, 마스터에서 새로운 업데이트가 발생해서 바이너리 로그에 새로운 이벤트가 나타나기를 기다리고 있는 상태이다.
  • Waiting to finalize termination
    쓰레드가 종료했을 때 매우 짧게 나타나는 상태
‘리플리케이션 슬레이브 I/O 쓰레드 상태

아래의 리스트는 슬레이브 서버의 I/O 쓰레드에 대해 State 컬럼에서 볼 수 있는 가장 일반적인 상태를 설명하는 것이다. 이 상태는 SHOW SLAVE STATUS를 통해서 볼 수 있는 Slave_IO_State 컬럼에서도 나타날 수 있다. 따라서 이 명령문을 사용하면, 여러분은 어떤 일이 일어났는지에 대해서 유익한 정보를 얻을 수가 있다.


  • Connecting to master
    쓰레드는 마스터에 접속을 시도하고 있다.
  • Checking master version
    마스터에 접속이 된 후에 매우 짧게 나타나는 상태.
  • Registering slave on master
    마스터에 접속이 된 후에 매우 짧게 나타나는 상태.
  • Requesting binlog dump
    마스터에 접속이 된 후에 매우 짧게 나타나는 상태. 쓰레드는 바이너리 로그 파일 이름과 위치를 가지고, 바이너리 로그 내용에 대한 요청을 마스터에 보낸다.
  • Waiting to reconnect after a failed binlog dump request
    바이너리 로그 덤프가 실패할 경우 (접속 불가로 인해), 쓰레드는 곧장 이 상태가 되며, 그 다음에는 주기적으로 재 접속을 시도하게 된다. 재시도 간격은 --master-connect-retry 옵션을 가지고 지정할 수가 있다.
  • Reconnecting after a failed binlog dump request
    쓰레드는 마스터에 재 접속을 시도한다.
  • Waiting for master to send event
    쓰레드는 마스터에 접속이 되었고 바이너리 로그 이벤트가 도착 하기를 기다리고 있다. 마스터가ave_read_timeout 시간 동안 대기를 하게 되면, 시간 초과 (timeout)가 발생한다. 이렇게 되면, 쓰레드는 마스터와의 연결이 단절되었다고 생각을 하고 재 접속을 시도한다.
  • Queueing master event to the relay log
    쓰레드는 이벤트를 읽었고 이것을 릴레이 로그에 복사를 해서 SQL 쓰레드가 이 이벤트를 처리하게끔 한다.
  • Waiting to reconnect after a failed master event read
    이벤트를 읽는 도중에 에러 (접속 단절로 인해)가 발생했음. 쓰레드는 재 접속을 시도하기 전에 master-connect-retry 시간 동안 대기 (sleeping)를 한다.
  • Reconnecting after a failed master event read
    쓰레드는 마스터에 재 접속을 시도한다. 접속이 다시 이루어지면, 상태는 Waiting for master to send event 가 된다.
  • Waiting for the slave SQL thread to free enough relay log space
    여러분은 0 (zero)이 아닌 relay_log_space_limit 값을 사용하는 중이며, 릴레이 로그의 크기는 이 값을 초과할 만큼 충분이 커져 있다. I/O 쓰레드는 SQL 쓰레드가 릴레이 로그 파일 중에 일부를 삭제해서 충분한 공간을 확보하지 않으면 계속 대기를 한다.
  • Waiting for slave mutex on exit
    쓰레드가 멈추었을 때 매우 짧게 발생하는 상태.
리플리케이션 슬레이브 SQL 쓰레드 상태

아래의 리스트는 State 컬럼에서 가장 일반적으로 볼 수 있는 슬레이브 서버 SQL 쓰레드 상태를 나타낸 것이다:


  • Reading event from the relay log
    쓰레드는 릴레이 로그에서 이벤트를 하나 읽었으며 이것을 처리할 수가 있다.
  • Has read all relay log; waiting for the slave I/O thread to update it
    쓰레드는 릴레이 로그 파일에 있는 모든 이벤트를 처리하였고, I/O쓰레드가 새로운 이벤트를 릴레이 로그에 작성하기를 기다리고 있다.
  • Waiting for slave mutex on exit
    쓰레드가 멈추었을 때 매우 짧게 나타나는 상태.

I/O 쓰레드용 State 컬럼은 명령문 문장도 함께 보여 준다. 이것은 쓰레드가 릴레이 로그로부터 하나의 이벤트를 읽었으며, 거기에서 명령문을 추출했고, 추출한 명령문을 실행했다는 것을 가리킨다.


리플리케이션 릴레이 및 상태 파일

릴레이 로그 파일 이름은 host_name-relay-bin.nnnnnn 형식을 디폴트로 가지며, 여기에서 host_name 는 슬레이브 서버 이름이 되고, nnnnnn 은 시퀀스 번호가 된다. 000001으로 시작하는 연속적인 시퀀스 번호를 사용해서 연속적인 릴레이 로그 파일들이 생성된다. 슬레이브는 현재 사용 중에 있는 릴레이 로그 파일을 추적하기 위해 하나의 인덱스를 사용한다. 디폴트 릴레이 로그 인덱스 파일 이름은 host_name-relay-bin.index이다. 디폴트로는, 슬레이브 서버는 자신의 데이터 디렉토리에 릴레이 파일을 생성한다. 디폴트 파일 이름은 --relay-log 와 --relay-log-index 서버 옵션을 가지고 덮어 쓸 수가 있다.

릴레이 로그는 바이너리 로그와 동일한 포맷을 사용해서 mysqlbinlog를 사용해서 읽을 수가 있다. SQL 쓰레드는 릴레이 로그 파일 안에 있는 모든 이벤트들이 처리가 되고 더 이상 그 파일이 필요가 없게 되면 자동으로 즉시 각 릴레이 로그 파일을 삭제한다. SQL 쓰레드는 이러한 삭제 동작을 매우 조심스럽게 진행하기 때문에 릴레이 로그 파일을 삭제하는 데에는 명백한 메커니즘이 존재하지 않는다. 하지만, FLUSH LOGS 는 릴레이 로그를 로테이트 (rotate) 시키며, 이것은 SQL 쓰레드가 이 파일들을 삭제하는 시기에 영향을 미친다.

슬레이브 서버는 아래의 조건 아래에서 새로운 릴레이 로그 파일을 생성한다:


  • I/O 쓰레드가 매번 시작될 때.
  • 로그가 플러시 될 때; 예를 들면, FLUSH LOGS 또는 mysqladmin flush-logs가 실행될 때.
  • 현재 로그 파일의 크기가 너무 커질 때. “너무 크다 (too large)” 의 의미는 아래와 같이 판단된다:
    • 만일 max_relay_log_size의 값이 0보다 크면, 그 값이 릴레이 로그 파일의 최대 크기가 된다.
    • 만일 max_relay_log_size의 값이 0이면, max_binlog_size가 릴레이 로그 파일의 최대 크기가 된다.

슬레이브 리플리케이션 서버는 데이터 디렉토리에 두 개의 작은 파일을 추가로 생성을 한다. 이 상태 파일들은 디폴트로 master.info 및 relay-log.info라는 이름이 붙게 된다. 이것들의 이름은 --master-info-file 과 --relay-log-info-file 옵션으로 바꿀 수가 있다.

두 상태 파일들은 Section 13.6.2, “슬레이브 서버를 제어하기 위한 SQL 명령문”에서 설명을 하는 SHOW SLAVE STATUS 명령문 결과에서 볼 수 있는 정보를 가지고 있다. 상태 파일들은 디스크에 저장이 되기 때문에, 슬레이브 서버가 셧 다운 되더라도 계속 존재를 하게 된다. 슬레이브가 시작되는 다음 시점에, 슬레이브 서버는 마스터에서 바이너리 로그를 어디까지 읽었는지 그리고 자신의 릴레이 로그가 어디까지 진행 되었는지를 알아보기 위해 이 파일들을 읽게 된다.

I/O 쓰레드는 master.info 파일을 업데이트한다. 아래의 테이블은 SHOW SLAVE STATUS가 출력하는 컬럼과 파일의 라인이 어떤 상관 관계를 가지고 있는지 설명하는 것이다.



Line Description
1 Number of lines in the file
2 Master_Log_File
3 Read_Master_Log_Pos
4 Master_Host
5 Master_User
6 Password (not shown by SHOW SLAVE STATUS)
7 Master_Port
8 Connect_Retry
9 Master_SSL_Allowed
10 Master_SSL_CA_File
11 Master_SSL_CA_Path
12 Master_SSL_Cert
13 Master_SSL_Cipher
14 Master_SSL_Key

SQL 쓰레드는 relay-log.info 파일을 업데이트한다. 아래의 테이블은 SHOW SLAVE STATUS가 출력하는 컬럼과 파일의 라인이 어떤 상관 관계를 가지고 있는지 설명하는 것이다.



Line Description
1 Relay_Log_File
2 Relay_Log_Pos
3 Relay_Master_Log_File
4 Exec_Master_Log_Pos

여러분이 슬레이브의 데이터를 백업할 때에는, 릴레이 로그 파일과 더불어 이 두 파일들도 함께 백업을 받도록 해야 한다. 이 파일들은 슬레이브 데이터를 다시 읽어온 후에 리플리케이션을 재 구동 시키기 위해 필요한 것 들이다. 만일 릴레이 로그는 잃어버렸지만 relay-log.info 파일은 여전히 가지고 있다면, 이것을 가지고 SQL 쓰레드가 마스터 바이너리 로그에서 얼마나 진행이 되었는지를 알아볼 수가 있다. 그런 다음에 MASTER_LOG_FILE 및 MASTER_LOG_POS 옵션과 함께 CHANGE MASTER TO를 사용하면 슬레이브로 하여금 그 시점에서 바이너리 로그를 다시 읽어 오도록 할 수가 있다. 물론, 이것은 바이너리 로그가 여전히 마스터 서버에 있어야 한다는 것을 전제로 한다.

만일 슬레이브가 LOAD DATA INFILE 명령문을 리플리케이션 하는 것과 관련이 있다면, 슬레이브가 이러한 목적으로 사용하는 디렉토리의 모든 SQL_LOAD-* 파일들도 함께 백업을 해 두어야 한다. 슬레이브는 이 파일들을 가지고 인터럽트를 당한 LOAD DATA INFILE의 리플리케이션을 다시 진행한다. 디렉토리의 위치는 --slave-load-tmpdir 옵션을 사용해서 지정할 수가 있다. 만일 이 옵션을 지정하지 않으면, 디렉토리 위치는 tmpdir 시스템 변수 값이 된다.

출처 : MySQL 코리아