라떼군 이야기
PostgreSQL pg_dump 복원 시 'transaction_timeout' 에러 원인과 해결 방법
Problem
PostgreSQL 데이터베이스 스키마나 데이터를 백업하고 다른 데이터베이스에 복원(restore)하는 과정에서 종종 버전 불일치로 인한 에러를 마주하게 됩니다. 특히 서버 버전(예: 15.x)보다 상위 버전의 클라이언트 도구(예: pg_dump 17.0)를 사용하여 덤프를 생성한 후, 이를 다시 하위 버전의 서버에 적용하려고 할 때 문제가 발생합니다. 이때 psql을 통해 스키마를 적용하면 ERROR: unrecognized configuration parameter "transaction_timeout"과 같은 에러가 발생하며 복원이 중단되는 현상을 겪을 수 있습니다.
Background
이 문제의 근본적인 원인은 pg_dump의 설계 철학과 하위 호환성 정책에 있습니다. PostgreSQL 공식 문서에 따르면, pg_dump는 주로 구버전에서 신버전으로 데이터를 마이그레이션(업그레이드)하는 목적으로 사용됩니다. 따라서 pg_dump는 자신의 버전보다 오래된 서버(9.2 버전까지)에서 데이터를 추출하는 것은 지원하지만, 추출된 덤프 파일이 이전 버전의 서버에 문제없이 로드된다는 보장은 하지 않습니다. 즉, 17 버전의 pg_dump로 15 버전 서버의 데이터를 덤프하더라도, 덤프 파일에는 17 버전에 새로 추가된 설정(예: transaction_timeout)이 포함될 수 있으며, 이를 15 버전 서버가 이해하지 못해 에러가 발생하는 것입니다.
Solution
이 문제를 해결하기 위해서는 크게 두 가지 접근 방법이 있습니다. 상황에 맞게 적절한 방법을 선택하세요.
1. 클라이언트와 서버 버전 일치시키기 (가장 권장되는 방법)
가장 확실하고 안전한 방법은 데이터베이스 서버와 동일한 버전의 pg_dump 및 psql 클라이언트 도구를 사용하는 것입니다. Docker 환경을 사용 중이라면, 로컬에 설치된 최신 클라이언트를 쓰지 말고 해당 데이터베이스 컨테이너 내부의 도구를 활용하는 것이 좋습니다.
# 1. Postgres 15 컨테이너 내부의 pg_dump를 사용하여 덤프 생성 (버전 일치)
docker exec -i <컨테이너_이름> pg_dump --schema-only -U <사용자명> db1 > schema.sql
# 2. 동일하게 컨테이너 내부의 psql을 사용하여 복원
docker exec -i <컨테이너_이름> psql -U <사용자명> -d db2 < schema.sql
2. 덤프 파일에서 호환되지 않는 구문 제거하기
이미 덤프 파일을 생성했고 클라이언트 버전을 당장 변경하기 어려운 환경이라면, 덤프된 SQL 파일에서 구버전 서버가 인식하지 못하는 SET 구문을 수동으로 또는 스크립트로 제거해야 합니다. 리눅스/맥 환경에서는 sed 명령어를 활용할 수 있습니다.
# schema.sql 파일에서 'SET transaction_timeout'이 포함된 줄을 삭제하고 새로운 파일로 저장합니다.
sed '/SET transaction_timeout = 0;/d' schema.sql > schema_fixed.sql
# 수정된 파일을 대상 데이터베이스에 복원합니다.
psql 'postgresql://user:password@host/db2' < schema_fixed.sql
3. psql 실행 시 에러 무시 옵션 사용 (주의 필요)
단순한 환경 변수 설정 에러이고 스키마 생성 자체에는 문제가 없다면, psql 실행 시 에러가 발생해도 멈추지 않도록 할 수 있습니다. 하지만 다른 치명적인 문법 에러도 무시될 수 있으므로 권장하지는 않습니다.
# ON_ERROR_STOP 변수를 해제하여 에러가 발생해도 다음 쿼리를 계속 실행하도록 합니다.
# (기본적으로 psql은 스크립트 실행 중 에러가 나면 계속 진행하지만,
# 파이프라인이나 특정 설정에 따라 중단될 수 있으므로 명시적으로 제어할 때 사용합니다.)
psql -v ON_ERROR_STOP=0 'postgresql://user:password@host/db2' < schema.sql
Deep Dive
프로덕션 환경이나 CI/CD 파이프라인에서 자동화된 백업 및 복구 스크립트를 작성할 때는 도구의 버전 관리가 매우 중요합니다. pg_dump가 덤프 파일 상단에 수많은 SET 구문을 추가하는 이유는, 복원되는 서버의 기본 설정(타임존, 인코딩, 타임아웃 등)에 영향을 받지 않고 원본과 100% 동일한 환경을 강제하기 위함입니다. 따라서 이러한 SET 구문을 무작정 삭제하기보다는, 인프라 구성 시 PostgreSQL 서버 버전과 클라이언트 유틸리티 버전을 명시적으로 동기화하는 파이프라인을 구축하는 것이 베스트 프랙티스입니다. 만약 다양한 버전의 DB를 관리해야 한다면, 각 버전에 맞는 클라이언트 도구들을 독립된 Docker 이미지로 만들어 사용하는 것이 좋습니다.
Conclusion
pg_dump는 상위 버전으로의 데이터 마이그레이션을 염두에 두고 설계되었기 때문에, 상위 버전의 도구로 생성한 덤프를 하위 버전 서버에 복원할 때 호환성 에러가 발생할 수 있습니다. 이 문제를 깔끔하게 해결하려면 서버와 클라이언트 도구의 버전을 일치시키는 것이 가장 바람직하며, 불가피한 경우 덤프 파일에서 호환되지 않는 구문을 sed 등으로 제거한 후 복원해야 합니다.