Transaction Guard 관련 사항

Transaction Guard 개요

Oracle Database의 Transaction Guard는 애플리케이션이 예기치 않은 오류(하드웨어 오류, 네트워크 문제 등) 발생 시 트랜잭션의 결과를 알 수 있도록 지원하는 기능입니다. 특히, 클라우드 환경이나 분산 시스템에서 안정적인 운영을 보장하는 데 필수적입니다. Transaction Guard는 애플리케이션이 재시도 시 중복 작업을 방지하고, 트랜잭션의 결과를 안전하게 유지하도록 설계되었습니다.

Transaction Guard의 핵심 기능

  • 멱등성(Idempotency) 보장: 동일한 요청을 여러 번 실행하더라도 결과가 동일하도록 보장합니다.
  • 장애 복구(Failover) 시 안전한 재시도: 장애 발생 후 재시도 시 트랜잭션이 중복 실행되지 않도록 합니다.
  • 자동 및 투명한 트랜잭션 복구: 애플리케이션 코드 변경 없이 트랜잭션 복구를 지원합니다.

Transaction Guard 설정 및 사용 방법

Transaction Guard를 사용하려면 데이터베이스와 애플리케이션 설정을 확인해야 합니다. 아래는 설정 단계와 예시입니다.

1. 데이터베이스 설정 확인

먼저, 데이터베이스가 Transaction Guard를 지원하는지 확인합니다. 12c Release 1 (12.1.0.1) 이상의 버전을 사용해야 합니다.

2. 필요한 권한 부여

Transaction Guard를 사용하려면 애플리케이션 사용자에게 필요한 권한을 부여해야 합니다.

GRANT EXECUTE ON DBMS_APP_CONT.GET_LTXID_OUTCOME TO application_user;

3. 연결 문자열 설정

애플리케이션 연결 문자열에 다음 매개변수를 추가하여 Transaction Guard를 활성화합니다.

(CONNECT_DATA=(SERVICE_NAME=myservice)(RETRY_COUNT=3)(RETRY_DELAY=5)(TRANSPORT_CONNECT_TIMEOUT=10))

4. 애플리케이션 로직 구현

애플리케이션은 오류 발생 시 DBMS_APP_CONT.GET_LTXID_OUTCOME 프로시저를 호출하여 트랜잭션 결과를 확인하고, 필요한 경우 재시도합니다.

DECLARE
    lv_outcome  VARCHAR2(32767);
    lv_status   VARCHAR2(32);
BEGIN
    lv_outcome := DBMS_APP_CONT.GET_LTXID_OUTCOME(p_ltxid => :ltxid);

    IF lv_outcome = 'COMMIT' THEN
        lv_status := 'Success';
    ELSIF lv_outcome = 'ROLLBACK' THEN
        lv_status := 'Failed';
    ELSE
        lv_status := 'Unknown';
    END IF;

    :trans_status := lv_status;
END;
/

예시: 은행 계좌 이체 애플리케이션

다음은 Transaction Guard를 사용하여 은행 계좌 이체 애플리케이션을 안전하게 구현하는 예시입니다.

1. 트랜잭션 시작

계좌 이체 트랜잭션을 시작하고, 고유한 논리적 트랜잭션 ID(LTXID)를 생성합니다.

BEGIN
  DBMS_TRANSACTION.TRANSACTION_ID(ltxid);
  -- LTXID를 테이블에 저장 (선택 사항)
  INSERT INTO transaction_log (tran_id, start_time, status) VALUES (ltxid, SYSTIMESTAMP, 'ACTIVE');
  COMMIT;
END;

2. 계좌 이체 작업 수행

출금 및 입금 작업을 수행합니다.

UPDATE accounts SET balance = balance - transfer_amount WHERE account_id = debit_account;
UPDATE accounts SET balance = balance + transfer_amount WHERE account_id = credit_account;

3. 트랜잭션 완료 및 커밋

트랜잭션을 커밋하고, LTXID를 사용하여 트랜잭션 상태를 업데이트합니다.

BEGIN
    COMMIT;
    -- 상태 업데이트
    UPDATE transaction_log SET status = 'COMMITTED', finish_time = SYSTIMESTAMP WHERE tran_id = ltxid;
    COMMIT;
END;

4. 오류 발생 시 복구 로직

오류가 발생하면 DBMS_APP_CONT.GET_LTXID_OUTCOME을 사용하여 트랜잭션 결과를 확인하고, 필요한 경우 롤백 또는 재시도합니다.

EXCEPTION
    WHEN OTHERS THEN
        -- 트랜잭션 상태 확인
        outcome := DBMS_APP_CONT.GET_LTXID_OUTCOME(ltxid);
        IF outcome = 'COMMIT' THEN
            -- 이미 커밋된 경우, 로깅만 수행
            log_message := 'Transaction already committed';
        ELSIF outcome = 'ROLLBACK' THEN
            -- 이미 롤백된 경우, 로깅만 수행
            log_message := 'Transaction already rolled back';
        ELSE
            -- 알 수 없는 상태, 롤백 수행
            log_message := 'Transaction in unknown state, rolling back';
            ROLLBACK;
        END IF;
        -- 오류 로깅
        INSERT INTO error_log (tran_id, error_message, log_time) VALUES (ltxid, log_message, SYSTIMESTAMP);
        COMMIT;
    END;

실무 팁 및 주의사항

  • LTXID 관리: LTXID는 고유해야 하며, 적절하게 관리되어야 합니다.
  • 타임아웃 설정: 트랜잭션 타임아웃을 적절히 설정하여 장시간 미결정 트랜잭션을 방지합니다.
  • 로깅 및 모니터링: 트랜잭션 상태를 로깅하고, 주기적으로 모니터링하여 오류를 신속하게 감지합니다.
  • 테스트: 다양한 오류 시나리오에서 Transaction Guard의 동작을 테스트합니다.

결론

Transaction Guard는 Oracle Database에서 고가용성 및 데이터 무결성을 보장하는 강력한 도구입니다. 실무에 적용하기 위해선 위에 제시된 단계들을 주의 깊게 따르고, 발생 가능한 모든 시나리오를 고려해야 합니다.

위로 스크롤