VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
복제본의 용도
- 읽기 확장. 대시보드, 검색, 내보내기, API 읽기가 소스에서 빠져나가, 소스의 용량이 쓰기를 위해 남습니다.
- 비싼 쿼리의 격리. 분석가의 40초짜리 집계가 복제본에서 실행되어 아무도 막지 않습니다.
- 웜 스탠바이(warm standby). 최신 상태의 복제본은 소스가 실패할 때 승격할 수 있습니다.
읽기 라우팅
MySQL은 쿼리를 대신 라우팅해 주지 않습니다. 스택의 무언가가 쓰기를 소스로, 선택한 읽기를 복제본으로 보내야 합니다:- 애플리케이션 수준 라우팅. 대부분의 프레임워크가 직접 지원합니다(Django 데이터베이스 라우터, Rails
connects_to/roles, Laravel 읽기/쓰기 연결). 단순하고 명시적이며, 애플리케이션이 쿼리마다 결정합니다. - 프록시. ProxySQL과 비슷한 도구들은 문장 유형이나 규칙에 따라 라우팅하므로, 애플리케이션은 연결 문자열 하나를 유지합니다. 장애 조치도 한곳에 모읍니다.
복제 지연: 진짜 어려운 부분
복제는 기본적으로 비동기입니다. 소스의 커밋은 복제본이 변경을 적용하기 전에 반환되므로, 잠시 뒤의 복제본 읽기는 이미 성공한 쓰기를 놓칠 수 있습니다. 복제본에서 지연을 측정하세요:Seconds_Behind_Source 필드가 표준 신호입니다. 보통은 0에 가깝고, 쓰기 폭주, 큰 트랜잭션, 스키마 변경 아래에서 치솟습니다. 이 값에 경보를 걸고, 읽기 경로별로 허용 범위를 알아 두세요.
전형적인 실패는 **자신의 쓰기 읽기(read-your-own-writes)**입니다: 사용자가 프로필을 저장하고(소스에 쓰기), 다음 페이지가 복제본에서 그것을 불러오는데, 복제본이 아직 그 쓰기를 적용하지 않은 경우입니다. 사용자는 자신의 변경이 사라지는 것을 봅니다. 표준 완화책을 가장 싼 것부터 나열하면:
- 쓰기 후 고정. 세션이 쓰기를 한 뒤, 다음 몇 초 동안 그 세션의 읽기를 소스로 라우팅합니다. 많은 프레임워크와 프록시가 이 패턴을 직접 지원합니다.
- 허용 범위에 따라 라우팅. 금액 잔액과 방금 편집한 페이지는 소스에서 읽고, 탐색 페이지, 검색, 분석은 복제본에서 읽습니다.
- GTID를 통한 세션 일관성. 쓰기 후 트랜잭션 식별자를 잡아두고, 복제본 읽기가
WAIT_FOR_EXECUTED_GTID_SET()으로 그것을 기다리게 합니다. 정확하지만, GTID를 요청에 실어 나르는 배관 작업이 필요합니다.
두 가지 실용적인 규칙
- 복제본은 남는 하드웨어가 아니라 소스 이상의 사양을 갖춘 하드웨어여야 합니다. 소스보다 느린 복제본은, 바로 복제본을 추가하게 만든 그 부하 아래에서 뒤처집니다.
- 승격을 연습하세요. 한 번도 승격해 본 적 없는 복제본은 한 번도 복원해 본 적 없는 백업입니다. 필요해지기 전에 장애 조치 경로를 연습하세요.