Skip to content
튜닝 연습Lock과 동시성 제어
LOCK-028

입고 예정 배치는 매번 성공인데, 물류센터 화면에 없는 발주가 있다

중급PLSQL유통523 / 700

상황 ​

본사 레거시 유통의 「입고 예정」 배치는 매일 08:00에 오늘 입고될 발주(거래처 리드타임 2일, 이틀 전에 낸 발주)를 발주완료(10)에서 입고중(11)으로 바꾼다. 물류센터 화면은 입고중인 발주만 보여 준다. 2022년에 이 배치가 발주 담당자의 수정 화면을 기다리느라 40분 멈춘 일이 있었고, 그 뒤 배치에 SKIP LOCKED를 넣었다. 지난달부터 물류센터가 "트럭이 왔는데 화면에 없는 발주"라며 입고를 일주일에 한두 번 돌려보낸다. 배치 로그는 매번 '성공'이다.

테이블과 인덱스 ​

  • CF12 발주: 734행 · 10블록 · PK ORD_NO ('2023061002') · ORD_DT VARCHAR2(8) · ORD_PRGS_CD (CF16 공통코드: 10 발주완료 · 11 입고중 · 12 입고완료) · 하루 입고 예정 3~8건
  • CF13 발주상품: 7,102행 · 57블록 · PK (ORD_NO, ITM_NO)
  • 발주 수정 화면(본사 발주 담당자)은 발주를 열 때 CF12 행을 FOR UPDATE로 잠그고, 수량을 고쳐 저장할 때 COMMIT한다. 아침 08:00 전후에 전날까지의 발주를 다듬는 일이 잦다.

원본 SQL ​

sql
-- 08:00 「입고 예정」 배치
DECLARE
  v_cnt PLS_INTEGER := 0;
BEGIN
  FOR r IN (SELECT ORD_NO
              FROM CF12
             WHERE ORD_DT = TO_CHAR(SYSDATE - 2, 'YYYYMMDD')
               AND ORD_PRGS_CD = '10'
               FOR UPDATE SKIP LOCKED) LOOP           -- 2022.04 수정 화면을 기다리지 않게
    UPDATE CF12 SET ORD_PRGS_CD = '11', MOD_DTT = SYSDATE WHERE ORD_NO = r.ORD_NO;
    v_cnt := v_cnt + 1;
  END LOOP;
  COMMIT;
  PKG_LOG.WRITE('입고 예정 ' || v_cnt || '건 성공');
END;

실행계획 학습용 예시 ​

xplan
[시간표 — 6월 12일 · 6월 10일에 낸 발주 6건]
시각       발주 담당자 화면 (SID 66)                     입고 예정 배치 (SID 140)
07:52      발주 2023061002 열기 → CF12 행 잠금 (FOR UPDATE)
           수량 다듬는 중 — COMMIT 전
08:00:00                                                대상 6건 중 잠기지 않은 5건만 가져온다 (2023061002 는 에러 없이 건너뜀)
08:00:01                                                5건 → 11 · COMMIT · 로그 '입고 예정 5건 성공'
08:09      저장 · COMMIT (2023061002 는 여전히 10 발주완료)
10:40      트럭 도착 · 물류센터 화면에 2023061002 없음 → 입고 거부

[V$LOCK — 08:00:00]
SID   TYPE  대상                    LMODE  REQUEST  BLOCK
66    TM    CF12                      3      0        0
66    TX    SID 66 의 트랜잭션          6      0        0      ← 기다리는 사람이 없어 BLOCK 0
140   TM    CF12                      3      0        0
140   TX    SID 140 의 트랜잭션         6      0        0
      (배치는 아무것도 기다리지 않았다 · enq: TX 0)

[같은 대상 — 배치 전후 건수]
            ORD_PRGS_CD = '10'   ORD_PRGS_CD = '11'
08:00 전            6                    0
08:00 후            1                    5        ← 로그에는 '5건 성공'뿐, 몇 건이 남았는지는 없다

[지난 4주 — 입고를 돌려보낸 발주]  7건 · 모두 배치 시각에 발주 수정 화면이 열려 있던 발주

문제 ​

  1. 시간표와 배치 전후 건수를 근거로 발주가 어떻게 빠졌는지, 배치 로그가 왜 '성공'인지 설명하시오.
  2. 한 건도 조용히 빠뜨리지 않으면서 수정 화면을 오래 기다리지도 않도록 배치를 고치시오.
  3. SKIP LOCKED가 맞는 일과 맞지 않는 일을 구분해 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자