2026년 07월 17일 | DBMS Error 가이드
이 글에서 다루는 내용
55006 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
55006 object in use 는?
PostgreSQL 에러 코드 55006(object_in_use)은 특정 데이터베이스 객체(테이블, 인덱스, 데이터베이스 등)가 현재 다른 세션이나 프로세스에 의해 사용 중인 상태일 때 발생합니다. 대표적으로 DROP DATABASE 명령을 실행할 때 해당 데이터베이스에 아직 활성 연결이 존재하거나, 특정 테이블스페이스 또는 인덱스가 다른 작업에 의해 점유된 경우에 이 에러가 발생합니다. 이 에러는 PostgreSQL이 데이터 무결성과 동시성을 보호하기 위해 의도적으로 발생시키는 충돌 방지 메커니즘의 일부입니다.
주요 발생 원인
1. 활성 연결이 존재하는 데이터베이스를 DROP하려는 시도
가장 흔한 원인으로, DROP DATABASE 명령 실행 시 해당 데이터베이스에 하나 이상의 활성 클라이언트 연결이 남아 있을 때 발생합니다. PostgreSQL은 데이터 손상 방지를 위해 연결이 완전히 종료될 때까지 데이터베이스 삭제를 허용하지 않으며, 애플리케이션 서버의 커넥션 풀이나 모니터링 도구가 백그라운드에서 연결을 유지하고 있는 경우 특히 자주 발생합니다.
2. 사용 중인 테이블스페이스 변경 또는 삭제
테이블스페이스(TABLESPACE)에 아직 테이블, 인덱스 등의 객체가 존재하거나, 해당 테이블스페이스를 참조하는 활성 트랜잭션이 있을 때 DROP TABLESPACE 명령이 실패합니다. 테이블스페이스는 물리적인 스토리지 경로와 직접 연결되어 있기 때문에, 논리적으로 완전히 비워지지 않은 상태에서 삭제를 시도하면 이 에러가 발생합니다.
3. REINDEX 또는 VACUUM 중인 인덱스/테이블에 대한 충돌
REINDEX CONCURRENTLY 또는 VACUUM 작업이 진행 중인 테이블이나 인덱스에 대해 DDL 작업(예: DROP INDEX, ALTER TABLE)을 동시에 실행하려 할 때 에러가 발생할 수 있습니다. 이러한 유지보수 작업은 내부적으로 잠금(lock)을 획득하며, 충돌하는 명령이 들어오면 PostgreSQL은 즉시 에러를 반환하거나 잠금 대기 상태에 빠집니다.
해결 방법
원인 1 해결: 활성 연결 종료 후 DROP DATABASE
먼저 해당 데이터베이스에 연결된 세션을 확인하고 강제 종료합니다.
-- 현재 데이터베이스에 연결된 활성 세션 확인
SELECT pid, usename, application_name, client_addr, state, query_start
FROM pg_stat_activity
WHERE datname = 'target_database_name';
-- 특정 데이터베이스의 모든 연결 강제 종료 (PostgreSQL 9.2+)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'target_database_name'
AND pid <> pg_backend_pid();
-- 연결 종료 확인 후 데이터베이스 삭제
DROP DATABASE target_database_name;
PostgreSQL 13 이상에서는 WITH (FORCE) 옵션을 사용하면 연결을 자동으로 종료하고 삭제할 수 있습니다.
-- PostgreSQL 13+ 에서 강제 삭제
DROP DATABASE target_database_name WITH (FORCE);
원인 2 해결: 테이블스페이스 비우기 후 삭제
테이블스페이스를 삭제하기 전에 해당 테이블스페이스에 남아 있는 객체를 먼저 확인하고 이동시킵니다.
-- 테이블스페이스에 남아 있는 객체 확인
SELECT schemaname, tablename, tablespace
FROM pg_tables
WHERE tablespace = 'my_tablespace';
-- 인덱스 확인
SELECT indexname, tablespace
FROM pg_indexes
WHERE tablespace = 'my_tablespace';
-- 테이블을 기본 테이블스페이스로 이동
ALTER TABLE my_schema.my_table SET TABLESPACE pg_default;
-- 인덱스를 기본 테이블스페이스로 이동
ALTER INDEX my_schema.my_index SET TABLESPACE pg_default;
-- 모든 객체 이동 후 테이블스페이스 삭제
DROP TABLESPACE my_tablespace;
원인 3 해결: 유지보수 작업 완료 후 DDL 실행
현재 실행 중인 REINDEX 또는 VACUUM 작업을 확인하고 완료될 때까지 기다리거나 취소합니다.
-- 현재 실행 중인 쿼리 및 잠금 상태 확인
SELECT pid, query, state, wait_event_type, wait_event, now() - query_start AS duration
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;
-- 잠금 충돌 확인
SELECT
blocked.pid AS blocked_pid,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.query AS blocking_query
FROM pg_stat_activity AS blocked
JOIN pg_stat_activity AS blocking
ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
WHERE blocked.cardinality(pg_blocking_pids(blocked.pid)) > 0;
-- 필요시 유지보수 쿼리 강제 취소 (데이터 안전)
SELECT pg_cancel_backend(pid)
FROM pg_stat_activity
WHERE query ILIKE '%REINDEX%' OR query ILIKE '%VACUUM%';
-- 즉각 종료가 필요한 경우 (주의 필요)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE query ILIKE '%REINDEX%';
예방 방법
1. 데이터베이스 삭제 전 연결 차단 자동화 스크립트 운영
운영 환경에서 데이터베이스를 삭제해야 하는 경우, 삭제 전 신규 연결을 차단하고 기존 연결을 안전하게 종료하는 표준 절차를 마련해야 합니다. 아래와 같이 pg_hba.conf 갱신 또는 REVOKE CONNECT 명령으로 신규 접속을 막은 후 기존 세션을 정리하는 절차를 자동화하면 55006 에러를 예방할 수 있습니다.
-- 신규 연결 차단
REVOKE CONNECT ON DATABASE target_database_name FROM PUBLIC;
-- 기존 연결 종료
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'target_database_name'
AND pid <> pg_backend_pid();
-- 이후 DROP DATABASE 실행
DROP DATABASE target_database_name;
2. 유지보수 작업 시간대 분리 및 잠금 타임아웃 설정
REINDEX, VACUUM FULL 등 잠금을 요구하는 유지보수 작업은 트래픽이 적은 시간대에 수행하고, lock_timeout 파라미터를 설정하여 장시간 잠금 대기로 인한 장애를 예방합니다. 세션 단위 또는 트랜잭션 단위로 타임아웃을 설정하면 예기치 않은 55006 및 잠금 관련 에러를 최소화할 수 있습니다.
-- 세션 단위 잠금 타임아웃 설정 (5초)
SET lock_timeout = '5s';
-- 또는 특정 작업에만 적용
BEGIN;
SET LOCAL lock_timeout = '3s';
REINDEX INDEX CONCURRENTLY my_index;
COMMIT;
관련 에러
- 55000 (
object_not_in_prerequisite_state): 객체가 요청된 작업을 수행하기에 적합한 상태가 아닐 때 발생하며, 55006과 유사하게 객체 상태 관련 에러입니다. - 55P03 (
lock_not_available):NOWAIT옵션 사용 시 즉시 잠금을 획득하지 못할 때 발생하며, 55006과 함께 잠금 경합 상황에서 자주 함께 발생합니다. - 57P01 (
admin_shutdown): 관리자에 의해 강제 연결 종료가 발생할 때 나타나며, 연결 정리 과정에서 연관될 수 있습니다. - 40P01 (
deadlock_detected): 데드락 상황에서 발생하며, 복수의 세션이 서로의 잠금을 기다릴 때 55006과 유사한 맥락에서 나타납니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.