2026년 10월 03일 | DBMS Error 가이드
이 글에서 다루는 내용
XX001 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
XX001 data corrupted 는?
PostgreSQL 에러 코드 XX001 (data corrupted)은 데이터베이스 내부의 데이터 구조나 파일이 물리적 또는 논리적으로 손상되었을 때 발생하는 심각한 시스템 에러입니다. 이 에러는 PostgreSQL이 테이블, 인덱스, 또는 시스템 카탈로그를 읽거나 쓰는 과정에서 데이터의 무결성을 확인할 수 없을 때 발생하며, 일반적인 SQL 구문 오류와 달리 단순한 쿼리 수정으로는 해결할 수 없습니다. 이 에러는 데이터 유실로 이어질 수 있는 가장 위험한 PostgreSQL 에러 중 하나로, 즉각적인 조사와 대응이 필요합니다.
주요 발생 원인
1. 하드웨어 장애 및 스토리지 오류
가장 빈번한 원인은 하드웨어 결함입니다. HDD 또는 SSD의 배드섹터, RAID 컨트롤러 오류, 메모리(RAM) 불량 등이 PostgreSQL 데이터 파일에 직접적인 손상을 야기합니다. 특히 쓰기 캐시가 활성화된 스토리지에서 예기치 않은 전원 차단이 발생하면, WAL(Write-Ahead Log)에 기록되지 않은 데이터가 디스크에 잘못 기록되어 심각한 데이터 손상으로 이어집니다. 운영 환경에서는 반드시 UPS(무정전 전원 공급 장치)와 ECC 메모리를 사용하는 것이 권장됩니다.
2. 비정상적인 PostgreSQL 프로세스 종료 및 크래시
PostgreSQL 서버가 비정상적으로 종료되거나 OOM Killer에 의해 강제 종료될 경우, 진행 중이던 트랜잭션의 데이터가 디스크에 불완전하게 기록될 수 있습니다. PostgreSQL은 이런 상황을 대비해 WAL을 사용하지만, WAL 파일 자체가 손상되거나 pg_wal 디렉토리가 훼손된 경우에는 복구가 불가능해집니다. 커널 패닉, 파일시스템 마운트 오류, 또는 SIGKILL 시그널에 의한 강제 종료 후에는 반드시 데이터베이스 무결성 검사를 수행해야 합니다.
3. 파일시스템 및 OS 레벨의 버그 또는 오설정
ext4, XFS 등의 파일시스템이 잘못된 마운트 옵션(예: nobarrier 옵션 사용)으로 설정된 경우, 데이터 쓰기 순서가 보장되지 않아 PostgreSQL 데이터 파일이 손상될 수 있습니다. 또한, NFS와 같은 네트워크 파일시스템 위에 PostgreSQL 데이터 디렉토리를 위치시키는 것은 데이터 손상의 주요 원인이 됩니다. OS 레벨의 버그나 파일시스템 저널링 오류도 이 에러를 유발할 수 있으며, 정기적인 OS 및 드라이버 업데이트가 중요합니다.
해결 방법
Step 1: 손상된 테이블 및 인덱스 식별
우선 손상된 객체를 식별해야 합니다. pg_catalog 시스템 테이블과 VACUUM 명령어를 통해 손상 여부를 1차로 확인합니다.
-- 현재 데이터베이스의 모든 테이블에 대해 기본 검사 수행
-- pg_class를 통해 테이블 목록 조회
SELECT relname, relfilenode, relpages
FROM pg_class
WHERE relkind = 'r'
ORDER BY relname;
-- 특정 테이블에 대해 VACUUM VERBOSE 실행하여 오류 확인
VACUUM VERBOSE your_table_name;
-- 테이블 전체 스캔을 통한 데이터 읽기 테스트
SELECT COUNT(*) FROM your_table_name;
Step 2: pg_dump를 이용한 데이터 추출 시도
데이터가 일부 읽힌다면, 즉시 pg_dump로 백업을 시도합니다.
-- psql 외부 명령어로 실행 (bash 환경)
-- pg_dump --dbname=your_database --file=emergency_backup.sql
-- 특정 테이블만 덤프
-- pg_dump --table=your_table_name --dbname=your_database --file=table_backup.sql
-- 손상된 페이지를 건너뛰는 zero_damaged_pages 설정 활성화
-- postgresql.conf 또는 세션에서 설정
SET zero_damaged_pages = on;
-- 이후 손상된 테이블 재스캔
SELECT * FROM your_table_name LIMIT 100;
Step 3: 손상된 인덱스 재생성
인덱스 손상의 경우, 인덱스를 삭제하고 재생성하여 문제를 해결할 수 있습니다.
-- 손상된 인덱스 확인
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'your_table_name';
-- 기존 인덱스 삭제
DROP INDEX CONCURRENTLY IF EXISTS your_index_name;
-- 인덱스 재생성
CREATE INDEX CONCURRENTLY your_index_name
ON your_table_name (your_column_name);
-- 인덱스 유효성 검사
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes
WHERE tablename = 'your_table_name';
Step 4: amcheck 확장 모듈을 이용한 정밀 검사
PostgreSQL 10 이상에서는 amcheck 확장을 사용하여 B-tree 인덱스의 논리적 일관성을 검사할 수 있습니다.
-- amcheck 확장 설치
CREATE EXTENSION IF NOT EXISTS amcheck;
-- B-tree 인덱스 구조 검사
SELECT bt_index_check(index => 'your_index_name'::regclass);
-- 힙(테이블 데이터)과 인덱스 함께 교차 검증
SELECT bt_index_parent_check(
index => 'your_index_name'::regclass,
heapallindexed => true
);
Step 5: 백업에서 복구
위 방법으로도 해결이 불가능할 경우, 가장 안전한 방법은 검증된 백업에서 복구하는 것입니다.
-- 복구 후 데이터 무결성 확인
-- pg_restore 사용 예시 (bash)
-- pg_restore --dbname=your_database --verbose backup_file.dump
-- 복구된 테이블의 행 수 검증
SELECT
schemaname,
tablename,
n_live_tup AS live_rows,
n_dead_tup AS dead_rows
FROM pg_stat_user_tables
WHERE tablename = 'your_table_name';
-- 기본 제약 조건 확인
SELECT conname, contype, consrc
FROM pg_constraint
WHERE conrelid = 'your_table_name'::regclass;
예방 방법
1. 정기적인 백업 및 무결성 검증 자동화
단순히 백업을 수행하는 것만으로는 부족합니다. 백업 파일 자체가 올바른지 정기적으로 검증하는 프로세스를 반드시 구축해야 합니다. pg_dump 또는 pgBackRest, Barman과 같은 전문 백업 도구를 사용하고, 복구 테스트(Restore Drill)를 분기마다 실행하는 것이 Best Practice입니다.
-- 정기적으로 amcheck를 사용한 인덱스 전체 검사 스크립트
CREATE EXTENSION IF NOT EXISTS amcheck;
-- 모든 B-tree 인덱스에 대해 자동 검사 (함수화)
DO $$
DECLARE
r RECORD;
BEGIN
FOR r IN
SELECT indexrelid::regclass AS index_name
FROM pg_index i
JOIN pg_class c ON c.oid = i.indexrelid
JOIN pg_am am ON am.oid = c.relam
WHERE am.amname = 'btree'
LOOP
BEGIN
PERFORM bt_index_check(r.index_name);
RAISE NOTICE 'Index % is OK', r.index_name;
EXCEPTION WHEN OTHERS THEN
RAISE WARNING 'Index % has issues: %', r.index_name, SQLERRM;
END;
END LOOP;
END;
$$;
2. 체크섬 활성화 및 모니터링 강화
PostgreSQL 12 이상에서는 클러스터 초기화 시 데이터 체크섬을 활성화하거나, pg_checksums 도구로 기존 클러스터에 체크섬을 추가할 수 있습니다. 체크섬이 활성화되면 PostgreSQL이 데이터 페이지를 읽을 때마다 무결성을 자동으로 검증하여 조기에 손상을 탐지할 수 있습니다.
-- 현재 데이터 체크섬 활성화 여부 확인
SHOW data_checksums;
-- 체크섬 오류 발생 횟수 모니터링 (PostgreSQL 14+)
SELECT checksum_failures, checksum_last_failure
FROM pg_stat_database
WHERE datname = current_database();
-- 체크섬 실패 탐지 시 알림을 위한 모니터링 쿼리
SELECT
datname,
checksum_failures,
checksum_last_failure
FROM pg_stat_database
WHERE checksum_failures > 0;
관련 에러
- XX002 (index corrupted): XX001과 유사하지만, 테이블 데이터가 아닌 인덱스 구조가 손상된 경우에 발생합니다. 인덱스 재생성(
REINDEX)으로 해결 가능한 경우가 많습니다. - 58P01 (undefined_file): 데이터 파일 자체가 존재하지 않을 때 발생하며, 파일 시스템 레벨의 삭제 또는 손상과 관련이 있습니다.
- 53100 (disk_full): 디스크 공간 부족으로 인해 데이터가 정상적으로 기록되지 못할 경우, 이후 XX001 에러로 이어질 수 있습니다.
- 57P03 (cannot_connect_now): 심각한 데이터 손상 발생 시 PostgreSQL이 기동 자체를 거부하며 이 에러가 동반되기도 합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.