목록 보기
Python의 GC가 멀티프로세싱과 만나면 생기는 일 - Python과 Airflow, 그리고 관련된 문제 해결기 2편
백엔드

Python의 GC가 멀티프로세싱과 만나면 생기는 일 - Python과 Airflow, 그리고 관련된 문제 해결기 2편

네이버 D2
네이버 D2
2026년 10월 8일

두줄요약

Airflow의 fork 기반 프로세스에서 Python 순환 GC가 COW와 MySQL 커넥션 종료를 유발한 원인을 분석했습니다. Memray로 별도 누수를 수정하고, 지연 import로 fork 승계 객체를 줄이는 접근을 다뤘습니다.

문제 상황

  • Airflow의 fork 기반 worker에서 RSS 변화 없이 PSS·USS만 지속 증가하는 메모리 사용량 상승
  • MySQL 환경의 dag-processor에서 부모 DB 커넥션 종료 후 쿼리 실패와 불규칙한 재시작
  • Memray로 확인한 불필요한 kubernetes.client import 및 SSL context 반복 생성 문제

원인 분석

  • fork 이후 자식의 순환 GC가 부모에게서 승계한 추적 객체의 PyGC_Head에 기록하며 COW 유발
  • SQLAlchemy 풀과 커넥션 레코드의 순환 참조가 자식 GC 시점에 수거되며 mysqlclient의 COM_QUIT 전송
  • 작업 시간이 길고 객체 할당이 많을수록 GC 임계값 도달 가능성 증가

구조와 흐름

  • fork 직후 부모·자식의 물리 페이지 공유와 양쪽 PTE 쓰기 금지 상태
  • 자식의 gc.collect()만으로 객체가 놓인 공유 페이지의 PFN 분리 확인
  • 자식 시작 시 engine.dispose(close=False) 이후에도 순환 참조 객체의 지연 수거 가능성

해결 방법

  • Memray 기반 분석으로 secrets masker의 불필요한 모듈 import와 Task SDK client의 SSL context 누수 수정
  • worker 생성 이후 무거운 모듈을 지연 import하여 fork 시 승계 객체량 축소
  • 주요 컴포넌트의 Memray 추적 실행 기능과 메모리 프로파일링 문서 추가

네이버 계열사 채용4건

채용 사이트에서 전체 보기

다음 읽기

#Python 주제를 이어서 읽기

Python의 멀티프로세싱과 Airflow, 그리고 관련된 문제 해결기 1편

Airflow task 실행에서 필요한 병렬성과 격리성을 설명하고, fork와 spawn의 차이를 비교했습니다. Airflow 3가 성능상 fork를 채택한 이유와 프로세스 구조도 정리했습니다.

네이버 D2
네이버 D2
백엔드

댓글 0개

댓글을 작성하려면 로그인이 필요합니다.

댓글을 불러오는 중...