테마
한빛유통 콜센터의 「고객 정보 수정」 화면은 고객을 열 때 그 고객 한 행을 읽어 띄우고, 「저장」을 누르면 화면의 칸을 전부 그대로 UPDATE한다. 저장은 하루 약 3,000번이다.
3월 12일 상담원 1이 마케팅팀 요청대로 고객 CUS_000417의 등급을 B에서 A로 올렸다. 다음 날 그 고객이 "승급 문자를 받았는데 화면에는 아직 B 등급이에요"라고 전화했다. 에러 로그에는 아무것도 없었다.
M_CUS 고객: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · CUS_GD(A 1% · B 9% · C 90%) · RGN_ID 지역M_CUS에 칸을 더해도 된다.-- 「고객 정보 수정」: 고객을 열 때
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 CUS_NM = :cus_nm, RGN_ID = :rgn_id, GND_TP = :gnd_tp,
BTH_YMD = :bth_ymd, CUS_GD = :cus_gd
WHERE CUS_ID = :cus_id;
COMMIT;
[시간표 — 3월 12일 · 고객 CUS_000417]
시각 상담원 1 (SID 63) · VIP 승급 처리 상담원 2 (SID 118) · 주소 이전 문의
14:02:10 고객 열기 → RGN_ID 03 · CUS_GD B
14:02:25 고객 열기 → RGN_ID 03 · CUS_GD B
14:03:05 CUS_GD 를 A 로 바꿔 저장 → UPDATE 1행 · COMMIT
14:03:46 RGN_ID 를 05 로 바꿔 저장 → UPDATE 1행 · COMMIT
(화면에 남아 있던 CUS_GD 'B' 까지 그대로 쓴다)
14:04 이후 M_CUS : RGN_ID 05 · CUS_GD B ← 상담원 1 의 승급이 사라졌다
[저장 UPDATE — ALLSTATS LAST (14:03:46 · 상담원 2)]
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 | 00:00:00.01 | 4 |
| 1 | UPDATE | M_CUS | 1 | | 0 | 00:00:00.01 | 4 |
|* 2 | INDEX UNIQUE SCAN | PK_M_CUS | 1 | 1 | 1 | 00:00:00.01 | 2 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("CUS_ID"=:CUS_ID)
[V$SESSION — 14:03:46] enq: TX 기다림 없음 · 에러 없음 (상담원 1 은 41초 전에 COMMIT 했다)
[감사 로그 — 2월] 같은 고객을 10분 안에 두 사람이 저장 41번 · 그중 앞사람의 변경이 사라진 경우 38번
SELECT … FOR UPDATE로 잠가 두는 방법이 이 화면에 맞지 않는 이유도 쓰시오.