# 운영 적용 런북: REQ-057 — portfolio_ledger 수동 장부 메타데이터 migration - Batch: BAT-025 - Discovery: dcy-012 - Date: 2026-07-15 - 결재 게이트: REQ-057 완료 승인 및 release 결재 필수 - 작업 예상 시간: 약 20~40분 --- ## 전제 조건 - DB 백업 완료 - `PORTFOLIOHUB_DB_ENABLED=true` 및 DB 접속 환경변수 설정 - 대상 DB는 `alembic current`로 `20260628_0027` 상태(또는 그 이전 배포 라인)에서 진행 - 새 코드 배포는 `alembic upgrade 20260715_0028` 완료 + 검증 성공 및 `M5 Release` 결재 후에만 수행 > 주의: 운영 DB는 본 배치에서 실제 upgrade/runbook 실행 대상을 만들지 않는다. 아래는 실운영 적용 체크리스트이다. --- ## 0) 사전 점검 ```bash export TIMESCALEDB_HOST= export TIMESCALEDB_PORT= export TIMESCALEDB_NAME= export TIMESCALEDB_USER= export TIMESCALEDB_PASSWORD= export PORTFOLIOHUB_DB_ENABLED=true alembic heads alembic current ``` - `alembic heads`에는 구현 시점 head `20260715_0028`가 확인되어야 한다. - `alembic current` 값이 `20260715_0028`이면 이미 마이그레이션 적용 완료 상태다. ## 1) 프리체크 ### 1-1. 대기 중인 락/액티브 커넥션 ```sql SELECT pid, usename, application_name, state, wait_event_type, wait_event, query FROM pg_stat_activity WHERE query ILIKE '%portfolio_ledger%' AND state != 'idle'; ``` - 결과는 반드시 비어 있거나 승인된 윈도우에서만 허용. ### 1-2. 대상 스키마 및 데이터 건수 ```sql -- 현재 컬럼 상태 SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name = 'portfolio_ledger' AND column_name IN ('source', 'target_ledger_entry_id', 'confirmation_evidence', 'actor_user_id') ORDER BY column_name; -- 기존 행 수(증적) SELECT COUNT(*) AS rows FROM portfolio_ledger; ``` - `source`가 이미 없거나 NULL 허용 상태여도 업그레이드 실행 전/후로 수렴 가능. --- ## 2) 마이그레이션 실행 ```bash alembic upgrade 20260715_0028 ``` ### 수신 메시지 예시 - 정상: `Running upgrade ...` 형태로 revision 로그 출력 - 실패: 즉시 종료되며 partial 변경 여부는 로그로 확인 --- ## 3) 사후 검증 ```sql SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name = 'portfolio_ledger' AND column_name IN ('source', 'target_ledger_entry_id', 'confirmation_evidence', 'actor_user_id') ORDER BY column_name; -- source backfill 결과(0이어야 함) SELECT COUNT(*) AS null_source_rows FROM portfolio_ledger WHERE source IS NULL; SELECT COUNT(*) AS rows_after FROM portfolio_ledger; SELECT column_name, is_nullable FROM information_schema.columns WHERE table_name = 'portfolio_ledger' AND column_name = 'source'; SELECT column_default FROM information_schema.columns WHERE table_name = 'portfolio_ledger' AND column_name = 'source'; ``` - 기대치: `source`가 `NOT NULL`, `DEFAULT 'broker'`, `null_source_rows = 0` - `rows_after` 값은 프리체크 시점과 일치해야 한다. - `alembic current`가 `20260715_0028`로 일치해야 한다. ```bash alembic current ``` --- ## 4) 실패 대응 (Forward-only) - 업그레이드 실패 시 바로 이전 코드로 rollback은 허용하되, 본 migration에서 추가된 4개 컬럼은 운영에서 자동 삭제하지 않는다. - 필요한 경우 운영 담당과 협의하여 수동 복구 계획을 수립한다. - 필수 검토 항목: 대상 DB 백업 상태, 실행 로그, 에러 스택, 락/동시 접속 상태 --- ## 5) 운영 활성화 조건 - 위 사후 검증(`alembic current`/schema/row count/source null 없음) 완료 - API smoke(REQ-056 manual ledger) 통과 - release 결재 완료 - 위 조건 충족 시 신규 코드 재시작 및 API 활성화 수행