LLM WikiAccess-protected knowledge portal
← 스터디 홈
7편 · 약 23분

Metadata DB 운영: vacuum/analyze, cleanup, migration, connection pool

Metadata DB는 Airflow의 조용한 병목이다

Airflow 장애를 볼 때 많은 사람이 먼저 worker, Kubernetes pod, 외부 데이터베이스, Spark job을 의심한다. 그런데 scheduler가 task를 늦게 잡고, UI가 느려지고, queued 상태가 쌓이고, DAG parsing은 정상인데 실행 전환이 더디다면 Airflow metadata DB가 병목인 경우가 꽤 많다.

Metadata DB에는 단순한 설정만 들어가지 않는다. DAG run, task instance, job heartbeat, log metadata, XCom, rendered template, import error, user/session, connection, variable 같은 운영 상태가 계속 쌓인다. Airflow의 scheduler, webserver, triggerer, worker는 이 DB를 통해 상태를 읽고 쓴다. 그래서 metadata DB가 느려지면 Airflow 전체가 느려진다.

이 장의 핵심은 다음 네 가지다.

  1. vacuum/analyze: PostgreSQL 같은 backend에서 삭제·갱신 후 통계와 dead tuple을 관리한다.
  2. cleanup: 오래된 task/run/log/XCom metadata를 보존 정책에 맞게 지운다.
  3. migration: Airflow 업그레이드 전후로 schema migration을 안전하게 수행한다.
  4. connection pool: Airflow 컴포넌트가 만드는 DB connection 폭증을 제어한다.

중요한 관점은 “DBA가 알아서 해주는 DB”가 아니라, Airflow 운영자가 Airflow의 실행 특성을 알고 DB 운영 정책을 같이 설계해야 하는 DB라는 점이다.


1. Airflow 컴포넌트와 metadata DB의 상호작용

Metadata DB는 Airflow control plane의 중심이다. DAG 파일 자체는 filesystem, image, Git bundle 등에 있을 수 있지만, 실행 상태와 운영 기록은 DB에 모인다.

Airflow 컴포넌트
Scheduler
Webserver / API server
Worker
Triggerer
Connection 제어
SQLAlchemy pool
PgBouncer / DB proxy
max connections budget
Metadata DB
dag_run / task_instance
job / log / xcom
alembic_version
cleanup: 오래된 row 삭제
vacuum/analyze: 공간·통계 정리
migration: Airflow version과 schema 정렬
Airflow metadata DB 운영 경계

운영자가 봐야 하는 현상은 Airflow 화면의 증상과 DB 내부 상태를 연결하는 것이다.

Airflow 증상Metadata DB에서 의심할 것확인 방향
Scheduler가 task를 늦게 queueing함dag_run, task_instance, job 조회 지연slow query, index 사용, table bloat, DB CPU/IO
UI의 Grid/Graph/로그 화면이 느림과거 run/log/XCom 누적table size, 오래된 row 수, cleanup 주기
Scheduler heartbeat가 불안정함connection 고갈, DB lock, network 지연DB connection 수, pool 설정, long transaction
업그레이드 후 Airflow가 뜨지 않음schema migration 미적용 또는 실패airflow db check, airflow db migrate, migration log
DB 디스크가 계속 증가함log/XCom/rendered field 누적, vacuum 미흡retention, dead tuple, autovacuum 상태

Airflow 공식 문서도 metadata DB monitoring에서 CPU, I/O, memory, query frequency, slow/long query, execution plan, swap/cache 상태를 보라고 권한다. Airflow 자체가 DB 모니터링 도구를 제공하지는 않기 때문에, 실제 운영에서는 PostgreSQL/MySQL 모니터링 체계에 Airflow 전용 관점을 얹어야 한다.


2. Backend 선택: production에서는 SQLite를 잊어야 한다

Airflow는 SQLAlchemy를 통해 metadata DB에 접근한다. 기본값으로 SQLite를 쓸 수 있지만, 공식 문서 기준 SQLite는 개발 목적이다. production 또는 production과 비슷한 테스트라면 PostgreSQL이나 MySQL backend를 사용해야 한다.

특히 다음 사항을 기억해야 한다.

  • Airflow 3.2 문서 기준 지원 backend는 PostgreSQL, MySQL, SQLite이며, SQLite는 개발용이다.
  • MariaDB는 MySQL과 비슷해 보여도 Airflow backend로 지원되지 않는다. Airflow 문서는 migration script와 runtime이 MariaDB에서 테스트되지 않고 index 처리 같은 문제도 있어 사용을 강하게 말린다.
  • PostgreSQL connection string은 SQLAlchemy 1.4 이후 postgresql:// 또는 postgresql+psycopg2:// 형태를 써야 한다. 오래된 postgres:// prefix는 plugin load 오류를 낼 수 있다.
  • PostgreSQL을 schema 분리로 쓸 때는 search_pathSQL_ALCHEMY_SCHEMA를 같이 검토해야 한다.

운영 기준으로는 “Airflow가 DB에 연결된다”에서 끝나면 부족하다. 다음 질문을 같이 닫아야 한다.

  1. Airflow 전용 DB user의 권한은 migration과 runtime에 필요한 만큼인가?
  2. DB character set과 collation은 Airflow 권장값과 맞는가?
  3. scheduler/webserver/worker/triggerer 전체의 최대 connection 수가 DB budget 안에 들어오는가?
  4. backup과 restore 절차가 Airflow upgrade 전에 실제로 동작하는가?
  5. cleanup이 수행되어도 필요한 감사·장애 분석 데이터가 너무 빨리 사라지지 않는가?

3. Cleanup: 지워도 되는 것과 보존해야 하는 것을 나눈다

Airflow metadata는 자동으로 무한히 정리된다고 기대하면 안 된다. 과거 DAG run, task instance, log, XCom, rendered template 정보가 쌓이면 DB 크기와 query 비용이 증가한다. Airflow CLI에는 metadata DB history를 정리하는 airflow db clean 명령이 있다.

기본 형태는 다음과 같다.

airflow db clean --clean-before-timestamp "2026-06-01T00:00:00+00:00"

운영에서는 바로 삭제하지 말고 보통 다음 순서로 접근한다.

  1. 보존 정책 결정: 장애 분석, 감사, 재처리, SLA 보고에 필요한 기간을 정한다.
  2. 대상 table 검토: dag_run, task_instance, log, xcom, job, rendered_task_instance_fields처럼 빠르게 커지는 table을 확인한다.
  3. dry run 또는 staging 실행: 실제 삭제 전 삭제 범위와 실행 시간을 본다.
  4. 작은 batch로 실행: 한 번에 너무 오래 lock을 잡거나 replication lag를 만들지 않게 나눈다.
  5. 삭제 후 DB maintenance: PostgreSQL이면 vacuum/analyze, MySQL이면 table statistics와 purge 상태를 확인한다.
  6. 복구 가능성 확인: cleanup 직전 backup 또는 snapshot을 확보한다.

삭제 정책의 가장 큰 함정은 “오래된 것은 다 필요 없다”는 가정이다. 예를 들어 월별 DAG는 execution_date 또는 data interval과 실제 실행 시점 사이가 크게 벌어질 수 있다. Google Cloud Composer 문서도 30일 보존을 출발점으로 제안하면서, 월 단위 DAG처럼 scheduling 특성이 다르면 보존 기간을 늘리라고 설명한다.

실무에서 많이 쓰는 기준은 다음과 같다.

데이터삭제 전 확인할 질문보존 기준 예시
dag_run, task_instance과거 성공/실패 이력이 SLA·감사에 필요한가?30~180일, 규정 산업은 더 길게
log metadata실제 remote log 보존과 연결되어 있는가?remote log retention과 맞춤
xcomdownstream 재처리나 수동 rerun이 과거 XCom에 의존하는가?XCom 의존 설계를 줄이고 짧게 보존
rendered_task_instance_fields과거 template 값을 장애 분석에 쓰는가?최근 장애 분석 기간 중심
job, task_reschedulescheduler/worker 장애 분석에 필요한가?운영 분석 기간 중심

XCom은 특히 조심해야 한다. XCom을 작은 control metadata가 아니라 큰 payload 저장소처럼 쓰면 cleanup 이전에 이미 DB 성능을 망칠 수 있다. 대용량 데이터는 object storage나 외부 table에 두고 XCom에는 pointer만 넣는 편이 안전하다.


4. Vacuum/Analyze: 삭제했다고 DB가 바로 가벼워지는 것은 아니다

PostgreSQL backend를 쓰는 경우 cleanup으로 row를 삭제해도 table file이 즉시 작아지지 않을 수 있다. MVCC 구조 때문에 삭제된 row는 dead tuple로 남고, vacuum이 이를 회수 가능한 공간으로 정리한다. query planner가 좋은 실행계획을 고르려면 통계도 최신이어야 하므로 analyze가 필요하다.

Airflow 문서는 metadata DB maintenance에서 정기적인 house-keeping 작업, 예를 들어 ANALYZE SQL command 실행을 언급한다. PostgreSQL 운영 관점에서는 다음을 구분해야 한다.

  • ANALYZE: table 통계를 갱신한다. planner가 row 수와 분포를 더 잘 추정한다.
  • VACUUM: dead tuple을 정리하고 재사용 가능한 공간을 만든다.
  • VACUUM FULL: table을 rewrite해 파일 크기를 줄일 수 있지만 강한 lock과 큰 I/O를 유발하므로 운영 중 상시 작업으로 쓰면 위험하다.
  • autovacuum: 평소에는 자동 vacuum/analyze에 맡기되, Airflow table의 증가·삭제 패턴에 맞게 튜닝이 필요할 수 있다.

Cleanup 후 최소한 다음을 확인한다.

-- PostgreSQL 예시: Airflow 주요 table 크기 확인
SELECT
  relname AS table_name,
  pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
  n_live_tup,
  n_dead_tup,
  last_vacuum,
  last_autovacuum,
  last_analyze,
  last_autoanalyze
FROM pg_stat_user_tables
WHERE relname IN (
  'dag_run',
  'task_instance',
  'log',
  'xcom',
  'job',
  'rendered_task_instance_fields'
)
ORDER BY pg_total_relation_size(relid) DESC;

통계가 오래됐거나 대량 cleanup 직후라면 다음처럼 table별 analyze를 먼저 고려한다.

ANALYZE dag_run;
ANALYZE task_instance;
ANALYZE xcom;
ANALYZE log;

VACUUM FULL은 “디스크를 줄이고 싶다”는 이유만으로 바로 실행하지 않는다. Airflow metadata DB는 scheduler가 계속 접근하는 DB이므로 lock 영향이 Airflow 전체 장애로 번질 수 있다. 파일 크기 회수가 꼭 필요하다면 maintenance window, backup, failover/rollback plan, 예상 rewrite 시간, replication lag 영향을 먼저 계산해야 한다.

MySQL backend라면 용어는 다르지만 원칙은 같다. 오래된 row 삭제, purge 지연, table statistics, buffer pool pressure, slow query를 같이 봐야 한다. Airflow 관점에서는 DB engine별 세부 명령보다 삭제 후 planner/statistics와 I/O 상태를 확인하는 운영 루프가 더 중요하다.


5. Migration: Airflow version과 DB schema를 같은 릴리스 단위로 다룬다

Airflow upgrade에는 metadata DB schema migration이 따라올 수 있다. 공식 upgrade 문서는 새 버전 설치 후 필요하면 다음 명령을 실행하라고 설명한다.

airflow db migrate

Airflow 2.7 이후에는 airflow db upgrade보다 airflow db migrate가 기준이다. 문서에 따르면 migration이 없을 때 실행해도 안전하지만, 운영자가 이것을 “가볍게 아무 때나 실행해도 된다”로 해석하면 안 된다. Migration은 schema를 바꾸는 작업이고, 실패하면 DB가 half-migrated 상태에 남을 수 있다.

안전한 migration 절차는 다음과 같다.

  1. 현재 상태 기록

- Airflow version - DB engine/version - current image/tag - airflow db check 결과 - DB backup timestamp

  1. release note와 migration note 확인

- 제거된 config - provider compatibility - DB backend 요구사항 변화

  1. staging에서 migration rehearsal

- production snapshot 또는 anonymized copy로 실행 시간과 오류를 확인한다.

  1. 운영 backup 확보

- hot backup이 불가능한 DB라면 Airflow 컴포넌트를 멈춘 뒤 consistent backup을 만든다.

  1. Airflow 컴포넌트 정지 또는 write 최소화

- scheduler/worker/webserver가 구버전 code로 동시에 schema에 접근하지 않게 한다.

  1. migration 실행

- 같은 Airflow version의 CLI가 DB에 접근하도록 한다.

  1. 검증

- airflow db check - scheduler heartbeat - webserver/API 정상 기동 - canary DAG run

  1. rollback 기준 확인

- code rollback만으로 충분한지, DB restore가 필요한지 판단한다.

오프라인 리뷰가 필요한 조직에서는 SQL만 생성해 DBA 리뷰를 받을 수도 있다.

airflow db migrate --show-sql-only --from-version "2.8.4" --to-version "2.9.3"

지원 범위와 옵션은 Airflow version에 따라 달라질 수 있으므로, 실제 운영 runbook에는 해당 version의 공식 CLI reference를 링크해야 한다.


6. Connection pool: Airflow는 생각보다 많은 DB connection을 만든다

Airflow 공식 DB setup 문서는 고성능 구성에서 Airflow가 metadata DB에 많은 connection을 열 수 있다고 설명한다. PostgreSQL은 connection마다 process를 만들기 때문에 connection 수가 많으면 DB resource 사용량이 커진다. 그래서 production PostgreSQL 설치에서는 PgBouncer 같은 DB proxy 사용을 권장한다.

Connection budget은 다음 컴포넌트를 모두 합산해야 한다.

  • scheduler 개수와 scheduler 내부 parallelism
  • webserver/API server process 수
  • worker 수와 worker concurrency
  • triggerer 수
  • DAG parsing process
  • CLI, migration job, monitoring job
  • cleanup DAG 또는 maintenance job

단순 예시는 다음과 같다.

DB max_connections = 300
reserved_for_admin = 20
reserved_for_migration_and_monitoring = 20
available_for_airflow = 260

scheduler + webserver + triggerer + workers의 worst-case connection 수가
260을 넘지 않도록 SQLAlchemy pool, process 수, PgBouncer pool을 조정한다.

운영자가 흔히 놓치는 부분은 “평소 평균 connection”이 아니라 장애 시 worst case다. 예를 들어 scheduler restart, webserver autoscaling, worker 폭증, retry storm, cleanup job이 겹치면 connection이 한꺼번에 늘 수 있다. 이때 DB가 connection을 거절하면 Airflow는 더 느려지고, retry가 다시 DB를 두드리는 악순환이 생긴다.

PostgreSQL에서는 PgBouncer를 둘 때도 pooling mode를 신중히 고른다. Airflow와 SQLAlchemy는 transaction, session 설정, prepared statement, advisory lock 같은 DB 기능과 상호작용할 수 있다. “PgBouncer를 켜면 무조건 해결”이 아니라 staging에서 scheduler, migration, web UI, task execution을 함께 검증해야 한다.


7. 운영 대시보드에 넣을 지표

Metadata DB 운영 대시보드는 Airflow 지표와 DB 지표를 나란히 보여줘야 한다. DB만 보면 Airflow 영향이 안 보이고, Airflow만 보면 DB 원인이 안 보인다.

영역지표의미
Airflow schedulerscheduler heartbeat, queued task 수, scheduling delayDB 지연이 control loop에 미치는 영향
Airflow run 상태running/queued/failed task instance 수backlog와 retry storm 확인
DB connectionactive/idle connection, max 대비 사용률connection pool 고갈 위험
DB queryslow query, long transaction, lock waitscheduler/UI 지연 원인
DB storagetable size, index size, dead tuple, disk freecleanup/vacuum 필요성
DB I/Oread/write IOPS, fsync/checkpoint 지연metadata write burst 영향
Cleanup마지막 cleanup 시간, 삭제 row 수, 실행 시간retention 정책이 실제로 작동하는지
Migrationcurrent Airflow version, alembic revision, db check 결과code/schema mismatch 예방

알림도 단일 지표보다 조합이 낫다.

  • DB connection usage > 80%queued task 증가가 같이 나타나면 connection budget 문제일 수 있다.
  • task_instance table size가 계속 증가하고 cleanup 성공 로그가 없으면 retention job이 멈췄을 수 있다.
  • scheduler heartbeat 지연과 DB slow query가 동시에 증가하면 Airflow code보다 DB plan/statistics 문제를 먼저 볼 수 있다.
  • migration 직후 airflow db check 실패, import error 증가, scheduler restart loop가 보이면 즉시 rollout을 멈춘다.

8. Metadata DB runbook 예시

운영 runbook은 “누가 봐도 같은 순서로 판단할 수 있게” 짧고 명확해야 한다.

8.1 UI와 scheduler가 느릴 때

  1. Airflow scheduler heartbeat와 queued/running task 추이를 본다.
  2. DB connection 사용률과 lock wait를 확인한다.
  3. slow query에서 task_instance, dag_run, xcom, log 관련 query가 느린지 본다.
  4. 최근 cleanup, DAG 배포, Airflow upgrade, DB maintenance가 있었는지 확인한다.
  5. table size와 statistics freshness를 확인한다.
  6. 통계가 낡았으면 ANALYZE를 우선 검토한다.
  7. cleanup이 오래 멈췄다면 작은 batch로 재개한다.
  8. connection 고갈이면 worker/webserver scaling을 먼저 멈추고 pool budget을 조정한다.

8.2 Cleanup을 실행할 때

  1. 삭제 기준 timestamp와 retention 근거를 기록한다.
  2. 삭제 대상 table을 확인한다.
  3. 최근 backup 또는 snapshot을 확인한다.
  4. staging 또는 dry run으로 예상 row 수를 본다.
  5. 운영 시간대 영향이 낮은 시간에 batch 실행한다.
  6. 실행 후 Airflow UI, scheduler heartbeat, DB slow query를 확인한다.
  7. PostgreSQL이면 analyze/vacuum 상태를 확인한다.
  8. 삭제 row 수와 DB 크기 변화를 기록한다.

8.3 Airflow upgrade migration을 할 때

  1. production DB backup을 만든다.
  2. 같은 backup으로 staging migration을 먼저 수행한다.
  3. migration SQL 또는 release note의 위험 변경을 리뷰한다.
  4. Airflow 컴포넌트를 정지하거나 write를 최소화한다.
  5. 새 Airflow image/venv에서 airflow db migrate를 실행한다.
  6. airflow db check와 canary DAG run을 수행한다.
  7. 실패 시 code rollback으로 충분한지, DB restore가 필요한지 결정한다.

9. 실무 판단 기준

Metadata DB 운영은 과하게 복잡하게 만들 필요는 없다. 하지만 다음 기준은 반드시 가져가야 한다.

  • Cleanup 없는 Airflow는 언젠가 느려진다. 특히 task 수가 많고 schedule이 촘촘한 환경에서는 metadata 증가 속도를 추정해야 한다.
  • 삭제는 끝이 아니라 maintenance의 시작이다. PostgreSQL에서는 cleanup 후 vacuum/analyze와 statistics 상태를 확인한다.
  • Migration은 application deploy가 아니라 DB schema 변경이다. backup, rehearsal, rollback 기준 없이 실행하지 않는다.
  • Connection은 평균이 아니라 최악 상황으로 계산한다. retry storm과 autoscaling이 겹칠 때 DB를 보호해야 한다.
  • Airflow 증상과 DB 지표를 같이 본다. scheduler delay, UI latency, queued task, DB slow query를 한 화면에서 연결해야 원인 분석이 빨라진다.

좋은 Airflow 운영자는 DAG 문법만 아는 사람이 아니다. Airflow가 metadata DB를 어떤 식으로 사용하고, 그 DB가 느려질 때 scheduler와 UI가 어떻게 흔들리는지 이해하는 사람이다. Metadata DB를 별도 운영 대상으로 다루기 시작하면 Airflow 장애 대응은 훨씬 예측 가능해진다.


References

  • Apache Airflow Documentation, “Set up a Database Backend”, https://airflow.apache.org/docs/apache-airflow/stable/howto/set-up-database.html
  • Apache Airflow Documentation, “Using the Command Line Interface”, https://airflow.apache.org/docs/apache-airflow/stable/howto/usage-cli.html
  • Apache Airflow Documentation, “Upgrading Airflow to a newer version”, https://airflow.apache.org/docs/apache-airflow/stable/installation/upgrading.html
  • Apache Airflow Documentation, “ERD Schema of the Database”, https://airflow.apache.org/docs/stable/database-erd-ref.html
  • Google Cloud Composer Documentation, “Clean up the Airflow database”, https://docs.cloud.google.com/composer/docs/composer-2/cleanup-airflow-database