Aurora MySQL 대용량 테이블 DROP COLUMN

2026. 3. 19. 01:02Linux/MySQL

728x90
SMALL

Aurora MySQL 대용량 테이블 DROP COLUMN, 두 번 실패 후 성공한 기록

수억 행, 200GB가 넘는 테이블에서 컬럼을 제거해야 할 때가 있다. ALTER TABLE DROP COLUMN은 단순해 보이지만, 테이블 규모가 크면 예상보다 훨씬 오래 걸리고, 리소스 부족으로 실패하기도 한다. 이번에는 두 번 실패한 뒤 세 번째 시도에서 성공한 과정을 정리해봤다.


배경: 왜 컬럼을 제거했나

개인정보 보호를 위해 기존 평문 컬럼을 제거하고, 암호화된 컬럼만 남기는 작업이었다. 대상 테이블은 감사(audit) 로그용으로, 수억 행에 200GB 이상의 데이터와 인덱스를 가지고 있었다.


1차 시도: 일괄 DROP – 실패

첫 시도는 3개 컬럼을 한 번에 제거하는 방식이었다.

ALTER TABLE target_table
  DROP COLUMN col1,
  DROP COLUMN col2,
  DROP COLUMN col3,
  ALGORITHM=INPLACE,
  LOCK=NONE;
  • 인스턴스 스펙: (2 vCPU, 16GB 메모리)
  • 실행 시점: 새벽 (트래픽 최소)
  • 결과: 실패

추정 원인은 리소스 부족이었다. 대용량 테이블 리빌드 시 메모리, lock wait timeout 등에 여유가 부족했을 가능성이 크다.


2차 시도: 컬럼별 분리 실행 – 또 실패

부담을 줄이려고 컬럼을 하나씩 나눠서 실행해봤다.

ALTER TABLE target_table DROP COLUMN col1, ALGORITHM=INPLACE, LOCK=NONE;
-- 완료 후
ALTER TABLE target_table DROP COLUMN col2, ALGORITHM=INPLACE, LOCK=NONE;
-- 완료 후
ALTER TABLE target_table DROP COLUMN col3, ALGORITHM=INPLACE, LOCK=NONE;
  • 결과: 실패

컬럼을 나눠도 테이블 전체 리빌드가 필요하다는 점은 같다. 한 번에 3개를 하든 1개씩 하든, 처리해야 할 데이터 양은 비슷하고, 결국 같은 리소스 한계에 부딪혔다.


3차 시도: 스펙업 후 재시도 – 성공

사전 준비

인스턴스 스펙업

항목 변경 전 변경 후
vCPU 2 16
메모리 16GB 128GB
  • Writer, Reader를 순차적으로 스펙업 (디비스펙업 시에는 Reader부터 하면 failover를 한 번만 할 수 있다)
  • Storage-optimization이 끝난 뒤 ALTER 실행 (한 인스턴스가 Storage-optimization 중일 때 다른 인스턴스 수정은 가능하지만, DDL 복제 부담을 줄이려면 모두 available 상태일 때 실행하는 것이 안전함)

세션 타임아웃 설정

SET SESSION wait_timeout = 86400;
SET SESSION lock_wait_timeout = 86400;

SET SESSION은 해당 연결에만 적용되므로, 다른 서비스에는 영향을 주지 않는다.

실행 및 결과

동일한 ALTER를 다시 실행했고, 약 3~4시간 후 성공적으로 완료되었다.


진행 상황 모니터링

수 시간 걸리는 작업이라, 진행 여부를 확인할 방법이 필요했다.

1. Performance Schema

SELECT * FROM performance_schema.events_stages_current 
WHERE EVENT_NAME LIKE '%alter%' OR EVENT_NAME LIKE '%copy%';
  • stage/innodb/alter table (merge sort) → merge sort 단계 (가장 오래 걸림)
  • stage/innodb/alter table (insert) → insert 단계
  • WORK_COMPLETED, WORK_ESTIMATED가 함께 증가하면 진행 중

2. Performance Insights

  • wait/io/file/innodb/innodb_temp_file wait가 보이기 시작하면, 임시 파일 I/O가 진행 중이라는 의미로, 실제 데이터 복사 단계에 진입한 것이다.
  • CPU 사용률이 낮게 나와도(예: 11%) I/O bound 구간에서는 정상이다.

3. CloudWatch – FreeLocalStorage

  • ALTER 진행 중: 임시 파일 사용으로 FreeLocalStorage 감소
  • 완료 후: 정리되면서 원래 수준으로 복귀

이 지표만으로도 "진행 중인지", "완료되었는지"를 대략 파악할 수 있었다.

4. 프로세스 확인

SHOW PROCESSLIST;

Statecopying to tmp table 또는 altering table이면 진행 중이다.


알게 된 점 정리

  1. 컬럼별 DROP이 항상 유리한 건 아니다
    테이블 리빌드 규모가 같다면, 나눠서 해도 리소스 부담은 비슷하다.

  2. 대용량 DDL은 인스턴스 스펙이 중요하다
    메모리와 CPU가 충분해야 버퍼 풀, 정렬, I/O를 감당할 수 있다.

  3. Storage-optimization은 인스턴스별 제한
    한 인스턴스가 Storage-optimization 중이어도, 다른 인스턴스는 수정할 수 있다. 다만 DDL 복제 부담을 고려하면, 모두 available일 때 실행하는 편이 안전하다.

  4. FreeLocalStorage로 진행 여부 추정 가능
    CloudWatch에서 이 지표가 줄었다가 다시 올라오면, ALTER가 끝났을 가능성이 높다.

  5. 디비스펙업 시 Reader부터
    Reader를 먼저 스펙 다운하면 failover를 한 번만 할 수 있다.


실패 시 대안

같은 방식으로 또 실패한다면, 아래를 검토할 수 있다.

방법 비고
pt-online-schema-change 청크 단위로 처리, Aurora에서도 사용 가능
gh-ost 바이너리 로그 기반 온라인 스키마 변경
유지보수 시간 + ALGORITHM=COPY 다운타임을 허용할 수 있다면, 한 번에 처리 가능

마치며

대용량 테이블 DDL은 "쿼리 한 줄"이지만, 실제로는 수 시간이 걸리고, 리소스 설계가 중요하다. 이번 경험을 바탕으로, 비슷한 규모의 작업을 할 때 참고할 수 있기를 바란다.

728x90
LIST