테마
버거원 POS는 200개 매장에서 결제 버튼을 누를 때마다 주문 저장 프로시저를 부른다. 점심 피크(11:50 ~ 12:30)에는 결제가 초당 15건 남짓 들어온다. 지난달부터 점주들의 민원이 늘었다. "결제 버튼을 누르면 1초쯤 멈췄다가 '주문번호 중복, 다시 시도합니다'가 떠요." 앱은 ORA-00001을 받으면 세 번까지 다시 부르고, 세 번 다 실패하면 결제를 처음부터 다시 하게 한다.
ORD 주문: 1,000,000행 · 22,422블록(오늘 피크 직전 기준) · ORD_NO NUMBER, 1부터 빈틈없이 이어진 번호라 지금 최댓값은 1,000,000이다ORD_ITEM 주문상품: 2,472,717행 · ORD_ITEM_PK (ORD_NO, ITEM_ID) · 주문당 평균 2.5행ORD_PK (ORD_NO): BLEVEL 2 · 이 문제의 POS 운영 DB에는 PK 두 개만 있다 · 통계 최신ORD INSERT → ORD_ITEM INSERT(상품마다) → 카드 승인 요청(VAN 응답 평균 1.1초) → COMMIT-- PKG_POS.SAVE_ORDER — 결제 버튼 한 번 (ORA-00001 이면 앱이 세 번까지 다시 부른다)
SELECT NVL(MAX(ORD_NO), 0) + 1 INTO v_no FROM ORD;
INSERT INTO ORD (ORD_NO, ORD_DT, ORD_HMS, SHOP_NO)
VALUES (v_no, TO_CHAR(SYSDATE, 'YYYYMMDD'), TO_CHAR(SYSDATE, 'HH24MISS'), :shop_no);
-- 상품마다
INSERT INTO ORD_ITEM (ORD_NO, ITEM_ID, ORD_ITEM_QTY, ORD_DT, ORD_HMS)
VALUES (v_no, :item_id, :qty, TO_CHAR(SYSDATE, 'YYYYMMDD'), TO_CHAR(SYSDATE, 'HH24MISS'));
-- 카드 승인 (VAN) 응답을 받은 뒤
COMMIT;
[번호 받기 — ALLSTATS LAST]
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 3 |
| 2 | INDEX FULL SCAN (MIN/MAX)| ORD_PK | 1 | 1 | 1 |00:00:00.01 | 3 |
---------------------------------------------------------------------------------------------
[시간표 — 11:50:03 · 두 매장]
시각 매장 SH0017 (SID 88) 매장 SH0142 (SID 131)
11:50:03.20 MAX+1 → 1000001 · ORD INSERT · ORD_ITEM INSERT
카드 승인 요청 (트랜잭션을 연 채)
11:50:03.24 MAX+1 → 1000001 (88 의 행은 COMMIT 전이라 안 보인다)
ORD INSERT → 기다림
11:50:04.31 승인 · COMMIT → ORA-00001: unique constraint (DEV.ORD_PK) violated
11:50:04.33 앱이 다시 부른다 → MAX+1 → 1000002 · …
[V$SESSION — 11:50:03.9]
SID EVENT SECS BLOCKING_SESSION 하는 문장
88 SQL*Net message from client 1 (카드 승인 응답 대기 · 트랜잭션을 연 채)
131 enq: TX - row lock contention 1 88 INSERT INTO ORD …
[V$LOCK — 같은 시각]
SID TYPE 대상 / 이름표 LMODE REQUEST BLOCK
88 TM ORD 3 0 0
88 TX 88 의 트랜잭션 6 0 1
131 TM ORD 3 0 0
131 TX 88 의 트랜잭션 0 4 0 ← 같은 키를 먼저 넣은 쪽이 COMMIT 할지 ROLLBACK 할지 기다린다
[11:50 ~ 12:30 집계]
결제 36,240건 · 첫 시도에서 ORA-00001 2,870번 (7.9%) · 세 번 다 실패 41건
enq: TX - row lock contention 2,870번 · 평균 0.94초
V$LOCK으로 설명하시오.