테마
주간 정산 보정 배치 P_STLM_ADJ는 0.3초쯤 걸렸다. 지난달 장애 회의에서 "배치가 어디까지 했는지 알 수 없다"는 말이 나와, 개발자가 정산 한 건을 처리할 때마다 PKG_LOG.WRITE로 한 줄씩 남기게 했다. 로그는 배치가 실패해 롤백돼도 남도록 자율 트랜잭션으로 쓴다. 그 뒤로 배치가 9초 넘게 걸린다.
지난주 목요일 새벽 배치가 테이블스페이스 부족으로 실패했다. 운영 담당은 공간을 늘린 뒤, 로그의 마지막 OK 번호 다음부터 다시 돌렸다. 월요일 정산 확정에서 보정이 64,000건 모자랐다.
T_ORD_STLM 정산: 이번 주 100,020행 · 약 640블록 · STLM_SEQ 1 ~ 100,020M_CUS: 2,000행 · PK_M_CUS (CUS_ID) · 보정률은 등급 A 0.1%, B 0.2%, 그 밖 0.3%T_STLM_ADJ 보정 이력(이 문제용): 주차(ADJ_WK)마다 지우고 다시 넣는다 · 인덱스 없음T_BATCH_LOG(이 문제용): PK (LOG_SEQ) · LOG_SEQ는 시퀀스 SQ_BATCH_LOG(CACHE 20) · 지금 3,214,906행p_from_seq 인자는 2021년에 1,000건마다 커밋하던 판의 재시작 인자다. 지금 판은 끝에 한 번만 커밋한다.T_BATCH_LOG를 조회해 진행 상황을 본다.-- 로그 패키지 (지난달) — 배치가 롤백돼도 남도록 자율 트랜잭션
CREATE OR REPLACE PACKAGE BODY PKG_LOG IS
PROCEDURE WRITE(p_job VARCHAR2, p_key NUMBER, p_msg VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO T_BATCH_LOG (LOG_SEQ, LOG_DT, JOB_NM, KEY_NO, MSG)
VALUES (SQ_BATCH_LOG.NEXTVAL, SYSTIMESTAMP, p_job, p_key, p_msg);
COMMIT;
END;
END;
/
-- 주간 정산 보정
PROCEDURE P_STLM_ADJ(p_wk VARCHAR2, p_from_seq NUMBER DEFAULT 0) IS
CURSOR c IS
SELECT s.STLM_SEQ, s.STLM_AMT, m.CUS_GD
FROM T_ORD_STLM s, M_CUS m
WHERE m.CUS_ID = s.CUS_ID
AND s.STLM_SEQ > p_from_seq
ORDER BY s.STLM_SEQ;
TYPE t_rows IS TABLE OF c%ROWTYPE;
TYPE t_num IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
v t_rows;
v_rate t_num;
BEGIN
PKG_LOG.WRITE('STLM_ADJ', NULL, 'START ' || p_wk);
IF p_from_seq = 0 THEN
DELETE FROM T_STLM_ADJ WHERE ADJ_WK = p_wk;
END IF;
OPEN c;
LOOP
FETCH c BULK COLLECT INTO v LIMIT 1000;
EXIT WHEN v.COUNT = 0;
FOR i IN 1 .. v.COUNT LOOP
v_rate(i) := CASE v(i).CUS_GD WHEN 'A' THEN 0.001 WHEN 'B' THEN 0.002 ELSE 0.003 END;
PKG_LOG.WRITE('STLM_ADJ', v(i).STLM_SEQ, 'OK'); -- 장애 때 어디까지 했는지 보려고 (지난달)
END LOOP;
FORALL i IN 1 .. v.COUNT
INSERT INTO T_STLM_ADJ (ADJ_WK, STLM_SEQ, ADJ_RATE, ADJ_AMT)
VALUES (p_wk, v(i).STLM_SEQ, v_rate(i), ROUND(v(i).STLM_AMT * v_rate(i)));
END LOOP;
CLOSE c;
COMMIT;
PKG_LOG.WRITE('STLM_ADJ', NULL, 'END');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
PKG_LOG.WRITE('STLM_ADJ', NULL, 'FAIL ' || SQLERRM);
RAISE;
END;
[세션 통계 — 정상 한 판 (정산 100,020건)]
로그 넣기 전 지금
경과 시간 0.31 초 9.4 초
CPU used by this session 0.17 초 5.9 초
recursive calls 2,412 207,461
user commits 1 100,023
session logical reads 22,363 521,870
redo size 11.2 MB 78.4 MB
log file sync (이 세션) 1 3
LGWR log file parallel write (같은 구간) 14 4,106
T_BATCH_LOG 증가 — 100,023행
[지난주 목요일 — T_BATCH_LOG]
02:00:03 START 2024W23
02:00:09 OK 64000 ← 마지막 OK
02:00:09 FAIL ORA-01653: unable to extend table SQLP.T_STLM_ADJ by 128 in tablespace USERS
09:30:41 START 2024W23 (공간을 늘리고 P_STLM_ADJ('2024W23', 64000)로 다시 돌림)
09:30:44 END
[월요일 정산 확정 대조]
정산 100,020 · 보정 이력 36,020 · 차이 64,000
log file sync가 3번뿐인데도 커밋이 원인인 까닭도 쓰시오.