gh-ost로 트리거 없는 온라인 스키마 변경
MySQL온라인 작업명령어
# Connects to a replica and reads its binlog; postpones cut-over until the flag file is removed
gh-ost --host=db2 --port=3306 --user=ghost --password='Gh0st#2024' \
--database=shop --table=orders \
--alter="ADD COLUMN channel VARCHAR(20) NULL, ADD INDEX ix_channel (channel)" \
--max-load=Threads_running=50 --critical-load=Threads_running=200 --max-lag-millis=1500 \
--exact-rowcount --concurrent-rowcount --default-retries=120 \
--postpone-cut-over-flag-file=/tmp/ghost.postpone --panic-flag-file=/tmp/ghost.panic \
--serve-socket-file=/tmp/gh-ost.shop.orders.sock --ssl --ssl-allow-insecure --execute
# While running: status / throttle / cut-over
echo status | nc -U /tmp/gh-ost.shop.orders.sock
echo throttle | nc -U /tmp/gh-ost.shop.orders.sock
rm /tmp/ghost.postpone하는 일
ghost 테이블을 만들고 행을 복사하며, 동시 변경은 트리거 대신 binlog를 읽어 적용한다. throttling, 일시 중지, cut-over 시점은 socket이나 flag 파일로 런타임에 제어한다.
사용 시점
트리거 오버헤드를 허용할 수 없는 쓰기가 많은 대형 테이블에서, cut-over 시점(예: 트래픽이 적은 시간대)을 직접 선택하고 싶을 때.
주의
binlog_format=ROW와 binlog_row_image=FULL이 필요하며, 연결하는 replica에는 log_replica_updates=ON이 필요하다. 사용자에게 SUPER 또는 REPLICATION CLIENT / REPLICATION SLAVE와 테이블에 대한 ALL이 필요하다. foreign key가 있는 테이블(부모 또는 자식)은 지원되지 않는다. cut-over 후 이전 테이블은 _<table>_del로 남으므로 검증 후 수동으로 삭제한다(--ok-to-drop-table은 자동으로 삭제한다). 1.1.8 이전 gh-ost 릴리스는 SHOW SLAVE STATUS를 사용하므로 MySQL 8.4에서 오류 1064로 멈춘다. 8.4 지원은 1.1.8에서 추가되었다. gh-ost는 --postpone-cut-over-flag-file에 지정한 파일을 직접 생성하며, 파일이 제거될 때까지 cut-over가 일어나지 않는다.