2026년 08월 27일 | DBMS Error 가이드
이 글에서 다루는 내용
25001 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
25001 active sql transaction 는?
PostgreSQL 에러 코드 25001 (active_sql_transaction)은 특정 명령어가 활성 트랜잭션 블록 내부에서 실행될 수 없을 때 발생합니다. 일부 PostgreSQL 명령어들은 트랜잭션 블록 밖, 즉 자동 커밋(autocommit) 상태에서만 실행 가능하도록 설계되어 있으며, 이미 BEGIN 또는 START TRANSACTION으로 트랜잭션이 시작된 상태에서 해당 명령어를 실행하면 이 에러가 발생합니다. 실무에서는 주로 VACUUM, CREATE DATABASE, DROP DATABASE, ALTER SYSTEM 같은 명령어를 트랜잭션 블록 안에서 호출할 때 빈번하게 마주치게 됩니다.
주요 발생 원인
1. 트랜잭션 블록 내에서 VACUUM 실행
VACUUM 명령어는 PostgreSQL의 가비지 컬렉션 역할을 담당하는 유지 보수 명령어로, 트랜잭션 블록 내에서는 절대 실행할 수 없습니다. 애플리케이션 코드나 마이그레이션 스크립트에서 BEGIN으로 트랜잭션을 열고 VACUUM을 호출하는 실수가 자주 발생하며, 이는 즉시 25001 에러를 유발합니다.
-- 에러 발생 예시
BEGIN;
INSERT INTO logs (message) VALUES ('start');
VACUUM logs; -- ERROR: 25001 VACUUM cannot run inside a transaction block
2. 트랜잭션 블록 내에서 CREATE DATABASE / DROP DATABASE 실행
CREATE DATABASE와 DROP DATABASE는 데이터베이스 클러스터 전체에 영향을 미치는 DDL 명령어로, 트랜잭션 블록과 함께 사용할 수 없습니다. 특히 자동화된 배포 스크립트나 ORM 프레임워크가 트랜잭션을 자동으로 열어두는 환경에서 데이터베이스 생성/삭제를 시도할 때 이 문제가 자주 발생합니다.
-- 에러 발생 예시
BEGIN;
CREATE DATABASE new_service_db;
-- ERROR: CREATE DATABASE cannot run inside a transaction block
-- SQLSTATE: 25001
3. 트랜잭션 블록 내에서 ALTER SYSTEM 또는 CLUSTER 실행
ALTER SYSTEM은 postgresql.conf 파일을 직접 수정하는 명령어이고, CLUSTER는 테이블을 인덱스 순서로 물리적으로 재정렬하는 명령어입니다. 이 두 명령어 역시 트랜잭션 블록 내에서 실행이 불가능하며, 특히 DBA가 운영 중 파라미터 튜닝을 위해 ALTER SYSTEM을 사용할 때 트랜잭션 컨텍스트를 확인하지 않아 에러가 발생하는 경우가 많습니다.
-- 에러 발생 예시
BEGIN;
SELECT pg_sleep(1); -- 다른 작업 수행
ALTER SYSTEM SET work_mem = '64MB';
-- ERROR: ALTER SYSTEM cannot run inside a transaction block
-- SQLSTATE: 25001
해결 방법
원인 1 해결: VACUUM을 트랜잭션 밖에서 실행
현재 트랜잭션을 먼저 종료한 후 VACUUM을 독립적으로 실행해야 합니다.
-- 잘못된 방법
BEGIN;
VACUUM my_table; -- 에러 발생!
COMMIT;
-- 올바른 방법: 트랜잭션 없이 독립 실행
COMMIT; -- 혹은 ROLLBACK; 으로 기존 트랜잭션 종료
VACUUM ANALYZE my_table;
-- 혹은 psql에서 autocommit 상태 확인 후 바로 실행
\echo :AUTOCOMMIT
VACUUM FULL my_table;
VACUUM (VERBOSE, ANALYZE) my_table;
원인 2 해결: CREATE DATABASE / DROP DATABASE 독립 실행
데이터베이스 생성/삭제는 반드시 트랜잭션 블록 외부에서 실행하고, 자동화 스크립트에서는 AUTOCOMMIT 모드를 명시적으로 활성화해야 합니다.
-- psql에서 명시적으로 autocommit 확인 및 실행
\set AUTOCOMMIT on
CREATE DATABASE new_service_db
WITH OWNER = app_user
ENCODING = 'UTF8'
LC_COLLATE = 'ko_KR.UTF-8'
LC_CTYPE = 'ko_KR.UTF-8'
TEMPLATE = template0;
-- Python psycopg2 예시: autocommit 설정
-- conn.autocommit = True
-- cur.execute("CREATE DATABASE new_service_db")
-- 기존 트랜잭션이 있을 경우 먼저 종료
ROLLBACK; -- 또는 COMMIT;
DROP DATABASE IF EXISTS old_service_db;
원인 3 해결: ALTER SYSTEM 및 CLUSTER 독립 실행
-- 현재 트랜잭션 상태 확인
SELECT pg_current_xact_id_if_assigned();
-- NULL이면 트랜잭션 없음, 값이 있으면 트랜잭션 진행 중
-- 트랜잭션 종료 후 실행
COMMIT; -- 또는 ROLLBACK;
ALTER SYSTEM SET work_mem = '64MB';
ALTER SYSTEM SET shared_buffers = '256MB';
SELECT pg_reload_conf(); -- 변경사항 적용
-- CLUSTER도 동일하게 독립 실행
CLUSTER my_table USING my_table_idx;
-- 트랜잭션 블록 내에서 현재 상태 확인하는 쿼리
SELECT current_setting('transaction_isolation'),
txid_current_if_assigned() IS NOT NULL AS in_transaction;
예방 방법
1. 트랜잭션 불가 명령어 목록을 자동화 스크립트에서 사전 필터링
마이그레이션 스크립트나 배포 파이프라인에서는 VACUUM, CREATE DATABASE, DROP DATABASE, ALTER SYSTEM, CLUSTER, REINDEX DATABASE, CREATE TABLESPACE 등의 명령어가 포함된 경우 트랜잭션 블록을 자동으로 우회하는 로직을 구현해야 합니다. 예를 들어 Flyway나 Liquibase 같은 마이그레이션 도구를 사용할 때는 해당 마이그레이션 파일에 -- notransaction 또는 해당 도구의 비트랜잭션 옵션을 반드시 명시하세요.
-- Flyway에서 non-transactional 마이그레이션 예시 (파일 최상단에 주석 추가)
-- flyway:nonTransactional
VACUUM FULL large_table;
REINDEX DATABASE mydb;
2. 애플리케이션 레벨에서 명시적 트랜잭션 범위 관리
ORM이나 커넥션 풀을 사용하는 환경에서는 묵시적 트랜잭션이 자동으로 열리는 경우가 많습니다. 유지 보수성 명령어(VACUUM, CREATE DATABASE 등)를 실행하기 전에는 반드시 별도의 커넥션을 사용하고 autocommit=True로 설정하는 습관을 들이세요. 또한 정기적인 코드 리뷰에서 트랜잭션 경계를 명확히 검토하는 프로세스를 도입하는 것이 중요합니다.
-- 현재 세션의 트랜잭션 상태를 항상 확인하는 습관
SELECT
pid,
state,
xact_start,
query_start,
query
FROM pg_stat_activity
WHERE pid = pg_backend_pid();
관련 에러
- 25000 (invalid_transaction_state): 25001의 상위 에러 클래스로, 트랜잭션 상태가 잘못된 모든 경우를 포괄합니다.
- 25002 (branch_transaction_already_active): 분산 트랜잭션 환경에서 브랜치 트랜잭션이 이미 활성화되어 있을 때 발생합니다.
- 25008 (held_cursor_requires_same_isolation_level): 커서를 유지하는 트랜잭션에서 격리 수준이 맞지 않을 때 발생합니다.
- 2D000 (invalid_transaction_termination): 잘못된 방법으로 트랜잭션을 종료하려 할 때 발생하며, 25001과 함께 트랜잭션 관리 오류 그룹에 속합니다.
- 55000 (object_not_in_prerequisite_state):
VACUUM FULL이나CLUSTER실행 시 테이블 상태가 올바르지 않을 때 연달아 발생할 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.