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

판매 중지로 바꾼 상품이 다음 날 판매 중으로 돌아와 있다

중급UPDATE유통527 / 700

상황 ​

본사 레거시 유통의 MD는 「상품 정보」 화면에서 상품명, 분류, 거래처, 판매 여부를 고친다. 2년 전 동시 수정 사고 뒤 CF01에 수정일시 칸 CHG_DT(DATE)를 더하고, 화면을 연 뒤로 CHG_DT가 바뀌지 않았을 때만 저장하게 했다. 본사 전산 담당자의 설계 메모에는 "수정일시로 충돌 감지, 0건이면 재조회"라고만 적혀 있다. 그런데 지난달 재고팀이 판매 중지한 상품 둘이 다음 날 다시 판매 중이었고, 거래처가 바꾼 상품 분류 하나가 옛 값으로 돌아갔다. 그사이 MD 화면이 그 상품들을 저장한 기록이 있고, 저장은 모두 성공했다.

테이블과 인덱스 ​

  • CF01 상품: 109행 · 5블록 · PK ITM_NO · 이 문제에서는 CHG_DT DATE(마지막 수정 시각)를 더했다
  • MD 화면: 저장할 때 화면의 칸을 전부 SET에 넣고 CHG_DT = SYSDATE로 고친다. 지난달 저장은 412번이다.
  • 재고팀 「판매 중지」: 재고가 바닥난 상품을 하루 두 번(09:00, 16:00) 한 문장으로 판매 중지한다. 이 SQL은 CHG_DT를 고치지 않는다.
  • 거래처 연동 배치: 5분마다 거래처 시스템의 상품명과 분류를 받아 상품마다 UPDATE 두 문장(상품명, 분류)을 실행하고 문장마다 COMMIT한다. 두 문장 모두 CHG_DT = SYSDATE로 고친다.

원본 SQL ​

sql
-- MD 「상품 정보」 화면: 열 때
SELECT ITM_NO, ITM_NM, ITM_CL_CD, CTG_NO, PTNR_NO, SLE_YN, CHG_DT
  FROM CF01
 WHERE ITM_NO = :itm_no;

-- 저장 (0행이면 "다른 사용자가 먼저 고쳤습니다" → 다시 읽는다)
UPDATE CF01
   SET ITM_NM = :itm_nm, ITM_CL_CD = :cl_cd, CTG_NO = :ctg_no,
       PTNR_NO = :ptnr_no, SLE_YN = :sle_yn, CHG_DT = SYSDATE
 WHERE ITM_NO = :itm_no
   AND CHG_DT = :chg_dt;
COMMIT;

-- 재고팀 「판매 중지」 (09:00 · 16:00)
UPDATE CF01 SET SLE_YN = 'N'
 WHERE ITM_NO IN (SELECT ITM_NO FROM CF18 WHERE INV_BS_DT = :today
                   GROUP BY ITM_NO HAVING SUM(INV_QTY) = 0);
COMMIT;

-- 거래처 연동 배치 (5분마다 · 상품마다 두 문장 · 문장마다 COMMIT)
UPDATE CF01 SET ITM_NM = :nm, CHG_DT = SYSDATE WHERE ITM_NO = :itm_no;
COMMIT;
UPDATE CF01 SET ITM_CL_CD = :cl, CHG_DT = SYSDATE WHERE ITM_NO = :itm_no;
COMMIT;

실행계획 학습용 예시 ​

xplan
[사례 ① — 상품 42번 · 12월 4일 · 판매 중지가 되살아났다]
시각         MD (SID 66)                                       재고팀 (SID 140)
08:57:12     화면 열기 → SLE_YN 'Y' · CHG_DT 12-03 17:42:10
09:00:00                                                       판매 중지 UPDATE SLE_YN = 'N' · COMMIT
                                                               (CHG_DT 는 12-03 17:42:10 그대로)
09:03:41     상품명만 고쳐 저장 → WHERE CHG_DT = 12-03 17:42:10 → 1행 · SLE_YN 'Y' 로 다시 쓴다

[사례 ② — 상품 77번 · 12월 11일 · 분류가 옛 값으로 돌아갔다]
시각            연동 배치 (SID 201)                                 MD (SID 66)
10:15:07.10     UPDATE ITM_NM … CHG_DT = SYSDATE · COMMIT
                → CHG_DT 12-11 10:15:07
10:15:07.40                                                         화면 열기 → 분류 '0301' · CHG_DT 12-11 10:15:07
10:15:07.85     UPDATE ITM_CL_CD = '0305' … CHG_DT = SYSDATE · COMMIT
                → CHG_DT 12-11 10:15:07 (같은 초)
10:16:30                                                            거래처만 고쳐 저장 → WHERE CHG_DT = 12-11 10:15:07 → 1행
                                                                    분류 '0301' 로 되돌아갔다

[지난달]  MD 저장 412번 · 0행으로 막힌 저장 6번 · 막혔어야 했는데 통과한 저장 3번 (사례 ① 2번 · 사례 ② 1번)

문제 ​

  1. 두 사례에서 CHG_DT 검사가 왜 충돌을 잡지 못했는지 각각 설명하시오.
  2. 누가 어떤 SQL로 고치든 MD 화면이 충돌을 잡도록 고치시오. CHG_DT를 TIMESTAMP로 바꾸자는 의견에도 답하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자