PostgreSQL에서 운영 중인 테이블에 컬럼을 추가하거나 인덱스를 생성할 때 서비스 다운타임이 발생합니다. 특히 대용량 테이블(1000만 행)에 ALTER TABLE하면 락이 걸려서 요청이 밀리더라고요.
무중단으로 DB 스키마를 변경하려면 어떤 전략을 써야 하나요? 지금은 새벽에 점검 걸고 마이그레이션하는데, 24/7 서비스라 이것도 한계가 있습니다.
-- 나쁜 예 (테이블 락) ALTER TABLE users ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
-- 좋은 예 (PostgreSQL 11+에서는 DEFAULT가 메타데이터만 변경) -- 하지만 구버전이면 3단계로: ALTER TABLE users ADD COLUMN status TEXT; UPDATE users SET status = 'active' WHERE status IS NULL; -- 배치로 ALTER TABLE users ALTER COLUMN status SET NOT NULL;
2) 인덱스는 반드시 CONCURRENTLY:
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
3) 컬럼 타입 변경은 새 컬럼 추가 → 데이터 복사 → 이름 교체 패턴으로.
expand-and-contract 패턴을 검색해보시면 체계적인 방법론을 확인할 수 있습니다.
서서버지기영호1년 전
저희는 gh-ost(GitHub Online Schema Migration Tool) 쓰고 있습니다. MySQL 전용이긴 한데, PostgreSQL이면 pgroll이라는 도구가 비슷한 역할을 합니다. 자동으로 expand-contract 패턴을 적용해줍니다.
풀풀스택지훈1년 전
statement_timeout 설정도 중요합니다. ALTER TABLE이 오래 걸리면 자동으로 취소되게: SET statement_timeout = '5s'; 이러면 락 대기가 5초 넘으면 자동 롤백됩니다.
코코딩하는민수1년 전
CONCURRENTLY 옵션을 몰랐네요! 인덱스 생성 때문에 매번 점검 걸었는데... statement_timeout 팁도 감사합니다.
김김영삼1년 전
추가로 lock_timeout도 함께 설정하시면 좋습니다. SET lock_timeout = '3s'; 이러면 다른 트랜잭션의 락을 3초 이상 기다리지 않고 바로 실패합니다. 재시도 로직과 함께 쓰면 안전합니다.
댓글 5
1) NOT NULL 컬럼 추가 시 DEFAULT 값과 함께:
2) 인덱스는 반드시 CONCURRENTLY:
3) 컬럼 타입 변경은 새 컬럼 추가 → 데이터 복사 → 이름 교체 패턴으로.
expand-and-contract 패턴을 검색해보시면 체계적인 방법론을 확인할 수 있습니다.
SET statement_timeout = '5s';
이러면 락 대기가 5초 넘으면 자동 롤백됩니다.
SET lock_timeout = '3s';
이러면 다른 트랜잭션의 락을 3초 이상 기다리지 않고 바로 실패합니다. 재시도 로직과 함께 쓰면 안전합니다.