테마
감사팀 요구(2022)에 따라 정산 금액이 바뀌면 바꾼 사람과 시각, 바뀌기 전과 뒤의 금액을 감사 테이블에 남긴다. 개발팀은 T_ORD_STLM에 행 트리거를 달고, 감사 기록이 정산 쪽 오류에 휩쓸려 사라지지 않게 자율 트랜잭션 프로시저로 기록하게 했다.
지난달 말 「PG 수수료 정정」 배치가 이번 달 정산 10만 건의 금액을 고친 뒤, 합계가 PG사 정산 파일과 달라 ROLLBACK했다. 다음 날 고친 파일로 다시 돌려 성공했다. 분기 대조에서 감사팀이 물었다. "감사 기록을 이어 보면 10만 건이 중간에 끊겨요. 바뀐 적 없는 금액이 기록에 있어요." 박팀장은 감사 요구를 그대로 지키는 설계를 안끼리 비교해 정해 달라고 했다.
T_ORD_STLM 정산: 이번 달 100,000행 · 640블록 · PK_T_ORD_STLM (STLM_SEQ) · STLM_AMT NUMBER(10) NOT NULLT_STLM_AUD 정산 감사(이 문제용): AUD_SEQ(시퀀스 SQ_STLM_AUD) · STLM_SEQ · OLD_AMT · NEW_AMT · AUD_DT · AUD_USER · AUD_PGM · PK (AUD_SEQ) · 2022년부터 412,300행NEW_AMT와 다음 기록의 OLD_AMT가 같은지, 마지막 NEW_AMT가 지금 금액과 같은지 대조한다.CREATE OR REPLACE PROCEDURE P_AUD_WRITE(p_seq NUMBER, p_old NUMBER, p_new NUMBER) IS
PRAGMA AUTONOMOUS_TRANSACTION; -- 감사 기록이 정산 쪽 오류에 휩쓸려 사라지지 않게 (2022)
BEGIN
INSERT INTO T_STLM_AUD (AUD_SEQ, STLM_SEQ, OLD_AMT, NEW_AMT, AUD_DT, AUD_USER, AUD_PGM)
VALUES (SQ_STLM_AUD.NEXTVAL, p_seq, p_old, p_new, SYSDATE, USER, SYS_CONTEXT('USERENV', 'MODULE'));
COMMIT;
END;
/
CREATE OR REPLACE TRIGGER TRG_STLM_AUD
AFTER UPDATE OF STLM_AMT ON T_ORD_STLM
FOR EACH ROW
WHEN (NEW.STLM_AMT <> OLD.STLM_AMT)
BEGIN
P_AUD_WRITE(:OLD.STLM_SEQ, :OLD.STLM_AMT, :NEW.STLM_AMT);
END;
/
-- 월말 PG 수수료 정정 배치
PROCEDURE P_PG_FEE_FIX(p_rate NUMBER, p_pg_total NUMBER) IS
v_total NUMBER;
BEGIN
UPDATE T_ORD_STLM SET STLM_AMT = ROUND(STLM_AMT * p_rate);
SELECT SUM(STLM_AMT) INTO v_total FROM T_ORD_STLM;
IF v_total <> p_pg_total THEN
ROLLBACK; -- PG사 합계와 다르면 통째로 되돌린다
RAISE_APPLICATION_ERROR(-20031, 'PG 합계 불일치 ' || v_total || ' / ' || p_pg_total);
END IF;
COMMIT;
END;
[지난달 말 — 정정 1차 (PG 합계 불일치로 ROLLBACK)]
경과 12.1 초 · user commits 100,000 · redo size 98.2 MB
T_ORD_STLM : 바뀐 행 0 (전부 되돌아감) · T_STLM_AUD : +100,000행
[다음 날 — 정정 2차 (고친 파일로 성공)]
경과 12.5 초 · user commits 100,001 · T_STLM_AUD : +100,000행
[감사팀 분기 대조]
앞 기록의 NEW_AMT ≠ 다음 기록의 OLD_AMT 인 정산 : 100,000건 (1차 기록의 NEW_AMT는 한 번도 존재하지 않은 금액)
[TKPROF — 2차 · 트리거가 부른 프로시저 안 (dep=1)]
INSERT INTO T_STLM_AUD (…) VALUES (SQ_STLM_AUD.NEXTVAL, :B6, …) Execute 100,000 · current 412,377
(+ 자율 트랜잭션 COMMIT 100,000번 · 이 세션의 log file sync 3 · LGWR log file parallel write 4,180)
[시험 DB — 같은 정정 10만 건, 감사 방식만 바꿔서]
안 경과 user commits redo 감사 행 1차처럼 ROLLBACK하면 남는 감사 행
지금 (행 트리거 + 자율 트랜잭션 INSERT, COMMIT) 12.4 초 100,001 98.7 MB 100,000 100,000
① 행 트리거 + 같은 트랜잭션에서 INSERT 3.1 초 1 62.3 MB 100,000 0
② 복합 트리거 (행 구간은 배열에 모으고 1,000건마다 FORALL INSERT) 1.9 초 1 48.6 MB 100,000 0
③ 트리거 없이 배치가 UPDATE 전에 감사 행을 INSERT … SELECT 1.5 초 1 43.9 MB 100,000 0
(비교) 감사 없음 1.2 초 1 29.4 MB 0 —