[Developer] #567 list latest SQL cursors without time cutoff

This commit is contained in:
devmrko
2026-07-01 15:14:27 +09:00
parent b39968d43f
commit 57d77d2df2
3 changed files with 5 additions and 6 deletions

View File

@@ -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 출처 | 의미 |
|---|---|---|

View File

@@ -46,7 +46,6 @@ public class OrdsProbeService {
private static final TypeReference<Map<String, Object>> 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<SqlExecutionCandidate> candidateViews = candidates.stream()
.map(candidate -> new SqlExecutionCandidate(

View File

@@ -112,7 +112,7 @@
<div class="section-heading compact-heading">
<div>
<h3>DB 실행 증적</h3>
<p class="section-subtitle">최근 15분의 최신 DB cursor 10건에서 같은 보호 대상을 찾아 SQL_ID로 확인한 결과입니다.</p>
<p class="section-subtitle">DB가 보관한 최신 cursor 10건에서 같은 보호 대상을 찾아 SQL_ID로 확인한 결과입니다.</p>
</div>
<span class="badge text-bg-success" th:text="${'SQL_ID ' + result.executionEvidence().sqlId()}">SQL_ID</span>
</div>