InnoDB 클러스터에 대해 알아보자
InnoDB 클러스터
: MySQL의 고가용성(HA)
실현을 위해 만들어진 여러 구성 요소들의 집합체
구성 요소
그룹 복제(Group Replication)
: 소스 서버의 데이터를 레플리카 서버로 동기화
하는 복제 역할, MySQL 서버에 대한 자동화된 멤버십 관리
역할MySQL 라우터(MySQL Router)
: 애플리케이션 서버
와 MySQL 서버
사이에 동작하는 미들웨어
로, 애플리케이션
이 실행한 쿼리
를 적절한 MySQL 서버
로 전달하는 프락시(Proxy)
역할MySQL 셸(MySQL Shell)
: 새로운 클라이언트 프로그램
으로, SQL문 실행뿐만 아니라 자바스크립트
및 파이썬
기반의 스크립트
작성 기능, 어드민 작업
을 할 수 있게 해주는 API
제공InnoDB 클러스터
에서 데이터가 저장되는 MySQL 서버들은 그룹 복제 형태
로 복제
구성
=> 각 서버
는 읽기/쓰기
가 모두 가능한 프라이머리
또는 읽기
만 가능한 세컨더리
중 하나의 역할
=> 프라이머리
- 기존 복제에서 소스 서버
=> 세컨더리
- 레플리카 서버
서버를 최소 3대 이상
으로 구성
클라이언트
는 MySQL 서버
로 직접 접근X
, MySQL 라우터
에 연결해서 쿼리 실행
=> MySQL 라우터
는 MySQL 서버
에 대한 메타데이터
정보를 지니며, 이를 바탕으로 클라이언트
로부터 실행된 쿼리를 적절한 MySQL 서버
로 전달
MySQL 셸
: 사용자가 InnoDB 클러스터
를 생성
및 관리
할 수 있도록 API 제공
, InnoDB 클러스터의 상태 확인
또는 MySQL 서버의 설정 변경
기능 제공
=> InnoDB 클러스터
관련 작업 진행시 MySQL 서버
에 직접 연결
해서 작업해야 함
MySQL 서버에 장애
발생시, 그룹 복제
가 감지
해서 자동
으로 해당 서버 복제 그룹 제외
, MySQL 라우터
는 클라이언트
로부터 실행된 쿼리가 정상 작동 서버
로만 전달될 수 있도록 함
그룹 복제
: 복제 프레임워크
를 기반으로 구현, Row 포맷
의 바이너리 로그
, 릴레이 로그
, GTID
사용
=> 기존 복제
와 달리 복제
에 참여하는 MySQL 서버
들이 하나의 복제 그룹
으로 묶인 클러스터
형태를 가지며, 그룹 내 서버
들은 서로 통신
하면서 양방향 복제 처리
=> 그룹 멤버
: 그룹 복제
에 참여하는 서버
들
소스 서버
에서의 트랜잭션 커밋 처리
가 레플리카 서버
와는 무관
소스 서버
에서 트랜잭션 커밋 처리
중 레플리카 서버
로 트랜잭션이 잘 전달됐는지 응답
을 기다린 후 최종적으로 커밋 처리
그룹 내 다른 멤버
들의 응답
을 확인하는 단계 존재
=> 트랜잭션
커밋할 준비 되면, 다른 멤버
들에게 전송 후 과반수 이상
응답 받으면 해당 트랜잭션
을 인증
하고 최종적으로 커밋
=> 과반수 이상 응답 못받으면 해당 트랜잭션 적용X
그룹 복제
에 참여하는 MySQL 서버들은 group_replication_applier
라는 복제 채널
을 생성하며, 해당 채널을 통해 트랜잭션
전달받아 처리
최상위 계층
: 그룹 복제 플러그인
이 MySQL 서버와 상호작용하기 위해 구현된 플러그인 API 집합
=> API
를 통해 그룹 복제 플러그인
혹은 반대
방향으로 요청 전달
=> MySQL 서버의 시작
또는 복구
, 트랜잭션 커밋
등의 이벤트를 그룹 복제 플러그인
에 전달하고 그룹 복제 플러그인
에서는 처리 중인 트랜잭션에 대한 커밋
또는 중단
, 릴레이 로그 기록 요청
등을 서버에 전달
복제 플러그인 계층
: 그룹 복제
의 기능들이 실질적으로 구현
=> 로컬
및 그룹 복제
의 다른 MySQL 서버에서 실행된 원격 트랜잭션
들이 처리
=> 트랜잭션
들에 대한 충돌 감지
및 그룹 내 전파
등이 수행
=> 그룹 복제
의 분산 복구 작업
그룹 통신 시스템 API
와 그룹 통신 엔진
: 상위 플러그인 계층
에서 그룹 통신 시스템 API
를 통해 그룹 통신 엔진
과 상호작용
=> 그룹 통신 엔진
: 그룹 복제
에 참여 중인 다른 MySQL 서버들과의 통신 처리
담당
=> 그룹 통신 엔진
은 트랜잭션
이 그룹 복제 멤버
들에 동일한 순서
로 전달되도록 보장, 토폴로지 변경
과 그룹 멤버
의 장애
등 감지
쓰기
를 처리할 수 있는 프라이머리 서버 수
에 따라 싱글 프라이머리 모드
와 멀티 프라이머리 모드
로 나뉨
쓰기
를 처리할 수 있는 프라이머리 서버
가 한 대
만 존재
=> 그룹 복제 구축
을 진행한 서버가 프라이머리
로 지정됨
싱글 프라이머리 모드
동작 중 그룹 내 프라이머리 서버
가 변경될 경우
자발적
혹은 예기치않게
현재 프라이머리 서버
가 그룹 탈퇴
하는 경우새로운 프라이머리
로 그룹의 특정 멤버
지정한 경우그룹 복제
가 새로운 프라이머리
선출하는 우선순위
1. MySQL 서버 버전
: 가장 낮은 버전
2. 각 멤버의 가중치 값
: 가중치 값 비교
3. UUID 값의 사전식 순서
: 가장 낮은 값
그룹 멤버
들이 전부 프라이머리로 동작
하는 형태
현재 어떤 서버
들이 그룹
에 참여하고 있는지 목록
과 상태
관리
그룹 복제
에서 트랜잭션
은 합의(Consensus)
와 인증(Certification)
단계를 거친 후 최종적
으로 그룹의 각 서버들에 적용
합의
: 일관된 트랜잭션 적용
을 위해 그룹 멤버
들에게 트랜잭션 적용
을 제안
하고 승낙
받는 과정
=> 클라이언트
가 한 그룹 멤버에서 트랜잭션 실행 후 커밋 요청
보내면, 해당 그룹 멤버는 그룹 통신 엔진
을 통해 트랜잭션에서 변경한 데이터에 대한 WriteSet
과 커밋
될 당시의 gtid_executed 스냅샷 정보
, 트랜잭션의 이벤트 로그 데이터
등이 포함된 데이터
를 다른 멤버
로 전파
다수의 그룹 멤버
들에서 실행된 트랜잭션들은 합의 단계
를 거친 후 정렬되어, 각 멤버
들에서 모두 동일한 순서
로 인증
단계 거침
=> 트랜잭션 충돌 여부
확인
group_replication_consistency
변수를 통해 그룹 복제
에서의 트랜잭션 일관성 수준
설정 가능
최종적
으로는 멤버들이 일관된
데이터를 가지게 됨
=> 오래된 데이터
를 읽을 수 있음
=> 트랜잭션
과 충돌시 롤백
가능성 존재
싱글 프라이머리 모드
로 설정된 그룹 복제에서 프라이머리 페일오버
발생해 신규 프라이머리 선출
시 트랜잭션
에 영향
=> 이전 프라이머리
의 트랜잭션
이 모두 적용될 때까지 대기
=> 신규 프라이머리
로 유입된 읽기 전용
및 읽기-쓰기 트랜잭션
들은 오래된 데이터
가 아닌 최신 데이터
바탕으로 동작
=> 적용 대기 중
인 이전 프라이머리 트랜잭션
과 충돌
로 롤백X
모든 선행 트랜잭션
이 완료될 때까지 대기
후 처리
트랜잭션
적용 시 해당 시점
에 그룹 멤버
들이 모두 동기화된 데이터
를 갖게 함
=> 읽기-쓰기 트랜잭션
은 다른 모든 멤버
들에서도 해당 트랜잭션이 커밋될 준비
가 됐을 때까지 대기
후 처리
읽기-쓰기 트랜잭션
은 모든 선행 트랜잭션
이 적용될 때까지 대기 후 실행, 다른 모든 멤버
들에서도 커밋 준비
되어 응답
시 최종적 커밋
읽기 트랜잭션
은 모든 선행 트랜잭션
적용 대기 후 실행
지연된 멤버
에서 트랜잭션
실행 시, 오래된 데이터
를 읽을 수 있으므로 해결해야 함
=> 흐름 제어
: 그룹 멤버
들의 쓰기 처리량
을 조절
하는 메커니즘
문제 상태
에 있는 멤버를 식별하고 해당 멤버를 그룹 복제
에서 제외
시킴으로써 그룹이 정상적
으로 동작 중인 멤버로만 구성될 수 있게 함
분산 복구
: 멤버가 그룹 가입 시
다른 그룹 멤버
들과 동일한 최신 데이터를 가질 수 있도록 가입 멤버
에서 누락된 트랜잭션들을 다른 그룹 멤버
에서 가져와 적용하는 복구 프로세스
기증자(Donor)
: 가입 멤버
가 복구 작업
을 위해 선택한 기존 그룹 멤버
바이너리 로그 복제 방식
: 가입 멤버에 적용되지 않은 트랜잭션들을 복제
해서 가져와 가입 멤버에 적용원격 클론 방식
: 모든 데이터
와 메타데이터
를 일관된 스냅샷
으로 가져와 가입 멤버
재구축로컬 복구
: 가입 멤버
가 이전에 그룹에 가입한 적이 있는 경우
, 릴레이 로그에 미쳐 적용하지 못한 트랜잭션 먼저 적용 후 복구 작업 진행글로벌 복구
: 기증자 멤버
를 선택해 데이터
또는 누락된 트랜잭션
을 가져와 적용, 현재 처리되는 트랜잭션
들은 내부적으로 캐싱
캐시 트랜잭션 적용
: 캐싱
해서 보관하던 트랜잭션들을 적용해 최종적으로 그룹에 참여분산 복구
도중 문제 발생
시 자동
으로 새로운 그룹 멤버
로 연결 전환
기증자
로 선택한 멤버로의 연결
이 정상적으로 이뤄지지 않은 경우바이너리 로그 복제 방식
으로 복구 작업 진행 중 레플리케이션 I/O 스레드
또는 SQL 스레드
에서 에러 발생한 경우원격 클론 작업
이 실패
하거나 중단
된 경우복구 작업
동안 기증자 멤버
에서 그룹 복제
가 중단
된 경우InnoDB
스토리지 엔진 사용프라이머리 키
사용네트워크 통신
환경바이너리 로그
활성화ROW
형태의 바이너리 로그 포맷 사용체크섬
설정log_slave_updates
활성화GTID
사용server_id
값 사용메타데이터 저장소
설정WriteSet
설정테이블스페이스 암호화
설정lower_case_table_names
설정멀티 스레드 복제
설정트랜잭션 격리 수준
을 READ-COMMITED
로 사용하는 것이 좋음테이블 락
및 네임드 락
고려 X멀티 프라이머리 모드
는 serializable
격리 수준 사용 X동일한 테이블
에 대해 서로 다른 멤버
에서 동시에 실행되는 DDL
및 DML
지원XCASCADE
제약 조건 사용된 테이블 지원XMySQL 셸
: MySQL을 위한 고급 클라이언트 툴
=> 기본적으로 자바스크립트 모드
로 동작
\py #파이썬 모드로 전환
\sql #sql모드로 전환
\js #자바스크립트 모드로 전환
API 제공
X DevAPI
: 관계형 데이터
와 문서 기반 데이터
모두 처리AdminAPI
: InnoDB 클러스터
관련 설정MySQL 라우터
: InnoDB 클러스터
에서 애플리케이션 서버
로부터 유입된 쿼리 요청
을 클러스터 내 적절한 MySQL 서버
로 전달하고 MySQL 서버
에서 반환된 쿼리 결과를 다시 애플리케이션 서버
로 전달하는 프락시
역할
MySQL 구성 변경
자동 감지최소한
의 버전 요구Performance 스키마
활성화파이썬
설치#MySQL 셸 접속
$mysqlsh
//dba.configureInstance() : 인자 서버에 접속해 InnoDB 클러스터 요구사항 충족하는지 확인
$dba.configureInstance("root@localhost:3306")
MySQL 서버
중 한 대
에 접속
\connect ~~@~~~
//dba.createCluster() : 클러스터 생성
var cluster=dba.createCluster("testCluster")
//멀티로 생성하고 싶을 경우
var cluster=dba.createCluster("testCluster",{multiPrimary:true})
//상태 조회
var cluster=dba.getCluster()
cluster.status()
<cluster>.addInstance()
메서드를 통해 서버
추가
//현재 클러스터에 존재하는 MySQL 서버 중 한 대에 접속
var cluster=dba.getCluster()
cluster.addInstance("~~~@~~~")
별도의 라우터용 서버
가 존재한 경우, InnoDB 클러스터
에서 사용할 라우터 서버
구성을 위해 라우터용 서버
에서 아래 명령 실행
#라우터 부트스트랩
mysqlrouter --bootstrap 계정명@주소:3306 --name icrouter1 \
--directory /tmp/myrouter --account icrouter --user root
#라우터 실행
/tmp/myrouter/start.sh
//클러스터 복제 토폴로지 구성 확인
cluster.describe()
//클러스터 전반적인 상태
//자세히 표시
cluster.status({'extended':1})
싱글 프라이머리 모드
와 멀티 프라이머리 모드
전환
cluster.switchToMultiPrimaryMode()
//멀티 프라이머리 모드로 전환
cluster.switchToSinglePrimaryMode([instance])
//싱글 프라이머리 모드로 전환
프라이머리 서버
를 강제로 특정 서버
로 변경
cluster.setPrimaryInstance(instance)
//인자 인스턴스를 새로운 프라이머리 서버로
클러스터
의 특정 인스턴스
제거
cluster.removeInstance(instance)
클러스터
의 사용 종료
혹은 클러스터 단위의 설정 변경
등으로 인한 경우
cluster.dissolve()
현재 동작 중인 클러스터 및 인스턴스 설정
을 온라인으로 변경
//클러스터 현재 설정 확인
cluster.options()
cluster.setOption(option,value)
//모든 인스턴스에 대해 설정 변경 또는 클러스터 단위 설정 변경
cluster.setInstanceOption(instance,option,value)
//클러스터 인스턴스별 설정 변경
cluster.setInstanceOption("ic-node1:3306","tag:location","Seoul")
사용자
가 임의
로 설정하는 태그의 키 값은 언더스코어(_)
로 시작X
=> 빌트인
태그가 _
로 시작
cluster.setInstanceOption("ic-node1:3306","tag:_hidden",true)
//태그 값이 true라면 MySQL 라우터에서 해당 인스턴스로 쿼리 요청 전달X
cluster.setInstanceOption("ic-node1:3306","tag:_disconnect_existing_sessions_when_hidden1",false)
//_hidden과 위 태그가 true면 MySQL 라우터는 해당 인스턴스와 연결된 커넥션 끊음
네트워크 통신
이 안정화되고, 서버
에 별다른 문제가 없다면 사용자는 인스턴스
에서 MySQL 그룹 복제
가 재시작
되게 해서 인스턴스
를 다시 클러스터
에 참여
cluster.rejoinInstance(instance)
//클러스터에 참여하는 데 필요한 설정 확인 및 재설정 후 그룹 복제 실행
정족수
, 즉 과반수 이상
의 인스턴스에 장애 발생시 쓰기 요청 처리 불가
cluster.forceQuorumUsingPartitionOf(instance)
//해당 인스턴스에서 정상적인 상태로 인식되는 클러스터 내 다른 인스턴스들 확인 후 그 인스턴스들로 클러스터 재구성
클러스터
안전하게 업그레이드
하는 순서
1. MySQL 라우터
업그레이드
2. MySQL 셸
및 InnoDB 클러스터 메타데이터 스키마
업그레이드
3. MySQL 인스턴스
업그레이드
dba.upgradeMetadata()
//메타데이터 스키마 버전 업그레이드
롤링 업그레이드(Rolling Upgrade)
: 세컨더리 서버
부터 순차적
으로 업그레이드해서 프라이머리 서버
를 가장 마지막
에 업그레이드
=> _hidden
태그 이용
그룹 복제
의 제약 사항 포함
--defaults-extra-file 옵션
을 사용해 추가적 옵션 파일 지정해 사용X별도 복제 채널
관리X샤딩
지원X라우터
는 하나의 클러스터
에 대해서만 설정 가능