From 57d77d2df25e5bf2100d35d24c08203703d90e50 Mon Sep 17 00:00:00 2001 From: devmrko Date: Wed, 1 Jul 2026 15:14:27 +0900 Subject: [PATCH] [Developer] #567 list latest SQL cursors without time cutoff --- docs/design/567-ords-vpd-sql-trace/README.md | 2 +- .../vpdbackoffice/service/OrdsProbeService.java | 7 +++---- src/main/resources/templates/fragments/probe-result.html | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/design/567-ords-vpd-sql-trace/README.md b/docs/design/567-ords-vpd-sql-trace/README.md index 61fd85a..1986c80 100644 --- a/docs/design/567-ords-vpd-sql-trace/README.md +++ b/docs/design/567-ords-vpd-sql-trace/README.md @@ -138,7 +138,7 @@ ## 13. SQL_ID 실행 증적 확장 — 2026-07-01 -재현 SQL만으로는 “이 조건이 실제 DB cursor에 적용됐는가”를 충분히 설명하지 못한다. `/probe` 성공·0행 결과 뒤에 백오피스는 `V$SQL`에서 최근 15분의 최신 cursor 10건을 먼저 읽고, Java에서 `SQL_FULLTEXT`에 보호 객체명이 있는 cursor만 고른다. DB에서 SQL 텍스트를 `LIKE`로 필터링하지 않아 ORDS Handler의 PL/SQL·공백·긴 SQL 표현 때문에 놓치는 문제를 줄인다. 이어 `DBMS_XPLAN.DISPLAY_CURSOR(SQL_ID, CHILD_NUMBER, 'ALLSTATS LAST +PREDICATE +ALIAS')`의 Predicate Information을 함께 표시한다. +재현 SQL만으로는 “이 조건이 실제 DB cursor에 적용됐는가”를 충분히 설명하지 못한다. `/probe` 성공·0행 결과 뒤에 백오피스는 `V$SQL`에서 시간 조건 없이 마지막 활성 cursor 10건을 먼저 읽고, Java에서 `SQL_FULLTEXT`에 보호 객체명이 있는 cursor만 고른다. DB에서 SQL 텍스트를 `LIKE`로 필터링하지 않아 ORDS Handler의 PL/SQL·공백·긴 SQL 표현 때문에 놓치는 문제를 줄인다. 이어 `DBMS_XPLAN.DISPLAY_CURSOR(SQL_ID, CHILD_NUMBER, 'ALLSTATS LAST +PREDICATE +ALIAS')`의 Predicate Information을 함께 표시한다. | 화면 증적 | DB 출처 | 의미 | |---|---|---| diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/OrdsProbeService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/OrdsProbeService.java index 8cccda4..b85c8c6 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/service/OrdsProbeService.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/OrdsProbeService.java @@ -46,7 +46,6 @@ public class OrdsProbeService { private static final TypeReference> MAP_TYPE = new TypeReference<>() { }; private static final Logger log = LoggerFactory.getLogger(OrdsProbeService.class); - private static final int EXECUTION_EVIDENCE_LOOKBACK_MINUTES = 15; private record ExecutionEvidenceLookup( SqlExecutionEvidence evidence, @@ -277,7 +276,7 @@ public class OrdsProbeService { lookup.candidates()); } return result.withExecutionEvidence(null, - "최근 15분의 최신 실행 cursor 10건에서 이 보호 대상을 찾지 못했습니다. " + "최신 실행 cursor 10건에서 이 보호 대상을 찾지 못했습니다. " + "아래 원문 SQL을 직접 확인하세요.", lookup.candidates()); } @@ -339,7 +338,7 @@ public class OrdsProbeService { elapsed_time, buffer_gets FROM v$sql - WHERE last_active_time >= SYSTIMESTAMP - NUMTODSINTERVAL(?, 'MINUTE') + WHERE last_active_time IS NOT NULL ORDER BY last_active_time DESC ) WHERE ROWNUM <= 10 @@ -354,7 +353,7 @@ public class OrdsProbeService { resultSet.getLong("rows_processed"), Math.round(resultSet.getLong("elapsed_time") / 1000.0d), resultSet.getLong("buffer_gets") - ), EXECUTION_EVIDENCE_LOOKBACK_MINUTES); + )); List candidateViews = candidates.stream() .map(candidate -> new SqlExecutionCandidate( diff --git a/src/main/resources/templates/fragments/probe-result.html b/src/main/resources/templates/fragments/probe-result.html index a071fc4..5127508 100644 --- a/src/main/resources/templates/fragments/probe-result.html +++ b/src/main/resources/templates/fragments/probe-result.html @@ -112,7 +112,7 @@

DB 실행 증적

-

최근 15분의 최신 DB cursor 10건에서 같은 보호 대상을 찾아 SQL_ID로 확인한 결과입니다.

+

DB가 보관한 최신 cursor 10건에서 같은 보호 대상을 찾아 SQL_ID로 확인한 결과입니다.

SQL_ID