테마
한빛유통 고객센터의 상담 프로그램(설치형 클라이언트)은 상담원이 고객을 조회할 때 개인정보 접근 기록을 남긴다. 작년 개인정보 점검 뒤 M_CUS에 컬럼 둘을 더하고, 조회할 때마다 그 고객 행을 UPDATE하게 바꿨다. COMMIT은 상담원이 「저장」 버튼을 누를 때만 한다.
7월 1일 12:00에 돈 「고객 등급 재산정」 배치가 12:51에야 끝났다(평소 3초). 그 사이 다른 상담원 둘의 고객 조회 화면도 멈췄다. 상담원들은 점심시간이라 아무것도 하지 않았다고 한다.
M_CUS 고객: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · 작년에 더한 LST_INQ_DT(마지막 조회 시각), LST_INQ_EMP(조회한 상담원)CUS_GD를 한 문장으로 고치고 COMMIT한다.-- 상담 프로그램: 고객 조회 (상담원이 고객을 열 때마다)
SELECT CUS_ID, CUS_NM, RGN_ID, GND_TP, BTH_YMD, CUS_GD
FROM M_CUS
WHERE CUS_ID = :cus_id;
UPDATE M_CUS
SET LST_INQ_DT = SYSDATE, LST_INQ_EMP = :emp_id -- 개인정보 접근 기록 (작년 점검 조치)
WHERE CUS_ID = :cus_id;
-- COMMIT 은 「저장」 버튼에서만 (조회만 하고 넘어가면 다음 저장 때 함께)
-- 12:00 「고객 등급 재산정」 배치 (평소 3초)
MERGE INTO M_CUS c
USING (SELECT CUS_ID,
CASE WHEN SUM(ORD_AMT) >= 5000000 THEN 'A'
WHEN SUM(ORD_AMT) >= 1000000 THEN 'B' ELSE 'C' END AS NEW_GD
FROM T_ORD
WHERE ORD_DT >= ADD_MONTHS(TRUNC(SYSDATE), -12)
GROUP BY CUS_ID) s
ON (c.CUS_ID = s.CUS_ID)
WHEN MATCHED THEN UPDATE SET c.CUS_GD = s.NEW_GD;
COMMIT;
[블로킹 트리 — 7월 1일 12:20:05]
SID_TREE PROGRAM STATUS EVENT SECS BLOCKER SQL_ID 의 문장 / PREV_SQL_ID 의 문장
77 CSCLIENT.exe INACTIVE SQL*Net message from client 1,207 (없음) / UPDATE M_CUS SET LST_INQ_DT = SYSDATE …
203 JDBC Thin Client ACTIVE enq: TX - row lock contention 1,203 77 MERGE INTO M_CUS c USING …
18 CSCLIENT.exe ACTIVE enq: TX - row lock contention 640 203 UPDATE M_CUS SET LST_INQ_DT = SYSDATE … (CUS_000412)
41 CSCLIENT.exe ACTIVE enq: TX - row lock contention 312 203 UPDATE M_CUS SET LST_INQ_DT = SYSDATE … (CUS_000377)
[V$LOCK — 같은 시각]
SID TYPE 대상 LMODE REQUEST BLOCK
77 TM M_CUS 3 0 0
77 TX SID 77 의 트랜잭션 6 0 1
203 TM M_CUS 3 0 0
203 TX 배치의 트랜잭션 6 0 1 ← 이미 고친 고객 1,286명의 행
203 TX SID 77 의 트랜잭션 0 6 0 ← CUS_001287 에서 멈췄다
18 TX 배치의 트랜잭션 0 6 0
41 TX 배치의 트랜잭션 0 6 0
[V$TRANSACTION ⋈ V$SESSION — SID 77]
START_TIME 11:59:58 · USED_UREC 1 (행 하나) · 상담원 7번 자리
11:59:58 고객 CUS_001287 조회 · 그 뒤 실행한 SQL 0개 (화면을 열어 둔 채 점심)
[12:51:40] 상담원 7번이 돌아와 다른 고객을 조회하고 「저장」 → COMMIT → 12:51:43 배치 끝 → 18 · 41 진행
V$LOCK, V$TRANSACTION을 근거로 배치가 무엇을 50분 동안 기다렸는지 설명하시오. 막은 세션이 아무 SQL도 실행하지 않는데 락을 쥐고 있던 이유도 쓰시오.