Last Updated on 9월 21, 2023 by Jade(정현호)
안녕하세요
이번 포스팅에서는 MySQL에서 사용가능한 온라인 스키마 변경 유틸리티인 gh-ost 에 대해서 확인해보도록 하겠습니다.
Contents
GitHub's online DDL Tool
gh-ost는 MySQL을 위한 트리거리스(triggerless) 온라인 스키마 마이그레이션 솔루션입니다. 테스트 기능을 제공하고 일시 중지, 동적 제어/재구성, 감사 및 운영상의 여러 이점을 제공합니다.
gh-ost는 트리거리스이며 데이터 변경 이벤트에 대해서 바이너리 로그 스트림을 사용하며, 마이그레이션 기능을 제공하고 진행되는 동안 소스 인스턴스에서 가벼운 워크로드가 사용됩니다.
이와 같은 작업 유형은 기존 테이블과 소스 인스턴스에 대해서 워크로드를 분리하고 소스 인스턴스에 대해서 더 적은 리소스 사용에 대한 장점을 얻을 수 있고, 온라인 DDL 유틸리티의 새로운 패러다임을 제시하고 있습니다.
What's in a name
원래 이 툴의 이름은 Facebook online schema change 및 pt-online-schema-change과 같은 GitHub Online Schema Change : gh-osc으로 명명되었습니다.
그러나 어떤 이유로 c가 t로 변하게 되었고 gh-ost (발음: 고스트) 라는 새로운 약어를 찾게 되었습니다.
gh-ost (발음: 고스트)는 GitHub의 Online Schema Transmogrifier/Translator/Transformer/Transfigurator 를 의미 합니다.
[참고] pt-online-schema-change에 대한 내용은 다음 포스팅을 참고하시면 됩니다.
HOW
기존의 모든 온라인 스키마 변경 도구는 유사한 방식으로 작동합니다.
원본 테이블과 유사한 형태로 임시 테이블(고스트 테이블)을 만들고, 비어 있는 임시 테이블로 데이터를 마이그레이션하고, 원본 테이블에서 임시 테이블로 데이터를 천천히 점진적으로 복사하는 동시에 진행 중인 변경 사항(테이블에 적용된 모든 INSERT, DELETE, UPDATE)을 임시 테이블로 전파합니다.
마지막으로, 적절한 시기에 원본 테이블과 임시 테이블을 교체합니다.
gh-ost는 동일한 패턴을 사용하지만 트리거를 사용하지 않음으로써 기존의 모든 도구와 차별점이 있습니다.
트리거가 많은 제한과 위험의 원인이라는 것을 인식했습니다.
gh-ost는 바이너리 로그 스트림을 사용하여 테이블 변경 사항을 캡처하고 이를 비동기적으로 고스트 테이블(임시 테이블)에 적용합니다.
결과적으로 gh-ost는 마이그레이션 프로세스에 대한 더 큰 제어권을 갖게 되고, 실제로 중단할 수 있으며, 소스 인스턴스의 워크로드에서 마이그레이션의 쓰기 로드를 분리할 수 있습니다.
그래서 조금 더 부하를 줄일 수 있고, 신뢰할 수 있고 안전하게 사용할 수 있는 운영상 많은 이점을 제공합니다.
동작 방식 요약
[gh-ost]
- 마이그레이션 될 서버에 ghost 테이블(임시 테이블)을 생성
- ghost 테이블에 alter 구문 실행
- MySQL의 리플리카 인스턴스로 연결, 바이너리 로그 이벤트 스트리밍
- 교대로(interchangeably) 수행
- 원본 테이블에서 고스트 테이블로 행 복사
- 고스트 테이블의 이벤트 적용
- cut-over(테이블 교체)
필요 및 제약사항
필요사항
•gh-ost는 MySQL 5.7 버전 이상을 지원합니다.
•복제 환경일 경우 하나의 서버에서 RBR(ROW Based Replication , 행 기반 복제)형식으로 설정된 바이너리 로그의 제공이 필요 합니다. 즉, 가급적 바이너리 로그 포맷은 ROW Based 포맷이어야 합니다.
•row image 방식은 FULL 로 설정해야 합니다.(MINIMAL 향후 버전에서 지원 예정)
•복제(Replication) 환경일 경우, 테이블은 마스터와 복제본(Replica) 간에 동일한 스키마를 가져야 합니다.
•gh-ost 에서 사용되는 계정은 다음의 권한이 필요 합니다.
- ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATE on the database
or of course on *.* - SUPER, REPLICATION SLAVE on *.*,
or
REPLICATION CLIENT, REPLICATION SLAVE on *.*
•SUPER 권한은 stop salve, start slave 실행에 필요한 권한입니다.
- 해당 작업은 리플리카 인스턴스에서 binlog_format=row 가 아닐 경우 ROW 로 전환을 하는 과정에서 수행합니다.
- 만약 리플리카 인스턴스에서 이미 binlog_format=row 일 경우 --assume-rbr 옵션을 사용해서 stop slave, start slave 작업을 피할 수 있으므로 SUPER 권한은 필요하지 않습니다.
•gh-ost는 서버 기본값에 관계없이 모든 MySQL 연결에 대해 REPETABLE_READ 트랜잭션 격리 수준을 사용합니다.
제한사항
•Foreign key 제약조건은 지원하지 않습니다.(향후 어느 정도 지원될 수도 있습니다.)
•Triggers는 지원하지 않습니다.(향후에 지원될 수도 있습니다.)
•MySQL 5.7 JSON 컬럼은 지원되지만 기본 키의 일부로는 지원되지 않습니다
•전후 테이블(before & after tables) 두 개는 PRIMARY KEY 또는 다른 UNIQUE KEY를 공유해야 합니다. 이 키는 gh-ost에서 복사할 때 테이블 행을 반복하는 데 사용됩니다.
•마이그레이션 키에는 NULL 값이 있는 열이 포함되지 않아야 합니다. 이는 다음 중 하나를 의미합니다.
- 컬럼이 NULL이 아닙니다.
- 컬럼은 null을 허용하지만 NULL 값을 포함하지 않습니다.
•기본적으로 gh-ost는 유일한 UNIQUE KEY에 null 허용 열이 포함된 경우 실행되지 않습니다.
- --allow-nullable-unique-key 옵션을 사용해서 이를 재정의할 수 있지만 해당 열에 실제 NULL 값이 없는지 확인해야 합니다.
- 기존 NULL 값은 마이그레이션된 테이블에서 데이터 무결성을 보장할 수 없습니다.
•이름이 같고 대소문자가 다른 테이블이 있을 경우 마이그레이션할 수 없습니다.
- 예를 들어 동일한 스키마(데이터베이스) 내에 MYTable이라는 테이블이 있는 경우 MyTable을 마이그레이션할 수 없습니다.
•Amazon RDS에서 사용할 수 있지만 몇 가지 제약사항은 있습니다.
•Google Cloud SQL에서 사용 가능하며 --gcp flag 가 필요 합니다.
•Aliyun RDS에서 사용 가능하며 --aliyun-rds flag 가 필요 합니다.
•Azure Database for MySQL에서 사용 가능하며 --azure flag 가 필요 합니다. 추가 내용은 다음 문서를 참고하세요
•복제 환경의 복제본(Replica)를 통해서 진행할 때 Multi Source는 지원하지 않습니다. 소스 인스턴스에 직접 연결할 때(--allow-on-master 사용)는 동작 합니다.(다만 테스트는 안된 상태)
•Master-Master 구성 환경에서는 Active-Passive 설정에서만 지원됩니다. Active-Active(두 마스터(소스) 모두에서 동시에 테이블이 작성되는 경우)는 지원되지 않습니다.(나중에 지원될 수도 있습니다.)
•마이그레이션 키(일반적으로 PRIMARY KEY)의 일부가 enum 필드가 있는 경우 마이그레이션 성능이 저하되고 잠재적으로 나쁠 수 있습니다.
•FEDERATED Table은 마이그레이션을 지원하지 않습니다.
•Encrypted binary logs는 지원하지 않습니다.
•ALTER TABLE ... RENAME TO some_other_name 작업은 지원하지 않습니다. 해당 작업은 gh-ost 대신 직접 수행하는 형태로 하는 것이 더 효율적입니다.
테스트 환경 구성
gh-ost 설치
gh-ost 바이너리 설치 파일은 리눅스와 Mac OS/X 포맷으로 제공되고 있습니다
• 다운로드 링크(릴리즈 정보)
gh-ost는 Go 1.15 이상 버전으로 개발된 Go 언어 프로젝트입니다.
직접 빌드하려면 다음 중 하나를 사용합니다.
- script/build - this is the same build script used by CI hence the authoritative
- build.sh for building tar.gz artifacts in /tmp/gh-ost
• 포스팅 환경
- 포스팅에서는 빌드 된 바이너리 파일을 사용하였습니다.
- gh-ost 버전 1.1.5
- AWS RDS for MySQL 8.0.32 : 2 인스턴스(Source, Replica)
• 파일 다운로드
wget https://github.com/github/gh-ost/releases/download/v1.1.5/gh-ost-binary-linux-amd64-20220707162303.tar.gz
• 디렉토리 생성 및 압축헤제
mkdir -p /usr/local/gh-ost tar zxvf gh-ost-binary-linux-amd64-20220707162303.tar.gz \ -C /usr/local/gh-ost ## 필요에 따라서 소유권을 변경합니다.(필수는 아님) chown -R root:root /usr/local/gh-ost
• PATH 환경 변수 추가
~/.bash_profile 파일의 PATH 환경 변수에 /usr/local/gh-ost 를 추가합니다.
echo "export PATH=\$PATH:/usr/local/gh-ost" >> ~/.bash_profile
• 추가 필요한 패키지 설치
nc 바이너리 패키지를 설치합니다.
dnf -y install nmap-ncat or yum -y install nmap-ncat
DB 작업
샘플 테스트 데이터를 로딩 및 gh-ost에서 사용할 계정을 생성하도록 하겠습니다.
• 스키마 생성
create database sysbench;
• 데이터 로딩
샘플 데이터는 sysbench를 통해서 생성하도록 하겠습니다.
sysbench --mysql-host=xxxxxx.rds.amazonaws.com --mysql-port=3306 \ --mysql-user=xxxxx --mysql-password='xxxxx' \ --mysql-db=sysbench --table-size=25000000 \ --tables=1 /usr/local/sysbench/share/sysbench/oltp_read_only.lua prepare
위와 같이 생성할 경우 크기 약 5GB 테이블이 1개가 생성되게 됩니다.
• gh-ost용 유저 생성
root 유저나 다른 admin 권한을 가진 계정을 사용할 경우 다음의 계정 생성은 생략합니다.
create user ghost@'%' identified by 'Ghost123!@#'; grant ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATE on *.* to 'ghost'@'%'; -- 또는 특정 스키마 grant replication client, replication slave on *.* to 'ghost'@'%' ; flush privileges;
AWS RDS for MySQL에서 진행하는 관계로 super 는 제외하고 권한을 부여하였습니다.
Operation modes
gh-ost 설정, 구성 및 마이그레이션을 실행할 위치에 따라 다음과 같은 다양한 작동 모드가 있습니다.
a. Connect to replica, migrate on master
이 동작 모드는 gh-ost가 기본적으로 수행되는 모드입니다. gh-ost는 리플리카 인스턴스를 통해 변경 이벤트 내용 확인 및 스트림하고, 복제 토폴로지의 마스터 인스턴스를 찾고 연결하며 마이그레이션 등을 수행합니다.
해당 동작 모드는 리플리카 인스턴스에서 바이너리 로그를 읽어서 소스 인스턴스에 반영하는 동작입니다.
마이그레이션 진행 과정에서 다음을 수행합니다.
- 소스 인스턴스에서 데이터 읽기 및 쓰기
- 리플리카 인스턴스에서 바이너리 로그 이벤트를 읽고 변경 사항을 소스 인스턴스에 적용
- 테이블 형식, 컬럼 및 키 확인 및 조사, 리플리카 인스턴스에서 테이블 행 수 카운팅
- 리플리카 인스턴스에서 내부 변경 로그 이벤트(예: heartbeat) 읽기
- 소스 인스턴스에서 Cut-over 실행(switch tables)
만약 소스 인스턴스가 Statement Based Replication (SBR)로 동작할 경우 리플리카 인스턴스는 바이너리 로그(log_bin, log_slave_updates)가 활성화된 상태로 구성되어야 하며 binlog_format=ROW 여야 합니다.
리플리카 인스턴스에서 바이너리 로그 활성화 및 log_slave_updates 활성화, binlog_format=ROW 설정이 불가능하다면 해당 작동 모드는 사용이 불가능합니다.
그렇기 때문에 리드 리플리카 인스턴스에서 바이너리 로그 활성화가 불가능한 AWS Aurora MySQL의 경우에는 "a. Connect to replica, migrate on master" 작동 모드의 사용이 불가합니다.
RDS for MySQL 에서는 리플리카 인스턴스에서 바이너리 로그 활성화가 가능하기 때문에 "a. Connect to replica, migrate on master" 작동 모드 사용이 가능합니다.
포스팅에서는 소스 인스턴스와 리플리카 인스턴스 모두 binlog_format=ROW 으로 설정하여 사용 중입니다.
• 사용 명령어
gh-ost \ --max-load=Threads_running=25 \ --critical-load=Threads_running=1000 \ --chunk-size=1000 \ --throttle-control-replicas="read-inst.rds.amazonaws.com:3306" \ --max-lag-millis=1500 \ --assume-master-host="source-inst.rds.amazonaws.com:3306" \ --host="read-inst.rds.amazonaws.com" \ --port=3306 \ --database="sysbench" \ --table="sbtest1" \ --user="ghost" \ --password='xxxxx' \ --alter="modify column c varchar(120) not null DEFAULT ''" \ --cut-over=default \ --allow-on-master \ --exact-rowcount \ --concurrent-rowcount \ --default-retries=120 \ --panic-flag-file=/tmp/ghost.panic.flag \ --ok-to-drop-table \ --assume-rbr \ --verbose \ --execute
* 위의 명령어에서 사용한 주소 정보(Endpoint)는 임의 값으로 치환된 정보이고 실제 Endpoint 정보는 아닙니다.
• 커맨드 라인 flag(옵션) 설명
- max-load : 임계값을 초과하면 throttler가 작동하며 임계값으로 설정할 항목과 값을 지정합니다.
- critical-load : critical-load는 충족시 gh-ost가 panic(panic-flag-file 생성)을 일으키고 종료되는 임계값을 정의합니다. 기본 동작은 이 임계값을 충족하면 즉시 종료합니다.
- throttle-control-replicas : 입력된 리플리카 인스턴스 중 하나라도 --max-lag-millis를 초과하게 되면 스토틀링이 동작합니다.
- max-lag-millis : 단위 ms
- assume-master-host : 소스 인스턴스의 호스트 정보를 gh-ost에 명시적으로 알릴 수 있습니다. RDS for MySQL 에서 사용합니다.
- switch-to-rbr : gh-ost가 binlog_format=ROW 일 때만 동작하기 때문에 작업 실행 대상 서버의 binlog_format을 ROW로 변경하는 옵션입니다. 주로 리플리카 인스턴스의 binlog_format 변경과 log_slave_updates 옵션 설정 후 재기동을 수행합니다.
- allow-master-master : master-master 구성 시 하나의 마스터를 임의로 지정할 경우 사용합니다. (MMM 사용)
- allow-on-master : 소스 인스턴스에서 작업할 때 설정하는 옵션, 반대 성격의 옵션이 --migrate-on-replica 입니다.
- migrate-on-replica : 일반적으로 gh-ost는 소스 인스턴스 테이블을 마이그레이션하는데 사용됩니다. 리플리카 인스턴스에서 이러한 작업을 수행하려면 gh-ost를 해당 리플리카 인스턴스에 연결하고 --migrate-on-replica를 옵션을 추가합니다.
gh-ost는 소스 인스턴스에 잠시 연결되지만 소스 인스턴스를 변경하지 않습니다. 작은 복제 지연을 유지하면서 마이그레이션은 리플리카 인스턴스에서 완전히 실행됩니다. - verbose : gh-ost가 실행될 때 더 자세한 정보를 출력하도록 합니다.
- ok-to-drop-table : 완료된 다음 old 테이블을 삭제합니다.
- dml-batch-size : 바이너리 로그에서 변경 이벤트를 읽어서 고스트 테이블에 적용시 일괄 쓰기 단위를 설정합니다. (기본값 10)
- assume-rbr : 서버가 RBR(행 기반 복제, binlog_format=ROW)을 사용할 경우 "--assume-rbr"을 지정할 수 있습니다. 이것은 gh-ost가 "STOP SLAVE" 또는 "START SLAVE" 를 수행하는 확인 단계를 건너뜁니다. 이 단계를 건너뛴다는 것은 gh-ost가 작동하기 위해 SUPER 권한이 필요하지 않음을 의미합니다. Amazon RDS에서 이것을 사용해야 합니다.
- panic-flag-file : gh-ost가 실행되는 중에 중지(abort) 하기 위한 옵션으로 설정한 경로에 파일을 생성하면 실행중인 마이그레이션 작업이 중단됩니다. 마이그레이션 과정에서 생성된 고스트 테이블은 남아 있기 때문에 별도로 삭제나 flag을 사용해야하며, socket 파일도 남아 있으므로 삭제 해야합니다.(보통 /Time 아래에 존재함)
- postpone-cut-over-flag-file : cut-over(table switch)를 연기시키는 옵션으로 사용하게 되면 gh-ost 실행 시 설정한 경로에 파일이 생성되게 되며, 데이터마이그레션 및 변경 데이터에 대한 반영이 모두 완료되어 테이블 스위치(switch)를 할 수 있는 시기가 와도 cur-over를 하지 않고 계속 연기하게 됩니다. cut-over를 수행하기 위해서 경로의 파일을 삭제하면 cut-over가 진행됩니다.
- alter : 스키마를 변경할 DDL 구문을 입력합니다.
b. Connect to master
리플리카(Replica) 인스턴스가 없거나 사용하지 않으려는 경우 소스(Source) 인스턴스에서 직접 작업할 수 있습니다. gh-ost는 소스 인스턴스에서 직접 모든 작업을 수행하며 다음과 같은 조건이 요구됩니다.
- 소스 인스턴스는 RBR(Row Base Replication) 포맷의 바이너리 로그가 설정되어 있어야 합니다.(binlog_format=ROW)
- 실행 시 --allow-on-master 옵션을 반드시 사용해야 소스 인스턴스에 직접 수행할 수 있습니다.
• 사용 명령어
gh-ost \ --max-load=Threads_running=25 \ --critical-load=Threads_running=1000 \ --chunk-size=1000 \ --max-lag-millis=1500 \ --host="source-inst.rds.amazonaws.com" \ --port=3306 \ --database="sysbench" \ --password='xxxxxxx' \ --table="sbtest1" \ --user="ghost" \ --alter="modify column c varchar(120) not null DEFAULT ''" \ --cut-over=default \ --allow-on-master \ --exact-rowcount \ --concurrent-rowcount \ --default-retries=120 \ --panic-flag-file=/tmp/ghost.panic.flag \ --ok-to-drop-table \ --assume-rbr \ --verbose \ --execute
"a. Connect to replica, migrate on master" 다른 점은 --throttle-control-replicas 와 --assume-master-host 2개 옵션을 사용하지 않으며 --host 에서 지정하는 접속 대상이 리플리카 인스턴스가 아닌 소스 인스턴스라는 점입니다.
c. Migrate/test on replica
일반적으로 gh-ost는 소스 인스턴스의 테이블을 마이그레이션하는 데 사용되는데 이번 유형은 리플리카 인스턴스에서 전체 마이그레이션만 수행하는 유형입니다.
gh-ost는 잠시 소스 인스턴스에 연결하지만 이후 소스 인스턴스에서 아무것도 변경하지 않고 리플리카 인스턴스에서 모든 작업을 수행합니다. 작업 내내 gh-ost는 리플리카 인스턴스가 최신 상태가 되도록 약간의 복제 지연을 유지하면서 수행하게 됩니다.
- migrate-on-replica 옵션(flag)은 리플리카 인스턴스에서 직접 테이블을 마이그레이션 실행을 의미하고 복제가 실행되는 동안에도 컷오버 단계를 수행합니다.
- test-on-replica는 마이그레이션이 테스트 전용 옵션입니다. 컷오버가 발생하기 전에 복제를 중지됩니다. 테이블이 교체한 다음 다시 교체됩니다. 원래 테이블이 원래의 위치로 돌아갑니다.
두 테이블 모두 복제가 중지된 상태로 남으며 두 테이블을 체크하고 데이터를 비교할 수 있습니다.
• 사용 명령어
gh-ost \ --user="ghost" \ --password='xxxxxx' \ --host="read-inst.rds.amazonaws.com" \ --port=3306 \ --database="sysbench" \ --table="sbtest1" \ --chunk-size=1000 \ --alter="modify column c varchar(120) not null DEFAULT ''" \ --max-load=Threads_running=30 \ --cut-over=default \ --exact-rowcount \ --concurrent-rowcount \ --ok-to-drop-table \ --initially-drop-ghost-table \ --initially-drop-old-table \ --migrate-on-replica \ --assume-rbr \ --panic-flag-file=/tmp/gh-ost.panic.flag \ --verbose \ --execute
AWS RDS for MySQL에서 "c. Migrate/test on replica" 유형을 사용하려면 리플리카 인스턴스(복제 인스턴스)에서 바이너리 로그 활성화가 필요하고 RDS for MySQL 에서 바이너리 로그를 활성화하기 위해서는 백업을 활성화해야 합니다.
또한 리플리카 인스턴스에서 직접 테이블 생성 및 입력 작업을 수행하기 때문에 쓰기가 가능해야 합니다. 즉 read_only=off 이어야 가능 합니다.
포스팅에서는 리플리카 인스턴스에서 백업을 활성화하였으며, read_only=off 설정을 하였습니다.
Dynamic reconfiguration
Dynamic reconfiguration는 gh-ost에서 마이그레이션 실행 중에 동작을 변경하는 기능입니다.
유사 다른 유틸리티와 차이를 보이는 기능으로 실행 시 설정한 여러 설정을 동적으로 변경할 수 있습니다.
여기에서 필요한 실행 바이너리는 nc 로 gh-ost 설치시에 추가로 같이 설치하였습니다.
gh-ost는 유닉스 소켓 파일을 수신(listen)하고 있고 선택적으로 TCP를 통해서도 수신합니다.
gh-ost를 실행하면 기본값으로 /tmp 아래에 소켓 파일이 생성되게 됩니다.
ls -al /tmp | grep gh-ost gh-ost.sysbench.sbtest1.sock
가령 chunk-size=5000 으로 설정하여 gh-ost를 실행하였는데 chunk 단위가 너무 높다고 판단되어 줄이고자 할 경우 gh-ost 작업을 중지 후 다시 시작하지 않고 다음과 같이 interactive commands을 통해서 동적으로 변경할 수 있습니다.
echo "chunk-size=1000" | nc -U /tmp/gh-ost.sysbench.sbtest1.sock
마찬가지로 max-load 구성을 변경할 수도 있습니다.
echo "max-load=Threads_running=50,threads_connected=1000" | nc -U /tmp/gh-ost.sysbench.sbtest1.sock
이와 같이 socket 파일을 통해서 동적으로 설정을 변경할 수도 있고, interactive commands를 통해 다른 기능을 수행할 수 있습니다.
가령 gh-ost 실행 시 verbose 옵션을 사용하면 계속적으로 아래와 같은 정보를 확인할 수 있습니다.
# Migrating `sysbench`.`sbtest1`; Ghost table is `sysbench`.`_sbtest1_gho` # Migrating ip-x.x.x.x:3306; inspecting ip-x.x.x.x:3306; executing on ip-x.x.x.x # Migration started at Thu Aug 10 xx:xx:xx +0900 2023 # chunk-size: 1000; max-lag-millis: 1500ms; dml-batch-size: 10; max-load: Threads_running=30; critical-load: ; nice-ratio: 0.000000 # throttle-additional-flag-file: /tmp/gh-ost.throttle # throttle-control-replicas count: 1 # panic-flag-file: /tmp/gh-ost.panic.flag # Serving on unix socket: /tmp/gh-ost.sysbench.sbtest1.sock * 가로 길이에 따라서 개행 되어 있습니다.
그런데 verbose 옵션을 사용하지 않았을 경우 진행 상태나 설정 내용을 확인하고자 할 경우 status 를 통해서 설정된 정보와 진행 상태를 확인할 수 있습니다.
echo status | nc -U /tmp/gh-ost.sysbench.sbtest1.sock # Migrating `sysbench`.`sbtest1`; Ghost table is `sysbench`.`_sbtest1_gho` # Migrating ip-x.x.x.x:3306; inspecting ip-x.x.x.x:3306; executing on ip-x.x.x.x # Migration started at Fri Aug 10 xx:xx:xx +0900 2023 # chunk-size: 1000; max-lag-millis: 1500ms; dml-batch-size: 10; max-load: Threads_running=25; critical-load: Threads_running=1000; nice-ratio: 0.000000 # throttle-additional-flag-file: /tmp/gh-ost.throttle # throttle-control-replicas count: 1 # panic-flag-file: /tmp/ghost.panic.flag # Serving on unix socket: /tmp/gh-ost.sysbench.sbtest1.sock Copy: 164000/900000 18.2%; Applied: 0; Backlog: 0/1000; Time: 5s(total), 4s(copy); streamer: mysql-bin-changelog.001412:31248653; Lag: 0.08s, HeartbeatLag: 0.05s, State: migrating; ETA: 21s * 가로 길이에 따라서 개행 되어 있습니다.
물론 verbose을 사용하더라도 status 를 사용할 수 있습니다.
interactive commands를 통해서 현재 진행중인 gh-ost 를 강제종료(abort) 할 수 있으며 그 때 사용되는 명령어는 panic 입니다.
다음과 같이 명령어를 수행하면 실행 중인 gh-ost 는 종료됩니다.
echo panic | nc -U /tmp/gh-ost.sysbench.sbtest1.sock
명령어 실행 후 리턴 메세지와 진행중인 화면에서 출력되는 메세지는 다음과 같이 동일한 내용이 출력 됩니다.
Copy: 90000/900000 10.0%; Applied: 0; Backlog: 0/1000; Time: 3s(total).... [중략] 2023-08-10 x:x:x ERROR User commanded 'panic'. The migration will be aborted without cleanup. Please drop the gh-ost tables before trying again. * 가로 길이에 따라서 개행 되어 있습니다.
이와 같이 interactive commands 를 통해서 실행 중에 다양한 명령어 수행이 가능 합니다.
추가적인 interactive commands 내용은 다음 링크에서 확인하시면 됩니다.
리소스 사용 비교
gh-ost 나 pt-online-schema-change 와 같은 유틸리티는 빠르게 스키마의 변경을 실행이라는 부분 보다는 부하를 줄이면서(또는 적절히 조절하면서) 온라인으로 스키마 변경을 하는 관점이기 때문에 수행 시간 보다 실행 과정에서 사용한 리소스 정보를 확인해보도록 하겠습니다.
• 비교 대상
- a. Connect to replica, migrate on master
- b. Connect to master
- percona pt-online-schema-change
• 테스트 조건
- 3개 모두 chunk-size 1000 으로 수행
- 실행 중에 대상 테이블에 1.5초당 500건 데이터 입력
- 사용된 인스턴스 타입 : db.t3.large
소스(Source) 인스턴스에서 사용된 리소스 정보입니다.
CPU
• a. Connect to replica, migrate on master
• b. Connect to master
• percona pt-online-schema-change
CPU는 gh-ost를 사용한 a 유형과 b 유형에서 30~35% 정도를 사용하였고, pt-online-schema-change 에서는 40~48% 정도 사용하였습니다.
테스트에서 사용한 RDS Class 기준으로 약 15%정도 CPU 사용 차이로 테스트되었습니다.
리소스 사용 수치는 사용하는 시스템 스펙(또는 Class)와 대상 테이블의 사이즈, 수행 중 부하(dml throughput)에 따라서 달라집니다.
WriteOPS
• a. Connect to replica, migrate on master
• b. Connect to master
• percona pt-online-schema-change
ReadOPS
• a. Connect to replica, migrate on master
• b. Connect to master
• percona pt-online-schema-change
WriteIOPS와 ReadIOPS의 수치에서도 gh-ost에 비해 pt-online-schema-change가 상대적으로 더 많은 리소스 사용을 하는 것으로 테스트되었습니다.
이번 글은 MySQL Online Schema Change 유틸리티 중 하나인 gh-ost에 대해서 확인해 보았으며, 여기서 글을 마무리하도록 하겠습니다. 긴 글 읽어 주셔서 감사합니다.
Reference
Reference URL
• github.com/github/gh-ost
연관된 다른 글
이러한 Toolkit은 일일이 수동으로 작업하기 다소 복잡하거나 어려운 작업들을 단순하고 수월하게 할수 있게 도와주는 유용한 도구입니다.
Principal DBA(MySQL, AWS Aurora, Oracle)
핀테크 서비스인 핀다에서 데이터베이스를 운영하고 있어요(at finda.co.kr)
Previous - 당근마켓, 위메프, Oracle Korea ACS / Fedora Kor UserGroup 운영중
Database 외에도 NoSQL , Linux , Python, Cloud, Http/PHP CGI 등에도 관심이 있습니다
purityboy83@gmail.com / admin@hoing.io