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

매장끼리 재고를 주고받는 마감 시간에 ORA-00060이 뜬다

기초UPDATE유통514 / 700

상황 ​

본사 레거시 유통의 「매장 간 재고 이동」 화면은 매장 담당자가 남는 재고를 다른 매장으로 넘길 때 쓴다. 저녁 마감(21:00~22:00)에는 매장 여섯 곳이 서로 재고를 맞추느라 이동이 몰린다. 지난주부터 일주일에 두세 번 화면에 ORA-00060이 뜨고, 그때마다 담당자가 같은 이동을 다시 입력한다. 화면은 아래 프로시저를 부르고, 프로시저가 끝나면 COMMIT한다.

테이블과 인덱스 ​

  • CF18 일별상품재고: 408행 · 6블록 · PK (SHP_NO, ITM_NO, INV_BS_DT) · 매장 6곳 × 상품 68개 · 이 화면은 기준일 행의 INV_QTY를 현재 재고로 고친다
  • CF15 입출고상품: 51,497행 · 349블록 · PK (INOUT_NO, ITM_NO) · 이동 전표 한 줄을 넣는다
  • CF07 매장: 6행 · SHP_NO 1000~1005
  • 이동 하나는 ① 출고 매장 재고 빼기, ② 이동 전표 넣기, ③ 입고 매장 재고 더하기 순서다. 화면과 프로시저 사이는 문장마다 따로 오간다.

원본 SQL ​

sql
-- PRC_MOVE_STOCK(:from_shp, :to_shp, :itm, :qty, :dt, :inout_no) — 화면이 부르고, 끝나면 COMMIT
UPDATE CF18
   SET INV_QTY = INV_QTY - :qty, MOD_DTT = SYSDATE
 WHERE SHP_NO = :from_shp AND ITM_NO = :itm AND INV_BS_DT = :dt;      -- ① 출고 매장 재고 빼기

INSERT INTO CF15 (INOUT_NO, ITM_NO, INOUT_QTY, REG_DTT)
VALUES (:inout_no, :itm, :qty, SYSDATE);                               -- ② 이동 전표

UPDATE CF18
   SET INV_QTY = INV_QTY + :qty, MOD_DTT = SYSDATE
 WHERE SHP_NO = :to_shp AND ITM_NO = :itm AND INV_BS_DT = :dt;        -- ③ 입고 매장 재고 더하기
COMMIT;

실행계획 학습용 예시 ​

xplan
[시간표 — 6월 14일 21:42 · 상품 1035 · 두 매장이 서로에게 넘겼다]
시각           매장 1000 담당자 (SID 37) : 1000 → 1003     매장 1003 담당자 (SID 52) : 1003 → 1000
21:42:10.120   ① CF18 (1000, 1035) 빼기 → 잠금
21:42:10.124                                               ① CF18 (1003, 1035) 빼기 → 잠금
21:42:10.131   ② 이동 전표
21:42:10.135                                               ② 이동 전표
21:42:10.140   ③ CF18 (1003, 1035) 더하기 → 기다림 (SID 52)
21:42:10.146                                               ③ CF18 (1000, 1035) 더하기 → 기다림 (SID 37)
21:42:13.410   ORA-00060 · ③ 한 문장만 되돌려짐
               화면이 ROLLBACK · 에러 창 → 다시 입력          → 깨어나 ③ · COMMIT

[SID 37 의 트레이스 — Deadlock graph]
                                          ------------Blocker(s)-----------  ------------Waiter(s)------------
Resource Name                             process session holds waits serial  process session holds waits serial
TX-00040012-000004A1-469D09C8-00000000         41      52     X        18822      38      37           X  31109
TX-00090007-00000B3C-469D09C8-00000000         38      37     X        31109      41      52           X  18822

Session 37:  current SQL: UPDATE CF18 SET INV_QTY = INV_QTY + :B5, MOD_DTT = SYSDATE WHERE SHP_NO = :B4 AND ITM_NO = :B3 AND INV_BS_DT = :B2
Session 52:  current SQL: (같은 문장)
Rows waited on:
  Session 37: obj - rowid = 0001A2F3 - AAAaLzAAMAAAACXAAk   (CF18 · SHP_NO 1003 · ITM_NO 1035)
  Session 52: obj - rowid = 0001A2F3 - AAAaLzAAMAAAACXAAA   (CF18 · SHP_NO 1000 · ITM_NO 1035)

[지난 4주 알림 로그] ORA-00060 9번 · 모두 PRC_MOVE_STOCK 의 ③ · 모두 21:00 ~ 22:00

문제 ​

  1. 시간표와 데드락 트레이스를 근거로 원이 어떻게 생겼는지 설명하시오. 일주일에 두세 번만 나는 이유도 쓰시오.
  2. 이동 방향과 상관없이 원이 생기지 않도록 프로시저를 고치시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자