PostgreSQL 22022 오류 원인과 해결 방법 완벽 가이드

22022
2026년 08월 09일 | DBMS Error 가이드

이 글에서 다루는 내용

22022 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

22022 indicator overflow 는?

PostgreSQL 에러 코드 22022indicator overflow로, ECPG(Embedded C for PostgreSQL) 또는 외부 클라이언트 라이브러리에서 인디케이터 변수(indicator variable)가 처리할 수 있는 범위를 초과했을 때 발생합니다. 인디케이터 변수는 NULL 값이나 데이터 잘림(truncation) 여부를 클라이언트 측에서 감지하기 위해 사용되는 특수 변수입니다. 주로 임베디드 SQL 환경이나 특정 ODBC/JDBC 드라이버와의 통신 과정에서, 반환된 데이터의 크기 또는 상태 정보가 인디케이터 변수에 할당된 저장 공간을 초과할 때 이 에러가 트리거됩니다.


주요 발생 원인

  • 인디케이터 변수의 데이터 타입 불일치

ECPG 코드에서 인디케이터 변수로 short int 타입을 선언했는데, 실제 반환된 데이터의 길이나 상태 코드가 short int의 최대값(32,767)을 초과하는 경우 이 에러가 발생합니다. 예를 들어, 매우 긴 텍스트 컬럼이나 대용량 TEXT, BYTEA 데이터를 가져올 때 인디케이터 변수가 실제 데이터 크기를 담지 못해 오버플로우가 일어납니다. 인디케이터 변수는 반드시 충분한 크기의 정수형(int 또는 long)으로 선언해야 합니다.

  • 대용량 컬럼 데이터 페치 시 버퍼 크기 부족

VARCHAR, TEXT, BYTEA 등 가변 길이 컬럼에서 수십 킬로바이트 이상의 데이터를 페치(fetch)할 때, 클라이언트 측 호스트 변수(host variable)와 연결된 인디케이터가 실제 데이터 바이트 수를 표현하지 못하는 경우 오버플로우가 발생합니다. 특히 레거시 시스템에서 오래된 ECPG 코드를 그대로 사용하다가 테이블의 데이터 크기가 늘어난 경우에 자주 나타납니다. 이 경우 호스트 변수 자체의 크기와 인디케이터 변수의 타입을 동시에 재검토해야 합니다.

  • NULL 처리 로직에서의 인디케이터 변수 오용

NULL 값을 인디케이터 변수로 감지하는 로직에서, 인디케이터 변수를 올바르게 초기화하지 않거나 잘못된 크기의 변수를 사용할 경우 예상치 못한 오버플로우가 발생할 수 있습니다. 특히 배열 형태의 호스트 변수와 인디케이터 배열을 함께 사용할 때, 배열 크기가 맞지 않으면 메모리 참조 오류와 함께 이 에러가 나타납니다. NULL 처리 시에는 항상 인디케이터 변수를 명시적으로 초기화하는 습관이 필요합니다.


해결 방법

원인 1 해결: 인디케이터 변수 타입을 충분한 크기로 변경

ECPG 코드에서 인디케이터 변수를 short 대신 intlong으로 선언합니다.

-- ECPG C 코드 예시 (잘못된 선언)
-- short ind_col;  <-- short는 최대 32767까지만 표현 가능

-- 올바른 선언
-- int ind_col;

-- PostgreSQL 측에서 컬럼 크기를 확인하는 쿼리
SELECT
    column_name,
    data_type,
    character_maximum_length,
    pg_size_pretty(pg_column_size(column_name::text)) AS estimated_size
FROM
    information_schema.columns
WHERE
    table_name = 'your_table_name'
    AND table_schema = 'public';
-- 실제 테이블에서 대용량 컬럼의 최대 길이를 확인
SELECT
    MAX(octet_length(your_large_column)) AS max_byte_length,
    AVG(octet_length(your_large_column)) AS avg_byte_length,
    COUNT(*) AS total_rows
FROM your_table_name;

원인 2 해결: 대용량 데이터 페치 시 CURSOR와 청크 단위 처리 적용

한 번에 대용량 데이터를 가져오는 대신, 커서(CURSOR)를 사용해 청크 단위로 나눠 처리합니다.

-- 커서를 활용한 대용량 데이터 분할 페치
BEGIN;

DECLARE large_data_cursor CURSOR FOR
    SELECT id, large_text_column
    FROM your_table_name
    WHERE some_condition = true
    ORDER BY id;

-- 1000건씩 나눠 가져오기
FETCH 1000 FROM large_data_cursor;

-- 처리 후 다음 배치
FETCH 1000 FROM large_data_cursor;

CLOSE large_data_cursor;

COMMIT;
-- 대용량 TEXT/BYTEA 컬럼을 substring으로 나눠 처리하는 예시
SELECT
    id,
    substring(large_text_column FROM 1 FOR 8192) AS chunk_1,
    substring(large_text_column FROM 8193 FOR 8192) AS chunk_2,
    octet_length(large_text_column) AS total_bytes
FROM your_table_name
WHERE id = 12345;

원인 3 해결: NULL 인디케이터 변수 명시적 초기화

-- PostgreSQL에서 NULL 포함 여부를 사전에 확인하여 클라이언트 부하 감소
SELECT
    column_name,
    COUNT(*) AS total_count,
    COUNT(your_column) AS non_null_count,
    COUNT(*) - COUNT(your_column) AS null_count,
    ROUND(
        (COUNT(*) - COUNT(your_column))::numeric / COUNT(*) * 100, 2
    ) AS null_percentage
FROM your_table_name
CROSS JOIN LATERAL (SELECT 'your_column') AS col(column_name)
GROUP BY column_name;

-- NULL 값을 COALESCE로 치환하여 인디케이터 변수 사용 자체를 줄이는 방법
SELECT
    id,
    COALESCE(nullable_column, '') AS safe_column,
    COALESCE(numeric_nullable, 0) AS safe_numeric
FROM your_table_name
LIMIT 100;
-- 컬럼 통계 정보를 통해 데이터 분포 사전 파악
SELECT
    attname AS column_name,
    null_frac AS null_fraction,
    avg_width AS avg_byte_width,
    n_distinct
FROM pg_stats
WHERE tablename = 'your_table_name'
    AND schemaname = 'public'
ORDER BY avg_width DESC;

예방 방법

  • ECPG 코드 작성 시 인디케이터 변수 타입 표준화

팀 내 ECPG 코딩 컨벤션에서 인디케이터 변수는 반드시 int 또는 sqlind(PostgreSQL ECPG 전용 타입) 타입으로만 선언하도록 규칙을 수립하세요. shortchar 같은 작은 크기의 타입은 절대 인디케이터 변수로 사용하지 않도록 코드 리뷰 체크리스트에 항목을 추가하고, CI/CD 파이프라인에서 정적 분석 도구로 이를 자동 검증하는 것이 이상적입니다.

“`sql

— 운영 DB에서 큰 컬럼을 가진 테이블 목록을 주기적으로 모니터링

SELECT

schemaname,

tablename,

attname AS column_name,

pg_size_pretty(avg_width::bigint) AS avg_size,

avg_width

FROM pg_stats

WHERE avg_width > 1000

ORDER BY avg_width DESC

LIMIT 20;

“`

  • 대용량 컬럼에 대한 데이터 크기 상한선 정책 수립

운영 테이블의 TEXT, BYTEA, VARCHAR 컬럼에 CHECK 제약 조건이나 트리거를 통해 최대 데이터 크기를 제한하면, 인디케이터 오버플로우 상황 자체를 원천 차단할 수 있습니다. 대용량 바이너리나 문서 데이터는 PostgreSQL 내부에 직접 저장하기보다 외부 오브젝트 스토리지(S3 등)에 저장하고, DB에는 참조 URL이나 키만 저장하는 아키텍처를 권장합니다.

“`sql

— 컬럼 크기 제한 CHECK 제약 조건 추가 예시

ALTER TABLE your_table_name

ADD CONSTRAINT chk_column_size

CHECK (octet_length(your_large_column) <= 65536); -- 64KB 제한

— 기존 데이터 크기 초과 여부 사전 검증

SELECT id, octet_length(your_large_column) AS byte_size

FROM your_table_name

WHERE octet_length(your_large_column) > 65536;

“`


관련 에러

  • 22001 (string_data_right_truncation): 문자열 데이터가 대상 컬럼의 크기를 초과하여 잘릴 때 발생하며, 22022와 함께 데이터 크기 관련 에러 계열에 속합니다.
  • 22003 (numeric_value_out_of_range): 숫자형 데이터가 대상 타입의 범위를 벗어날 때 발생하며, 인디케이터 변수의 숫자 범위 초과 문제와 개념적으로 유사합니다.
  • 22000 (data_exception): 데이터 관련 예외의 부모 에러 클래스로, 22022를 포함한 모든 22xxx 계열 에러의 상위 범주입니다.
  • HV000 (FDW 관련 에러): 외부 데이터 래퍼(Foreign Data Wrapper) 사용 시 원격 서버에서 인디케이터 관련 에러가 전파될 수 있으므로 함께 확인이 필요합니다.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기