當 Oracle 進程佔用 CPU 居高不下,需從 OS 進程層層穿透至具體 SQL。標準四步走:
top -c -p $(pgrep -d',' -f ora_.*_ORCL)
# 或
ps -eo pid,user,%cpu,comm --sort=-%cpu | head -20
記錄 PID (即 Oracle SPID),假設為 3575。
SELECT s.sid, s.serial#, s.username, s.machine, s.program, s.osuser,
s.logon_time, s.status, p.spid
FROM v$session s, v$process p
WHERE p.addr = s.paddr
AND p.spid = 3575; -- Step 1 取得的 SPID
取得 SID、SERIAL#。
-- 當前 SQL
SELECT sql_text
FROM v$sqltext_with_newlines
WHERE hash_value = (SELECT sql_hash_value FROM v$session WHERE sid = :sid)
ORDER BY piece;
-- 或最近一次 SQL
SELECT sql_text
FROM v$sqltext_with_newlines
WHERE hash_value = (SELECT prev_hash_value FROM v$session WHERE sid = :sid)
ORDER BY piece;
SELECT a.username, a.machine, a.program, a.sid, a.serial#, a.status,
c.piece, c.sql_text
FROM v$session a, v$process b, v$sqltext c
WHERE b.spid = '&spid'
AND b.addr = a.paddr
AND a.sql_address = c.address(+)
ORDER BY c.piece;
-- 該 Session 等待的鎖
SELECT * FROM v$lock
WHERE kaddr IN (SELECT lockwait FROM v$session WHERE sid = :sid);
-- SQL 完整執行計劃
EXPLAIN PLAN FOR <取得的 SQL>;
SELECT * FROM TABLE(dbms_xplan.display);
-- 1. 開啟 Session 級 Trace
EXEC dbms_system.set_sql_trace_in_session(:sid, :serial#, TRUE);
-- 2. 讓問題 SQL 跑完
-- 3. 關閉 Trace
EXEC dbms_system.set_sql_trace_in_session(:sid, :serial#, FALSE);
-- 4. 服務器端 user_dump_dest 找到 *.trc,轉換
tkprof ora_12345.trc output.txt explain=user/pass sys=no
DBMS_STATS.GATHER_TABLE_STATS。從 SPID 到 SQL Text 僅需 3 條查詢,建議收藏成腳本庫,關鍵時刻秒級定位。