SI DB 운영 · DDL 과 변경관리 · 실습
스키마 변경과 롤백 스크립트 작성
목표
확장-이관-축소 패턴으로 스키마를 변경하고, 롤백 스크립트와 배치 백필,
검증 스크립트, 작업 절차서까지 갖춘 변경관리 한 세트를 만들 수 있게 됩니다.
왜 중요한가
"down 스크립트가 있으니 안전하다"는 가장 흔한 착각입니다.DROP COLUMN 을 되돌리는 down 은 컬럼 구조만 되살릴 뿐 값은 못 되살립니다.
가역성은 코드의 속성이 아니라 코드와 데이터와 시간의 조합이라서,
같은 변경도 어제 배포했으면 가역이고 백만 건이 쌓인 뒤엔 비가역입니다.
그리고 대량 백필을 한 트랜잭션으로 돌리면 잠금과 로그가 폭증해
읽기 복제본이 밀리고, 조회 서비스가 오래된 데이터를 보여 줍니다.
이 실습은 그 함정들을 손으로 피해 보는 훈련입니다.
단계
0. 준비: dbo-schema 실습의 /root/db/si.db 가 있어야 합니다.
없다면 /opt/lab/fixtures/dbo/si-base.sql 로 만들 수 있습니다.
1. 현재 스키마를 /root/db/schema_v1.sql 로 저장하고,/root/db/baseline.txt 를 만듭니다. 세 줄입니다.
orders_cnt=<ORDERS 행 수> orders_amt=<ORDERS 의 ORD_AMT 합계> item_qty=<ORDER_ITEM 의 QTY 합계>2. /root/db/changelog.csv 를 만듭니다. 첫 줄은chg_id,date,object,ddl_file,rollback_file,est_sec,approver.
3~5 단계에서 만들 변경 3건을 미리 등록합니다.ddl_file·rollback_file·approver 는 비어 있으면 안 되고,est_sec 에는 숫자가 들어가야 합니다.
3. /root/db/mig/V2__add_dlvr_sts.sql 을 만듭니다.
ORDERS에DLVR_STS_CD컬럼 추가 (기본값'01')- 기존 행을 모두
'01'로 채움
적용 후 DLVR_STS_CD 가 NULL 인 행이 0건이어야 합니다.
4. /root/db/mig/V2__rollback.sql 을 만듭니다.
적용하면 스키마가 schema_v1.sql 과 같아져야 합니다.
(si.db 사본에서 up → down 을 실행해 확인하세요.)
5. /root/db/mig/V3__item_qty_check.sql 을 만듭니다.ORDER_ITEM.QTY 의 CHECK 를 1 이상 9999 이하로 강화합니다.
sqlite 는 제약 변경을 지원하지 않으므로 테이블 재작성 절차가 필요합니다.
적용 후에도 ORDER_ITEM 행 수와 QTY 합계가 1단계 기준선과 같아야 하고,
외래키 관계도 유지돼야 합니다.
6. /root/db/batch-update.sh 를 만듭니다. 인자 두 개(DB파일 배치크기)를 받아ORDERS 의 DLVR_STS_CD 가 '01' 인 행을 '02' 로 바꾸되,
한 번에 배치크기만큼씩 반복 처리합니다.
마지막 줄에 batches=<반복횟수> updated=<총건수> 를 출력합니다.
(원본을 더럽히지 않도록 인자로 받은 DB 에만 적용합니다.)
7. /root/db/mig-verify.sh 를 만듭니다. 인자 두 개(기준선파일 DB파일)를 받아
기준선의 세 지표를 현재 DB 와 비교하고,
모두 같으면 첫 줄에 OK, 다르면 NG 로 시작하는 줄과 함께
어떤 지표가 다른지 출력합니다. 종료코드도 각각 0 과 0 이 아닌 값입니다.
8. /root/db/mig-runbook.md 를 작성합니다.## 작업 개요, ## 사전 백업, ## 적용 절차, ## 검증,## 롤백 기준, ## 롤백 절차 여섯 개의 h2 제목이 있어야 하고,
본문에 백업 파일 경로와 숫자로 된 롤백 기준(소요 시간 또는 검증 실패 건수)이
들어가야 합니다.
참고
- 스키마 덤프:
sqlite3 /root/db/si.db .schema > schema_v1.sql - 테이블 재작성 순서:
PRAGMA foreign_keys=off→ 새 테이블 생성 → - 영향 행 수:
SELECT changes(); - 흔한 실수 1: 사본을 만들지 않고 원본에서 시험해 되돌릴 수 없게 되는 것.
- 흔한 실수 2: 테이블 재작성 때 인덱스를 다시 만들지 않는 것.
- 흔한 실수 3: 배치 백필 루프에 종료 조건이 없어 무한 루프가 되는 것.
INSERT ... SELECT → 기존 테이블 DROP → RENAME → 인덱스 재생성 → PRAGMA foreign_keys=on
DROP 하면 인덱스도 함께 사라집니다.
영향 행이 0이면 멈춰야 합니다.
단계 8개
- 스키마 스냅샷과 기준선
- 변경관리 대장
- 확장 스크립트
- 롤백 스크립트
- 테이블 재작성 마이그레이션
- 배치 백필
- 마이그레이션 검증 스크립트
- 작업 절차서