2026년 08월 29일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-06512 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-06512 at string line number 는?
ORA-06512는 Oracle PL/SQL 실행 중 런타임 오류가 발생했을 때, 해당 오류가 어느 위치(프로그램 단위 및 줄 번호)에서 발생했는지를 추적(traceback)하기 위해 Oracle이 자동으로 스택에 추가하는 보조 메시지입니다. 즉, ORA-06512 자체가 독립적인 오류를 나타내는 것이 아니라, 오류의 근본 원인이 된 다른 ORA 에러(예: ORA-01403, ORA-20001 등)와 함께 콜 스택 정보를 제공하는 역할을 합니다. 실무에서는 대부분 RAISE 문이나 RAISE_APPLICATION_ERROR, 혹은 예외 처리 미흡으로 인해 상위 블록으로 예외가 전파될 때 이 메시지가 동반됩니다.
주요 발생 원인
1. RAISE_APPLICATION_ERROR 또는 RAISE를 통한 사용자 정의 예외 발생
개발자가 비즈니스 로직 검증을 위해 RAISE_APPLICATION_ERROR(-20001, '메시지') 또는 RAISE를 명시적으로 호출할 때, Oracle은 ORA-06512와 함께 해당 줄 번호를 스택에 쌓습니다. 프로시저 → 함수 → 패키지 등 여러 단계의 호출 체인이 있을 경우 각 레이어마다 ORA-06512가 반복 출력되어 오류 추적이 복잡해 보일 수 있습니다.
2. 처리되지 않은 런타임 예외(Unhandled Runtime Exception)
NO_DATA_FOUND, TOO_MANY_ROWS, ZERO_DIVIDE 등 Oracle 내장 예외가 발생했음에도 불구하고 해당 블록에 적절한 EXCEPTION 핸들러가 없을 때, 예외는 상위 호출자로 전파되면서 각 전파 단계에서 ORA-06512 메시지가 누적됩니다. 특히 중첩 프로시저 구조에서 예외 핸들러를 가장 내부 블록에만 배치하거나, 아예 생략한 경우 실무에서 빈번하게 발생합니다.
3. 잘못된 데이터 타입 변환 또는 제약 조건 위반
PL/SQL 내부에서 DML(INSERT, UPDATE 등)을 수행할 때 NOT NULL 제약, UNIQUE 제약, CHECK 제약 등을 위반하거나, 숫자형 컬럼에 문자를 삽입하는 등의 묵시적 변환 오류가 발생하면 SQL 엔진이 ORA 에러를 던지고, PL/SQL 엔진은 이를 ORA-06512와 함께 호출 스택으로 전달합니다. 이 경우 근본 원인 에러(예: ORA-00001 unique constraint violated)를 함께 확인해야 합니다.
해결 방법
원인 1: 사용자 정의 예외 처리
오류 메시지의 스택을 위에서부터 순서대로 읽어 실제 발생 지점(가장 마지막 ORA-06512 줄)을 확인한 뒤, 해당 코드를 점검합니다.
-- 문제가 되는 코드 예시
CREATE OR REPLACE PROCEDURE check_salary(p_emp_id IN NUMBER) IS
v_salary NUMBER;
BEGIN
SELECT salary INTO v_salary FROM employees WHERE employee_id = p_emp_id;
IF v_salary < 0 THEN
-- 이 줄에서 ORA-06512 발생
RAISE_APPLICATION_ERROR(-20001, '급여는 음수일 수 없습니다: ' || p_emp_id);
END IF;
END;
/
-- 호출부에서 예외를 포착하는 올바른 처리 방법
BEGIN
check_salary(100);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('오류 코드: ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('오류 메시지: ' || SQLERRM);
-- 필요 시 로그 테이블에 기록
INSERT INTO error_log (err_code, err_msg, log_date)
VALUES (SQLCODE, SQLERRM, SYSDATE);
COMMIT;
END;
/
원인 2: 처리되지 않은 런타임 예외 처리
모든 PL/SQL 블록에 EXCEPTION 섹션을 추가하고, 예상 가능한 예외를 명시적으로 처리합니다.
CREATE OR REPLACE PROCEDURE get_employee_info(p_emp_id IN NUMBER) IS
v_name VARCHAR2(100);
v_dept_id NUMBER;
BEGIN
SELECT first_name || ' ' || last_name, department_id
INTO v_name, v_dept_id
FROM employees
WHERE employee_id = p_emp_id;
DBMS_OUTPUT.PUT_LINE('직원: ' || v_name || ', 부서: ' || v_dept_id);
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- ORA-01403 방지: 데이터 없음을 명확히 처리
DBMS_OUTPUT.PUT_LINE('사원번호 ' || p_emp_id || '에 해당하는 직원이 없습니다.');
WHEN TOO_MANY_ROWS THEN
-- ORA-01422 방지: 복수 행 반환 처리
DBMS_OUTPUT.PUT_LINE('복수의 데이터가 반환되었습니다. 조건을 확인하세요.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('예상치 못한 오류: ' || SQLERRM);
RAISE; -- 필요 시 상위로 재전파
END;
/
원인 3: 데이터 타입 및 제약 조건 위반 처리
DML 수행 전 데이터 유효성을 검증하고, 제약 조건 위반을 명시적으로 처리합니다.
CREATE OR REPLACE PROCEDURE insert_product(
p_product_id IN NUMBER,
p_product_name IN VARCHAR2,
p_price IN NUMBER
) IS
BEGIN
-- 사전 유효성 검사
IF p_product_name IS NULL THEN
RAISE_APPLICATION_ERROR(-20010, '상품명은 필수 입력 항목입니다.');
END IF;
IF p_price < 0 THEN
RAISE_APPLICATION_ERROR(-20011, '가격은 0 이상이어야 합니다.');
END IF;
INSERT INTO products (product_id, product_name, price)
VALUES (p_product_id, p_product_name, p_price);
COMMIT;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- ORA-00001: unique constraint violated
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('이미 존재하는 상품 ID입니다: ' || p_product_id);
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('삽입 오류: ' || SQLCODE || ' - ' || SQLERRM);
RAISE;
END;
/
ORA-06512 스택 추적 분석 방법
-- DBMS_UTILITY.FORMAT_ERROR_BACKTRACE를 활용한 정밀 스택 추적
CREATE OR REPLACE PROCEDURE outer_proc IS
BEGIN
inner_proc; -- inner_proc에서 예외 발생 시
EXCEPTION
WHEN OTHERS THEN
-- FORMAT_ERROR_BACKTRACE는 ORA-06512 스택을 문자열로 반환
DBMS_OUTPUT.PUT_LINE('=== 오류 발생 위치 추적 ===');
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
DBMS_OUTPUT.PUT_LINE('=== 오류 메시지 ===');
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);
END;
/
예방 방법
1. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE를 활용한 체계적 오류 로깅
모든 PL/SQL 프로그램의 최상위 EXCEPTION 핸들러에서 DBMS_UTILITY.FORMAT_ERROR_BACKTRACE와 DBMS_UTILITY.FORMAT_ERROR_STACK을 조합하여 오류 발생 위치와 전파 경로를 로그 테이블에 기록하는 공통 오류 처리 패키지를 구현하세요. 이를 통해 ORA-06512 스택이 길어지더라도 근본 원인을 신속하게 추적할 수 있으며, 운영 환경에서의 장애 대응 시간을 크게 단축할 수 있습니다.
-- 공통 오류 처리 패키지 예시
CREATE OR REPLACE PACKAGE error_handler AS
PROCEDURE log_error(p_module IN VARCHAR2, p_action IN VARCHAR2);
END error_handler;
/
CREATE OR REPLACE PACKAGE BODY error_handler AS
PROCEDURE log_error(p_module IN VARCHAR2, p_action IN VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO app_error_log (
log_id, module_name, action_name,
error_code, error_message, backtrace, log_date
) VALUES (
app_error_log_seq.NEXTVAL,
p_module, p_action,
SQLCODE, SQLERRM,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,
SYSTIMESTAMP
);
COMMIT;
END log_error;
END error_handler;
/
2. 표준화된 PL/SQL 코딩 가이드라인 수립 및 코드 리뷰 도입
팀 전체가 따르는 PL/SQL 예외 처리 표준(모든 프로시저/함수에 EXCEPTION 절 필수, WHEN OTHERS만 단독 사용 금지, RAISE 또는 로그 없이 예외 무시 금지 등)을 문서화하고 코드 리뷰 체크리스트에 포함시키세요. 또한 Oracle SQL Developer나 PL/SQL Developer의 정적 분석 기능, 또는 별도의 정적 분석 도구(예: Trivadis PL/SQL Cop)를 CI/CD 파이프라인에 통합하면 배포 전 단계에서 누락된 예외 처리를 자동으로 감지할 수 있습니다.
관련 에러
- ORA-06511: PL/SQL: cursor already open — 커서 관련 예외가 전파될 때 ORA-06512와 함께 출력됩니다.
- ORA-01403: no data found — SELECT INTO 구문에서 데이터가 없을 때 가장 흔히 ORA-06512를 동반하는 에러입니다.
- ORA-01422: exact fetch returns more than requested number of rows — SELECT INTO에서 복수 행 반환 시 발생합니다.
- ORA-00001: unique constraint violated — DML 실행 중 제약 위반으로 ORA-06512가 발생하는 대표적 케이스입니다.
- ORA-06510: PL/SQL: unhandled user-defined exception — 사용자 정의 예외를 처리하지 않았을 때 ORA-06512와 함께 나타납니다.
- ORA-20000 ~ ORA-20999: RAISE_APPLICATION_ERROR로 발생시키는 사용자 정의 에러 범위로, ORA-06512와 항상 쌍으로 등장합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.