테마
협력사 P007이 포장 단위를 박스(12개)에서 낱개로 바꾸면서, 그 협력사의 진행 중 발주상품 수량을 낱개로 환산(12배)하기로 했다. 개발자는 사내 배치 표준의 "트랜잭션은 짧게"에 따라 500건마다 커밋을 넣었다.
07:10 첫 실행은 ORA-01002로 멈췄고, 07:24에 다시 돌렸는데 같은 자리에서 또 멈췄다. 09:30에 구매팀이 전화했다. "P007 발주 수량이 이상해요. 어떤 건 그대로고 어떤 건 엄청 커요."
CF12 발주: 734행 · 10블록 · PK ORD_NO · P007의 진행 중(ORD_PRGS_CD '10', '20') 발주 139건CF13 발주상품: 7,102행 · 57블록 · PK (ORD_NO, ITM_NO) · 대상 1,384행. 이 문제에서는 단위 칸 ORD_UNIT_CD('BOX' · 'EA')가 더 있고, 대상은 모두 'BOX'다. 배치는 이 칸을 건드리지 않았다.CF13_BAK_0610: 운영 표준에 따라 07:09에 떠 둔 CF13 전체 사본(CTAS)이다. 그 뒤로 대상 행을 고친 것은 이 배치뿐이다(감사 로그로 확인).DECLARE
CURSOR c IS
SELECT d.ORD_QTY
FROM CF13 d
WHERE d.ORD_NO IN (SELECT h.ORD_NO FROM CF12 h
WHERE h.PTNR_NO = 'P007'
AND h.ORD_PRGS_CD IN ('10', '20'))
FOR UPDATE OF d.ORD_QTY;
n PLS_INTEGER := 0;
BEGIN
FOR r IN c LOOP
UPDATE CF13 SET ORD_QTY = ORD_QTY * 12 WHERE CURRENT OF c; -- 박스 → 낱개
n := n + 1;
IF MOD(n, 500) = 0 THEN COMMIT; END IF; -- 트랜잭션은 짧게 (사내 배치 표준)
END LOOP;
COMMIT;
END;
[배치 로그]
07:10:02 시작 · 대상 1,384행
07:10:03 500행 처리 · COMMIT
07:10:03 ORA-01002: fetch out of sequence
07:24:40 재실행 · 대상 1,384행
07:24:41 500행 처리 · COMMIT
07:24:41 ORA-01002: fetch out of sequence
[커서의 실행계획 — 첫 실행 (DISPLAY_CURSOR · ALLSTATS LAST)]
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 500 |00:00:00.01 | 1453 |
| 1 | FOR UPDATE | | 1 | | 500 |00:00:00.01 | 1453 |
| 2 | BUFFER SORT | | 1 | | 1384 |00:00:00.01 | 67 |
|* 3 | HASH JOIN RIGHT SEMI | | 1 | 1402 | 1384 |00:00:00.01 | 67 |
|* 4 | TABLE ACCESS FULL | CF12 | 1 | 141 | 139 |00:00:00.01 | 10 |
| 5 | TABLE ACCESS FULL | CF13 | 1 | 7102 | 7102 |00:00:00.01 | 57 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("D"."ORD_NO"="H"."ORD_NO")
4 - filter(("H"."PTNR_NO"='P007' AND ("H"."ORD_PRGS_CD"='10' OR "H"."ORD_PRGS_CD"='20')))
[09:30 — P007 진행 중 발주상품 1,384행을 사본 CF13_BAK_0610 과 대조]
ORD_QTY = 사본 × 144 500행
ORD_QTY = 사본 × 1 884행
ORD_QTY = 사본 × 12 0행
ORD_UNIT_CD 1,384행 모두 'BOX'
ORA-01002로 멈춘 이유를 커서와 커밋의 관계로 설명하시오.