테마
2013년 12월 26일부터 사흘 동안 POS 중계 서버 장애로 일부 매장의 주문상품이 본사에 들어오지 않았다. POS 업체는 어느 건이 빠졌는지 몰라 12월분 전체(103,046행)를 다시 보냈다. 본사 적재 프로그램은 한 행씩 넣고, 이미 있는 행은 예외로 잡아 넘긴다. 돌려 보니 7.2초가 걸렸고 redo가 91MB 쌓였는데, 새로 들어간 행은 4,312행뿐이었다. 오과장이 시험 DB에서 세 가지 안을 재 왔다. 장애가 나면 같은 재전송이 또 온다. 적재 규칙은 2019년부터 그대로다. "한 행이 실패해도 나머지는 넣는다. 실패한 행은 사유와 함께 남긴다. 이미 있는 행은 실패가 아니다."
ORD_ITEM_RCV(POS 수신 테이블, 이 문제용): ORD_ITEM과 같은 컬럼 · 12월 재전송분 103,046행 · 2,301블록 · 인덱스 없음ORD_ITEM 주문상품: 적재 전 2,468,405행(장애로 4,312행이 빠진 상태) · 적재 뒤 2,472,717행 · 55,265블록 · ORD_ITEM_PK (ORD_NO, ITEM_ID) 리프 6,870블록 · ORD_ITEM_X01 (ORD_DT, ORD_HMS)ORD_ITEM에 있고, 4,312행이 빠져 있었다.ORD_ITEM_REJ(반송함): ORD_NO · ITEM_ID · ERR_CD · ERR_MSG · 이번에는 0행PROCEDURE LOAD_POS_RESEND IS
v_ok PLS_INTEGER := 0;
v_dup PLS_INTEGER := 0;
v_cd PLS_INTEGER;
v_msg VARCHAR2(200);
BEGIN
FOR r IN (SELECT * FROM ORD_ITEM_RCV) LOOP
BEGIN
INSERT INTO ORD_ITEM VALUES r;
v_ok := v_ok + 1;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
v_dup := v_dup + 1; -- 이미 있음
WHEN OTHERS THEN
v_cd := SQLCODE;
v_msg := SUBSTR(SQLERRM, 1, 200);
INSERT INTO ORD_ITEM_REJ (ORD_NO, ITEM_ID, ERR_CD, ERR_MSG)
VALUES (r.ORD_NO, r.ITEM_ID, v_cd, v_msg);
END;
END LOOP;
COMMIT;
END;
[지금 판 — 12월 재전송분 103,046행 (V$MYSTAT 증가분)]
경과 시간 7.2 초
recursive calls 104,129
execute count 103,072
session logical reads 792,416
redo size 91.3 MB
undo change vector size 27.6 MB
결과 신규 4,312 · 이미 있음 98,734 · 반송 0
[TKPROF — 루프 안의 INSERT]
INSERT INTO ORD_ITEM VALUES (:B1 , :B2 , :B3 , …)
call count cpu elapsed disk query current rows
------- ------- -------- ---------- ---------- ---------- ---------- ----------
Execute 103046 4.61 4.83 0 3118 781944 4312
(103,046번 가운데 98,734번은 ORA-00001로 실패했고, 실패할 때마다 넣던 행을 되돌렸다)
[오과장의 세 안 — 같은 재전송분 · 시험 DB]
안 경과 recursive calls 논리 읽기 redo 결과
① BULK 1000 + FORALL … SAVE EXCEPTIONS 5.6 초 251 786,902 90.8 MB 같음 · 예외 98,734건을 BULK_EXCEPTIONS로 받음
② INSERT … SELECT … LOG ERRORS REJECT LIMIT UNLIMITED 6.8 초 38 1,108,551 128.4 MB 같음 · 오류 기록표에 98,734행
③ INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(ORD_ITEM, ORD_ITEM_PK) */
… SELECT 5.9 초 31 790,377 90.1 MB 같음 · 이미 있음 건수는 따로 세야 함