Skip to content
튜닝 연습파티션
PART-028

새해 0시가 지나자 쇼핑몰 주문 등록이 모두 ORA-14400으로 실패한다

기초DDL한빛유통403 / 700

상황 ​

2025년 1월 1일 00:00:03부터 쇼핑몰 주문이 하나도 저장되지 않는다. 애플리케이션 로그에는 ORA-14400만 줄지어 찍혔고, 새해 0시 특가 때문에 12분 동안 실패가 312건 쌓였다. 당직 DBA가 00:12에 전화를 받았다. 주문 테이블은 2년 전에 월별 파티션으로 바꿨다. 해마다 12월에 담당자가 다음 해 12칸을 손으로 더해 왔는데, 이 일은 운영 일정표 어디에도 없었고 그 담당자는 지난여름 다른 팀으로 옮겼다.

테이블과 인덱스 ​

  • T_ORD_RNG 주문(파티션 복사본, 문제 설정): T_ORD 100,000행을 PARTITION BY RANGE (ORD_DT) 월별 24칸(P202301 ~ P202412)으로 나눴다(STORAGE (INITIAL 64K)). MAXVALUE 칸은 없다. 잘못된 날짜를 막으려고 일부러 두지 않았다고 한다.
  • 칸 하나는 약 4,170행이고 FULL로 약 38블록이다. ORD_DT는 DATE이고 시분초가 있다(SYSDATE로 넣는다). 평소 하루 주문은 약 137건이다.
  • 인덱스는 LOCAL PK_T_ORD_RNG (ORD_SEQ, ORD_DT)뿐이다. 통계는 최신이다.
  • 보관 기간은 36개월이다. 월 정리 스크립트는 지울 칸의 이름을 날짜로 만든다('P' || TO_CHAR(ADD_MONTHS(SYSDATE, -36), 'YYYYMM')).

원본 SQL ​

sql
-- 주문 등록 (애플리케이션 · 주문마다 한 번)
INSERT INTO T_ORD_RNG (ORD_SEQ, CUS_ID, ORD_DT, ORD_ST, ORD_AMT)
VALUES (SQ_ORD_SEQ.NEXTVAL, :cus_id, SYSDATE, 'PENDING', :amt);

-- 「오늘 주문 현황」 (운영 화면 · 5분마다)
SELECT ORD_ST, COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
  FROM T_ORD_RNG
 WHERE ORD_DT >= TRUNC(SYSDATE)
   AND ORD_DT <  TRUNC(SYSDATE) + 1
 GROUP BY ORD_ST;

실행계획 학습용 예시 ​

xplan
[2025-01-01 00:00:03 이후 · 주문 등록]
  ORA-14400: inserted partition key does not map to any partition
  00:00 ~ 00:12 실패 312건 (주문 번호는 시퀀스에서 받았다가 버려졌다)

[USER_TAB_PARTITIONS · 마지막 세 칸]
  PARTITION_NAME  POSITION  HIGH_VALUE                                    NUM_ROWS
  P202410               22  TO_DATE(' 2024-11-01 00:00:00', 'SYYYY-…')       4,203
  P202411               23  TO_DATE(' 2024-12-01 00:00:00', 'SYYYY-…')       4,118
  P202412               24  TO_DATE(' 2025-01-01 00:00:00', 'SYYYY-…')       4,236

[2024-12-31 23:55 · 「오늘 주문 현황」]
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |      1 |        |      3 | 00:00:00.01 |      38 |        |       |
|   1 |  HASH GROUP BY              |           |      1 |      3 |      3 | 00:00:00.01 |      38 |        |       |
|*  2 |   FILTER                    |           |      1 |        |    139 | 00:00:00.01 |      38 |        |       |
|   3 |    PARTITION RANGE ITERATOR |           |      1 |    137 |    139 | 00:00:00.01 |      38 |    KEY |   KEY |
|*  4 |     TABLE ACCESS FULL       | T_ORD_RNG |      1 |    137 |    139 | 00:00:00.01 |      38 |    KEY |   KEY |
---------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(TRUNC(SYSDATE@!)<TRUNC(SYSDATE@!)+1)
   4 - filter(("ORD_DT">=TRUNC(SYSDATE@!) AND "ORD_DT"<TRUNC(SYSDATE@!)+1))

  (실행 때 고른 칸 — 24번 P202412)

문제 ​

  1. ORA-14400이 왜 났는지 칸 정의로 설명하고, 지금 바로 주문을 다시 받으려면 무엇을 해야 하는지 쓰시오.
  2. 해마다 같은 일이 생기지 않도록 테이블을 고치고, 그렇게 바꿀 때 함께 고쳐야 할 것과 MAXVALUE 칸을 두는 방법과의 차이를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자