2026년 07월 23일 | DBMS Error 가이드
이 글에서 다루는 내용
HV021 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
HV021 fdw inconsistent descriptor information 는?
PostgreSQL에서 HV021 에러는 Foreign Data Wrapper(FDW) 가 원격 서버의 테이블 또는 뷰의 컬럼 정보(descriptor)를 로컬 정의와 비교했을 때 불일치가 발생할 때 나타납니다. 즉, 로컬 PostgreSQL 인스턴스의 외부 테이블(Foreign Table) 스키마 정의와 실제 원격 데이터 소스의 스키마가 서로 맞지 않는 상황에서 발생합니다. 이 에러는 주로 원격 테이블의 구조가 변경되었음에도 불구하고 로컬의 Foreign Table 정의가 갱신되지 않았을 때, 혹은 FDW 드라이버가 메타데이터를 올바르게 전달하지 못했을 때 발생합니다.
주요 발생 원인
- 원격 테이블 스키마 변경 후 Foreign Table 미갱신
가장 빈번하게 발생하는 원인입니다. 원격 PostgreSQL, MySQL, Oracle 등의 데이터베이스에서 컬럼이 추가되거나 삭제되거나 데이터 타입이 변경된 경우, 로컬의 Foreign Table 정의는 자동으로 동기화되지 않습니다. 이 불일치 상태에서 FDW가 쿼리를 실행하려 하면 descriptor 정보가 맞지 않아 HV021 에러가 발생합니다.
- FDW 드라이버 버전 불일치 또는 버그
사용 중인 FDW 확장(예: postgres_fdw, mysql_fdw, oracle_fdw 등)의 버전이 PostgreSQL 서버 버전과 호환되지 않거나, 특정 버전에서 알려진 버그가 있을 경우 컬럼 descriptor를 잘못 해석할 수 있습니다. 특히 메이저 버전 업그레이드 후 FDW 확장을 재컴파일하지 않았거나 업데이트하지 않은 경우 이 문제가 자주 나타납니다.
- Foreign Table 컬럼 순서 또는 데이터 타입 불일치
로컬 Foreign Table을 수동으로 정의할 때 컬럼 순서나 데이터 타입을 원격 테이블과 다르게 지정한 경우에도 이 에러가 발생합니다. PostgreSQL FDW는 컬럼 이름뿐만 아니라 순서와 타입에도 민감하게 반응하기 때문에, 단순한 순서 오류만으로도 descriptor 불일치가 유발될 수 있습니다.
해결 방법
원인 1: Foreign Table 재정의 (스키마 재동기화)
원격 테이블의 스키마 변경 이후 로컬 Foreign Table을 삭제하고 다시 생성하는 것이 가장 확실한 방법입니다.
-- 기존 Foreign Table 삭제
DROP FOREIGN TABLE IF EXISTS public.remote_orders;
-- 원격 테이블 스키마에 맞게 재생성
CREATE FOREIGN TABLE public.remote_orders (
order_id BIGINT NOT NULL,
customer_id BIGINT NOT NULL,
order_date TIMESTAMP WITHOUT TIME ZONE,
status VARCHAR(50),
total_amount NUMERIC(15, 2)
)
SERVER remote_pg_server
OPTIONS (schema_name 'public', table_name 'orders');
postgres_fdw를 사용하는 경우, IMPORT FOREIGN SCHEMA를 활용하면 원격 스키마를 자동으로 가져올 수 있어 수동 오류를 줄일 수 있습니다.
-- 기존 Foreign Table을 포함한 스키마 정리
DROP SCHEMA IF EXISTS remote_schema CASCADE;
CREATE SCHEMA remote_schema;
-- 원격 스키마 자동 임포트 (postgres_fdw 전용)
IMPORT FOREIGN SCHEMA public
LIMIT TO (orders, customers, products)
FROM SERVER remote_pg_server
INTO remote_schema;
-- 임포트된 테이블 확인
SELECT foreign_table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'remote_schema'
ORDER BY foreign_table_name, ordinal_position;
원인 2: FDW 확장 업데이트 및 재설치
FDW 확장 버전을 확인하고 최신 버전으로 업데이트합니다.
-- 현재 설치된 확장 버전 확인
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('postgres_fdw', 'mysql_fdw', 'oracle_fdw', 'file_fdw');
-- 확장 업데이트 (가능한 경우)
ALTER EXTENSION postgres_fdw UPDATE;
-- 확장 재설치가 필요한 경우
DROP EXTENSION postgres_fdw CASCADE;
CREATE EXTENSION postgres_fdw;
-- Foreign Server 재생성 예시
CREATE SERVER remote_pg_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'remote-db.example.com', port '5432', dbname 'production');
-- User Mapping 재생성
CREATE USER MAPPING FOR current_user
SERVER remote_pg_server
OPTIONS (user 'fdw_user', password 'secure_password');
원인 3: 컬럼 정의 검증 및 수정
원격 테이블의 실제 컬럼 순서와 타입을 확인하고 로컬 정의와 비교합니다.
-- 원격 서버에서 실제 컬럼 정보 조회 (postgres_fdw 사용 시)
SELECT attname AS column_name,
atttypid::regtype AS data_type,
attnum AS column_order
FROM pg_attribute
WHERE attrelid = 'remote_schema.remote_orders'::regclass
AND attnum > 0
AND NOT attisdropped
ORDER BY attnum;
-- 로컬 Foreign Table 정의 확인
SELECT column_name, data_type, ordinal_position, udt_name
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'remote_orders'
ORDER BY ordinal_position;
-- 컬럼 타입이 불일치하는 경우 ALTER로 수정
ALTER FOREIGN TABLE public.remote_orders
ALTER COLUMN total_amount TYPE NUMERIC(18, 4);
-- 누락된 컬럼 추가
ALTER FOREIGN TABLE public.remote_orders
ADD COLUMN discount_rate NUMERIC(5, 2) OPTIONS (column_name 'discount_rate');
연결 테스트 및 디버깅
-- FDW 연결 상태 및 옵션 확인
SELECT srvname, srvtype, srvversion, srvoptions
FROM pg_foreign_server;
-- Foreign Table 옵션 확인
SELECT foreign_table_schema, foreign_table_name, ftoptions
FROM information_schema.foreign_tables;
-- 간단한 연결 테스트 쿼리 (LIMIT 1로 부하 최소화)
EXPLAIN (VERBOSE, ANALYZE)
SELECT * FROM public.remote_orders LIMIT 1;
예방 방법
- 원격 스키마 변경 시 자동 감지 및 알림 체계 구축
원격 데이터베이스의 DDL 변경이 발생하면 로컬 Foreign Table 정의도 반드시 함께 업데이트해야 합니다. 이를 위해 원격 서버에 DDL 감사 트리거를 설정하거나, CI/CD 파이프라인에 Foreign Table 스키마 검증 스텝을 포함시키는 것이 좋습니다. 아래와 같은 모니터링 쿼리를 정기적으로 실행하여 불일치를 사전에 감지하세요.
“`sql
— 정기 점검용: Foreign Table과 원격 테이블의 컬럼 수 비교 뷰 생성
CREATE OR REPLACE VIEW admin.fdw_schema_health_check AS
SELECT
ft.foreign_table_schema AS local_schema,
ft.foreign_table_name AS local_table,
COUNT(c.column_name) AS local_column_count,
ft.ftoptions AS remote_options
FROM information_schema.foreign_tables ft
JOIN information_schema.columns c
ON c.table_schema = ft.foreign_table_schema
AND c.table_name = ft.foreign_table_name
GROUP BY ft.foreign_table_schema, ft.foreign_table_name, ft.ftoptions
ORDER BY ft.foreign_table_schema, ft.foreign_table_name;
“`
IMPORT FOREIGN SCHEMA사용 자동화 및 주기적 재동기화
수동으로 Foreign Table을 정의하는 대신 IMPORT FOREIGN SCHEMA를 활용하면 스키마 불일치 가능성을 대폭 줄일 수 있습니다. 이 명령을 정기적인 배치 작업(cron job, pg_cron 등)으로 스케줄링하여 원격 스키마 변경 사항을 자동으로 반영하세요.
“`sql
— pg_cron을 활용한 주기적 스키마 재동기화 예시
SELECT cron.schedule(
‘fdw-schema-sync’,
‘0 2 *’, — 매일 새벽 2시 실행
$$
DROP SCHEMA IF EXISTS remote_schema CASCADE;
CREATE SCHEMA remote_schema;
IMPORT FOREIGN SCHEMA public
FROM SERVER remote_pg_server
INTO remote_schema;
$$
);
“`
관련 에러
HV000(fdw_error): FDW 관련 일반 오류.HV021이 특정 descriptor 불일치라면,HV000은 FDW 전반의 포괄적 에러입니다.HV005(fdw_column_name_not_found): Foreign Table의 컬럼 이름이 원격 소스에서 찾을 수 없을 때 발생하며,HV021과 함께 나타나는 경우가 많습니다.HV002(fdw_dynamic_parameter_value_needed): FDW 쿼리 실행 시 필요한 파라미터 값이 누락된 경우 발생합니다.08006(connection_failure): FDW가 원격 서버에 연결 자체를 실패할 때 발생하며, descriptor 오류 전에 선행될 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.