Oracle 지표 수집
V$ 뷰의 누적값 차이로 초당 지표 수집, 패널 SQL 점검과 병렬 쿼리의 블로킹 오탐 수정
#핵심 요약
실습 수집기 collector.py는 맨 위 SQL 사전에 패널별 SQL을 모아 두고, 화면 한 칸마다 수집 함수 하나와 SQL 사전 키 하나가 대응함
CPU, 읽기, 실행 횟수 같은 초당 지표는 두 번의 스냅숏(예는 3초 간격) 사이 누적값의 차이(델타)로 구함
실습에서는 패널 SQL을 화면 없이 하나씩 실행해 값과 소요 시간을 확인했음
모두 0.2초 안에 끝나 3초 수집 주기보다 충분히 빨랐음
병렬 쿼리 코디네이터는 Idle 대기(PX Deq: Execute Reply)로 슬레이브를 BLOCKING_SESSION으로 가리킴
실습에서는 블로킹 관계를 "Idle이 아닌 대기"일 때만 세도록 고쳐 락 오탐을 없앴음
#개념과 동작 원리
| 수집 함수 | 패널 | 실습 확인 결과 |
|---|---|---|
snapshot |
CPU, Memory, Logical, Physical Reads, 실행 횟수, 커밋, Redo | 2회차에 CPU total 29.96, 메모리 7.48GB 중 여유 1.85GB 등 |
sql_stats |
SQL Elapsed 점 | 99개 SQL, 0.06초 |
sessions |
활성 세션 표 | 평상시 0개, 0.03초 |
alert_log |
Alert Log(V$DIAG_ALERT_EXT) | 최근 24시간의 ORA- 줄 11건, 0.18초 |
tablespaces |
Tablespace Usage | SYSTEM 3.6%, SYSAUX 2.7%, USERS 1.6%, TEMP 0.0% |
실습에서는 수집기를 실제 DB용 OracleCollector와 화면 확인용 DemoCollector 두 개로 두므로, 새 패널은 두 수집기에 함께 넣어야 함
각 함수의 SQL 본문은 수업 자료에 sessions, d_victims의 수정 부분만 있고 나머지는 없음
스냅숏이 어떤 V$ 통계 이름을 읽는지도 실습 텍스트에는 없음
소스 non-CDB에서는 컨테이너가 하나라 Tablespace 패널에 모든 테이블스페이스가 나왔고 CDB용 뷰로 바꿀 필요가 없었음
#필수 명령어 또는 SQL
#대시보드 실행
cd C:\work\mini_oracle_gauge
set MON_PASSWORD=<PASSWORD>
streamlit run app.py결과 해석: 환경 변수는 지금 창에서만 유효하고 = 앞뒤에 빈칸이나 따옴표를 넣지 않음
대시보드가 8501 포트로 뜨면 사이드바에서 실제 DB 연결을 고름
#패널 SQL을 화면 없이 확인(check_panels.py 일부)
import time
from collector import OracleCollector
col = OracleCollector("<MONITOR_USER>", "<PASSWORD>", "<HOST>:1521/<SERVICE_NAME>")
print("instance:", col.info)
def timed(name, fn):
t = time.time()
out = fn()
print(f"\n[{name}] {time.time() - t:2f}초")
return out
timed("snapshot 1회차 (기준값)", col.snapshot)
time.sleep(3)
snap = timed("snapshot 2회차 (3초 뒤 델타)", col.snapshot)
sq = timed("sql_stats (SQL Elapsed 점)", col.sql_stats)
se = timed("sessions (활성 세션 표)", col.sessions)
al = timed("alert_log (V$DIAG_ALERT_EXT)", col.alert_log)
ts = timed("tablespaces", col.tablespaces)결과 해석: 첫 스냅숏은 기준값이고 3초 뒤 두 번째 스냅숏에서 델타가 나옴
화면에서 값이 이상할 때 SQL 문제인지 화면 문제인지 가르는 용도임
#알럿 로그 패널 테스트
export ORACLE_SID=<SERVICE_NAME>
sqlplus -s / as sysdba <<< "exec sys.dbms_system.ksdwrt(2, 'ORA-20000: Mini Oracle Gauge alert log panel test')"결과 해석: 알럿 로그 패널은 최근 24시간의 ORA- 줄만 보여 주므로, 에러가 없던 DB에서는 이렇게 테스트 줄을 써서 패널을 확인함
첫 인자 2는 알럿 로그 파일이라고 실습에서는 설명함DBMS_SYSTEM은 공식 문서로 확인 불가
#읽기 부하(5단계 테이블을 만든 뒤)
python load.py io --sessions 3 --seconds 45결과 해석: 큰 테이블을 통째로 읽는 부하를 세션 3개로 45초 동안 걺
실습 결과는 세션마다 360회 남짓 실행됐음
테이블이 없으면 ORA-00942가 남
테이블은 부하 테스트와 동작 점검에서 만듦
#병렬 쿼리 락 오탐 수정(collector.py 일부)
"sessions": """
with blk as (
select blocking_session as sid, count(*) as cnt
from v$session
where blocking_session is not null
and state = 'WAITING' and wait_class <> 'Idle' -- ← 추가
group by blocking_session),
...
case when s.state = 'WAITING' and s.wait_class <> 'Idle'
then s.blocking_session end as blocking_session, -- ← s.blocking_session 에서 변경
...
"d_victims": """
select sid, serial#, username, event, seconds_in_wait
from v$session
where blocking_session = :sid
and state = 'WAITING' and wait_class <> 'Idle'""", -- ← 추가결과 해석: 실습 확인에서 코디네이터 세션은 PX Deq: Execute Reply(Idle)로 기다리면서 BLOCKER가 병렬 슬레이브였음
락이 아니라 슬레이브의 결과를 기다린다는 뜻임
고친 뒤 같은 부하에서 Blocked 0이 됐음
행 락 대기 enq: TX는 Application 클래스라 계속 잡힘...은 수업 자료에서도 생략된 부분임
#사용 조건과 주의사항
Streamlit 비밀번호 칸은 Enter나 포커스 이동으로 값이 확정되기 전에는 빈 값으로 접속해 ORA-01017이 났음
실습에서는 입력 후 Enter를 누르거나 환경 변수를 씀
부하 중에도 경보가 3개 남는 것은 load.py io 세션이 각각 논리 읽기 900만 블록 이상을 읽어 "논리 읽기 100만 블록 이상" 기준에 걸린 것이며, 기준은 사이드바에서 조절함
실습의 부하 중 수치는 캡션과 확인 표가 다름(Reads 약 95만과 약 113만 블록/초, SQL 99개와 300개)
서로 다른 시점의 값으로 보이며 어느 쪽도 고쳐 적지 않았음
블로킹 세션을 SQL로 직접 찾는 방법은 세션 블로킹에 있음