테마
버거 본사는 키오스크의 「포장/매장 식사」 선택을 주문에 남기려고 ORD에 컬럼 하나를 더하기로 했다. 배포 담당자는 개발 DB에서 쓰던 스크립트를 목요일 11:20에 운영에서 돌렸다. 점심 피크는 11:30부터다.
11:20부터 4분 동안 매장 POS의 「환불」 버튼이 돌기만 했다. 결제는 정상이었다. 스크립트는 마지막 줄에서 ORA-02296: cannot enable (DEV.) - null values found로 끝났고, 컬럼은 NULL을 허용한 채 남았다.
ORD 주문: 1,000,000행 · 22,422블록 · ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS) · PCTFREE 10(기본값) · 환불 표시는 상태 칸 ORD_STAT(문제 설정)ORD_NO로 찾아 ORD_STAT을 'R'로 UPDATE한다(하루 수십 건)ORD는 1만 행이라 스크립트가 2초 만에 끝났다-- 배포 스크립트 (개발 DB 에서 2초)
ALTER TABLE ORD ADD (TAKEOUT_YN VARCHAR2(1));
UPDATE ORD SET TAKEOUT_YN = 'N';
COMMIT;
ALTER TABLE ORD MODIFY (TAKEOUT_YN DEFAULT 'N' NOT NULL);
[목요일 — 배포 세션 (SID 66) 과 매장]
시각 배포 (SID 66) 매장 POS
11:20:03 ALTER TABLE ORD ADD … (0.02초)
11:20:05 UPDATE ORD SET TAKEOUT_YN = 'N' 시작 결제(INSERT) 정상 · 환불(UPDATE) 하나씩 멈춤
11:24:12 1000000 rows updated (4분 07초) · COMMIT 멈췄던 환불 7건이 한꺼번에 진행
11:24:13 ALTER TABLE ORD MODIFY … NOT NULL
→ ORA-02296: cannot enable (DEV.) - null values found
[UPDATE 한 문장 — ALLSTATS LAST]
----------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:04:07.31 | 1043K |
| 1 | UPDATE | ORD | 1 | | 0 |00:04:07.31 | 1043K |
| 2 | TABLE ACCESS FULL| ORD | 1 | 1000K| 1000K|00:00:03.12 | 22422 |
----------------------------------------------------------------------------------
세션 통계: redo size 268 MB · undo change vector size 96 MB
[V$SESSION — 11:22:00]
SID EVENT SECS BLOCKING_SESSION 하고 있는 문장
66 db file sequential read 0 UPDATE ORD SET TAKEOUT_YN = 'N'
141 enq: TX - row lock contention 84 66 UPDATE ORD SET ORD_STAT = 'R' WHERE ORD_NO = :B1 (매장 SH0117 환불)
187 enq: TX - row lock contention 31 66 UPDATE ORD SET ORD_STAT = 'R' WHERE ORD_NO = :B1 (매장 SH0042 환불)
[11:30 · 확인]
SELECT COUNT(*) FROM ORD WHERE TAKEOUT_YN IS NULL; → 1,236 (모두 11:20:05 ~ 11:24:12 에 들어온 주문)