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

아무도 안 건드렸다는데 정산 화면이 10분 멈췄다

중급UPDATE한빛유통496 / 700

상황 ​

5월 20일(월) 10:04에 정산팀 전체의 정산 등록 화면이 저장 버튼에서 멈췄다. 박팀장은 "배포한 사람 없대요." 하고 전했다. 화면은 10:14에 저절로 풀렸다. 지난 금요일 18:40에 개발팀이 '정산번호 중복 버그 수정' 핫픽스를 반영했다. 정산 번호를 MAX+1 대신 채번 테이블에서 받도록 바꾼 것이다. 10:04에는 정산 보정 배치가 정산 30건을 등록하고 있었다(배치는 30건을 다 등록한 뒤 COMMIT하며, 약 10분 걸린다). 강도현이 2019.03에 남긴 커밋 메모는 이렇다. "시퀀스는 쓰지 않음. 결번이 생긴다(2018 감사 지적)."

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록 · 정산 번호 STLM_SEQ는 100,000까지 쓰였다 · PK 없음 · 인덱스 없음
  • T_STLM_NUM 채번: 1행 · PK (NUM_TP) · 핫픽스 전에는 쓰지 않던 테이블
  • 2018 감사 지적 원문: "정산번호 결번 발생 시 결번 사유를 확인할 수 있는 기록이 없음"
  • 정산팀 확인: 정산 번호는 순서에 의미가 없는 식별 번호지만 겹치면 안 된다

원본 SQL ​

sql
-- PKG_ORD_STLM.REG_STLM — 정산 한 건 등록 (화면 · 보정 배치가 같이 부른다)
--   5월 17일 핫픽스 "정산번호 중복 버그 수정"
--   이전 판 (2019.03 강도현) : SELECT NVL(MAX(STLM_SEQ), 0) + 1 INTO v_no FROM T_ORD_STLM;
SELECT LAST_NO + 1 INTO v_no
  FROM T_STLM_NUM
 WHERE NUM_TP = 'STLM'
   FOR UPDATE;

UPDATE T_STLM_NUM SET LAST_NO = v_no WHERE NUM_TP = 'STLM';

INSERT INTO T_ORD_STLM (STLM_SEQ, ORD_SEQ, CUS_ID, STLM_DT, STLM_AMT)
VALUES (v_no, :ord_seq, :cus_id, SYSDATE, :amt);
-- COMMIT 은 부른 쪽이 한다 — 화면은 저장 버튼에서 · 보정 배치는 30 건을 다 등록한 뒤

실행계획 실측 · 교재 12화(복사본, 세 세션) ​

xplan
[세 사람 동시 — 핫픽스 판 · 연습 DB 복사본 (배치가 번호를 받고 약 3초 뒤 COMMIT 하도록 줄였다)]
시각     배치 (SID 53)                              화면 1 (SID 21)                     화면 2 (SID 216)
t+0.0    번호 받기 → 100001 · 등록을 이어 간다
t+0.1                                               번호 받기 → 기다림
t+0.1                                                                                   번호 받기 → 기다림
t+3.2    COMMIT                                     → 100002 (기다림 316 cs)            → 100003 (321 cs)

[V$LOCK — 기다리는 동안]
SID   TYPE  대상 / 이름표                       LMODE  REQUEST  BLOCK
53    TM    T_STLM_NUM                            3       0       0
53    TX    TX-00050011-00000338 (배치의 것)       6       0       1
21    TM    T_STLM_NUM                            3       0       0
21    TX    TX-00050011-00000338                  0       6       0
216   TM    T_STLM_NUM                            3       0       0
216   TX    TX-00050011-00000338                  0       6       0

[블로킹 트리 — V$SESSION (연습에서는 배치의 '일' 을 잠깐 쉬는 것으로 흉내 냈다)]
SID_TREE  EVENT                           SECS  BLOCKER
53        PL/SQL lock timer                  0
  21      enq: TX - row lock contention      2       53
  216     enq: TX - row lock contention      2       53

[이전 판 MAX+1 — 같은 세 사람]
  번호 하나 Buffers 568 (TABLE ACCESS FULL T_ORD_STLM) · 기다림 0 ~ 1 cs · 셋 다 100001 (겹침)
  MAX+1 에 PK 를 걸면 — 화면 둘이 TX 를 REQUEST 4 로 220 cs 기다린 뒤 ORA-00001

문제 ​

  1. 시간표와 V$LOCK을 보고 누가 무엇을 잠가서 누구를 언제까지 막는지 설명하시오. 운영에서 화면이 10분 동안 멈춘 이유도 쓰시오.
  2. 번호를 주는 방법을 고치시오. 이전 판(MAX+1)으로 되돌리면 안 되는 이유와, 강도현이 시퀀스를 피했던 근거를 지금 어떻게 다룰지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자