테마
버거 본사의 매장 관리 앱은 「오늘 주문」 목록을 프로시저 P_DAY_ORD로 받는다. 화면에서 정렬 기준(주문 시각, 주문 번호)과 방향을 고르면 앱이 정렬 문자열을 만들어 그대로 넘긴다. 매장과 날짜는 이미 바인드 변수로 넘긴다.
외부 보안 점검팀은 정렬 칸에 CASE WHEN (SELECT COUNT(*) FROM ORD WHERE SHOP_NO = 'SH0007' …) > 1500 THEN … 같은 식을 넣어, 목록 순서가 바뀌는지로 다른 매장의 주문 수를 알아낼 수 있었다고 보고했다. DBA는 같은 목록 문장이 정렬 문자열만 다른 채 공유 풀에 40여 개 있다고 덧붙였다.
ORD 주문: 1,000,000행 · 22,422블록 · ORD_NO · ORD_DT VARCHAR2(8) · ORD_HMS VARCHAR2(6) · SHOP_NO 'SH0001'(매장 200곳)ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS) · 이 문제에서는 ORD_X02 (SHOP_NO, ORD_DT, ORD_HMS)도 있다 · 통계 최신'ORD_HMS DESC', 'ord_hms desc', 'ORD_HMS DESC' 등)PROCEDURE P_DAY_ORD(p_shop_no IN VARCHAR2, p_dt IN VARCHAR2,
p_order IN VARCHAR2, -- 앱이 만든 정렬 문자열 (예: 'ORD_HMS DESC')
o_rc OUT SYS_REFCURSOR) IS
BEGIN
OPEN o_rc FOR
'SELECT ORD_NO, ORD_DT, ORD_HMS FROM ORD WHERE SHOP_NO = :s AND ORD_DT = :d ORDER BY ' || p_order
USING p_shop_no, p_dt;
END;
[V$SQLAREA: 이 프로시저가 만든 목록 문장 · 점검이 있던 날]
ORDER BY 뒤의 글자 문장 수 실행 수
ORD_HMS DESC · ord_hms desc · … 23 151,402
ORD_NO · ORD_NO ASC · ord_no · … 19 41,288
보안 점검이 넣은 식 (CASE WHEN …) 312 312
합계 354 193,002
[보안 점검 때 실행된 문장 하나 (V$SQL.SQL_TEXT)]
SELECT ORD_NO, ORD_DT, ORD_HMS FROM ORD WHERE SHOP_NO = :s AND ORD_DT = :d
ORDER BY CASE WHEN (SELECT COUNT(*) FROM ORD WHERE SHOP_NO = 'SH0007' AND ORD_DT = '20131224') > 1500
THEN ORD_NO ELSE ORD_HMS END
[한 번의 실행: DISPLAY_CURSOR (ALLSTATS LAST) · 'ORD_HMS DESC']
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 7 |00:00:00.01 | 10 |
| 1 | TABLE ACCESS BY INDEX ROWID | ORD | 1 | 7 | 7 |00:00:00.01 | 10 |
|* 2 | INDEX RANGE SCAN DESCENDING| ORD_X02 | 1 | 7 | 7 |00:00:00.01 | 3 |
-------------------------------------------------------------------------------------------------
2 - access("SHOP_NO"=:S AND "ORD_DT"=:D)
ORDER BY :col)이 왜 답이 아닌지도 쓰시오.