2026년 08월 04일 | DBMS Error 가이드
이 글에서 다루는 내용
08007 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
08007 transaction resolution unknown 는?
PostgreSQL 에러 코드 08007 (transaction_resolution_unknown)은 분산 트랜잭션 또는 Two-Phase Commit(2PC) 환경에서 트랜잭션의 최종 커밋 또는 롤백 여부를 서버가 확정할 수 없는 상태일 때 발생합니다. 주로 네트워크 단절, 서버 크래시, 또는 연결 장애로 인해 Prepared Transaction의 결과를 알 수 없는 상황에서 반환되는 에러입니다. 이 에러는 데이터 일관성 문제로 직결될 수 있기 때문에 DBA 입장에서 즉각적인 점검과 조치가 필요한 심각한 에러 중 하나입니다.
주요 발생 원인
1. Two-Phase Commit(2PC) 중 연결 장애
Two-Phase Commit 프로토콜에서 PREPARE TRANSACTION 이후 코디네이터(Coordinator)와 PostgreSQL 서버 간 네트워크가 끊기거나 코디네이터가 다운되면, 해당 Prepared Transaction은 커밋도 롤백도 되지 않은 불확실한 상태(in-doubt transaction)로 남게 됩니다. 이 상태에서 클라이언트가 트랜잭션 결과를 재조회하면 08007 에러가 발생할 수 있습니다. 특히 분산 데이터베이스 미들웨어(PgBouncer, Pgpool-II 등)를 사용하는 환경에서 빈번하게 나타납니다.
2. PostgreSQL 서버 비정상 종료 및 복구 중 Prepared Transaction 잔류
서버가 갑작스럽게 크래시되거나 pg_ctl stop -m immediate 명령으로 강제 종료된 경우, WAL에는 PREPARE TRANSACTION이 기록되었지만 COMMIT PREPARED 또는 ROLLBACK PREPARED는 기록되지 않은 상태가 생길 수 있습니다. 이 경우 서버 재기동 후에도 해당 트랜잭션은 pg_prepared_xacts 뷰에 Orphan 상태로 남아 있으며, 이를 처리하지 않으면 잠금(Lock) 보유로 인해 다른 쿼리가 블로킹되고 08007 유형의 불확실성 에러가 보고될 수 있습니다.
3. 외부 트랜잭션 관리자(XA Transaction) 오동작
Java의 JTA(Java Transaction API)나 .NET의 System.Transactions 같은 외부 트랜잭션 관리자가 PostgreSQL의 XA 프로토콜을 통해 분산 트랜잭션을 조율하는 도중, 관리자 자체의 버그 또는 타임아웃 정책 문제로 인해 COMMIT PREPARED 또는 ROLLBACK PREPARED 명령을 정상적으로 전달하지 못할 수 있습니다. 이로 인해 PostgreSQL 내부에는 Prepared Transaction이 미결 상태로 쌓이게 되고, 결국 트랜잭션 해결 불가 상태가 발생하게 됩니다.
해결 방법
1. 현재 미결(In-doubt) Prepared Transaction 확인
먼저 시스템에 남아 있는 Prepared Transaction 목록을 조회합니다.
-- 미결 Prepared Transaction 전체 조회
SELECT
gid,
prepared,
owner,
database,
transaction AS xid
FROM pg_prepared_xacts
ORDER BY prepared ASC;
오래된 Prepared Transaction이 있다면 즉시 처리 대상입니다. prepared 컬럼의 타임스탬프가 오래될수록 위험도가 높습니다.
2. 불확실한 Prepared Transaction 강제 커밋 또는 롤백
코디네이터 측 로그를 확인하여 해당 GID(Global Transaction ID)가 커밋되어야 하는지 롤백되어야 하는지 판단한 뒤 처리합니다.
-- 커밋이 확정된 경우
COMMIT PREPARED 'your_transaction_gid';
-- 롤백이 필요한 경우
ROLLBACK PREPARED 'your_transaction_gid';
> ⚠️ 주의: 이 작업은 반드시 코디네이터 로그나 외부 트랜잭션 관리자의 상태를 확인한 후에 수행해야 합니다. 잘못된 결정은 데이터 불일치를 초래할 수 있습니다.
3. Superuser 권한으로 타인 소유 Prepared Transaction 처리
다른 사용자가 생성한 Prepared Transaction을 처리해야 할 경우, Superuser 계정으로 접속하여 처리합니다.
-- superuser로 타 소유자의 prepared transaction 롤백
SET ROLE postgres;
ROLLBACK PREPARED 'distributed_txn_20240601_001';
4. 오래된 Prepared Transaction 자동 감지 쿼리 (모니터링용)
-- 10분 이상 미결 상태인 Prepared Transaction 감지
SELECT
gid,
owner,
database,
EXTRACT(EPOCH FROM (NOW() - prepared)) AS seconds_pending,
prepared
FROM pg_prepared_xacts
WHERE prepared < NOW() - INTERVAL '10 minutes'
ORDER BY prepared ASC;
이 쿼리를 cron이나 pgAgent를 통해 주기적으로 실행하고 알림을 설정하면 조기에 문제를 탐지할 수 있습니다.
5. 잠금 충돌 확인 및 해소
미결 Prepared Transaction이 보유한 잠금으로 인한 블로킹 여부 확인:
-- Prepared Transaction이 보유한 잠금 확인
SELECT
l.locktype,
l.relation::regclass AS table_name,
l.mode,
l.granted,
p.gid AS prepared_gid
FROM pg_locks l
JOIN pg_prepared_xacts p
ON l.transactionid = p.transaction
WHERE l.granted = true;
예방 방법
1. max_prepared_transactions 설정과 모니터링 자동화
postgresql.conf에서 max_prepared_transactions 값을 실제 사용량에 맞게 적절히 설정하고, Prometheus + pg_stat_activity 또는 Zabbix 같은 모니터링 도구를 활용하여 pg_prepared_xacts 뷰의 레코드 수가 임계치를 초과할 경우 즉시 알림을 받도록 구성합니다. 2PC를 실제로 사용하지 않는다면 max_prepared_transactions = 0으로 설정하여 아예 비활성화하는 것이 가장 안전한 방법입니다.
-- 현재 설정값 확인
SHOW max_prepared_transactions;
-- postgresql.conf 설정 예시 (2PC 미사용 시)
-- max_prepared_transactions = 0
2. 코디네이터 장애 대비 복구 절차 문서화 및 정기 훈련
Two-Phase Commit을 사용하는 시스템이라면 코디네이터 장애 발생 시 In-doubt Transaction을 어떻게 해결할지에 대한 명확한 복구 절차(Runbook)를 문서화해야 합니다. 정기적으로 장애 시나리오를 시뮬레이션하고, 관련 담당자가 COMMIT PREPARED / ROLLBACK PREPARED 명령을 신속하게 실행할 수 있도록 훈련하는 것이 중요합니다. 또한 외부 트랜잭션 관리자의 타임아웃 설정을 PostgreSQL의 lock_timeout, statement_timeout과 일치시켜 불일치 상황이 생기지 않도록 해야 합니다.
관련 에러
- 08000 (connection_exception): 일반적인 연결 오류로, 08007 발생 직전에 함께 나타나는 경우가 많습니다.
- 08003 (connection_does_not_exist): 연결이 존재하지 않을 때 발생하며, 2PC 코디네이터 연결 단절 상황에서 동반 발생할 수 있습니다.
- 08006 (connection_failure): 서버와의 연결 자체가 실패한 경우로, 네트워크 장애 시 08007과 함께 보고될 수 있습니다.
- 40001 (serialization_failure) / 40P01 (deadlock_detected): 분산 트랜잭션 환경에서 2PC와 함께 발생할 수 있는 트랜잭션 충돌 관련 에러입니다.
- XX001 (data_corrupted): 심각한 서버 크래시 후 복구 과정에서 08007과 함께 나타날 수 있는 데이터 손상 관련 에러입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.