先查目标用户的SID和SERIAL#:SELECT sid, serial#, username, machine, program FROM v$session WHERE username = 'MARY';若用户名为空,用machine或program辅助定位;SERIAL#是会话生命周期内唯一标识,需立即记录以防复用。
怎么查目标用户的 SID 和 SERIAL#
必须先拿到这两个值,dbms_system.set_sql_trace_in_session 才能工作。直接查 v$session 最可靠:
- 用用户名过滤:
SELECT sid, serial#, username, machine, program FROM v$session WHERE username = 'MARY'; - 如果用户名为空(比如连接池或后台作业),改用
machine或program辅助定位:WHERE program LIKE '%JDBC%' AND machine = 'app-server-02' -
SERIAL#不是自增序号,而是会话生命周期内唯一标识;哪怕SID被复用,SERIAL#也能保证不混淆
注意:查询结果要立刻记下,因为会话可能随时断开。别依赖“稍后重查”——SID 可能已被新会话占用。
用 DBMS_SYSTEM 开启/关闭跟踪
这是最通用、兼容性最好的方式,10g 到 19c 都支持:
- 开启:
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(123, 4567, TRUE);(把 123/4567 换成你查到的SID/SERIAL#) - 关闭:
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(123, 4567, FALSE); - 执行失败常见原因:
ORA-01031: insufficient privileges—— 需要ALTER SYSTEM权限,不是普通SELECT_CATALOG_ROLE就能跑 - 别用
DBMS_MONITOR直接跟踪别人会话——它默认只允许跟踪自己,跨用户需显式授权ADMINISTER DATABASE TRIGGER,实际很少配
如何确认跟踪已生效且文件可定位
光开没用,得知道日志写在哪、是不是真在记录:
- 跟踪文件名格式固定:
<instance_name>_ora_<spid>.trc</spid></instance_name>,不是按用户名命名的 - 查当前会话的
SPID(对应目标会话的 OS 进程 ID):SELECT p.spid FROM v$session s, v$process p WHERE s.sid = 123 AND s.serial# = 4567 AND s.paddr = p.addr; - 查路径优先用:
SELECT value FROM v$diag_info WHERE name = 'Diag Trace';(11g+ 推荐);user_dump_dest在 12c+ 已被标记为 deprecated - 别等用户反馈“没看到 SQL”,立刻去目录下
ls -lt *.trc | head -5看最新文件是否匹配刚查出的SPID
为什么不用 ALTER SYSTEM SET SQL_TRACE = TRUE
看似简单,但生产环境踩坑率极高:
-
ALTER SYSTEM SET SQL_TRACE = TRUE是全局开关,会连 LGWR、CKPT、PMON 这些后台进程一起跟踪——日志爆炸、I/O 压力陡增,可能直接拖慢整个实例 - 12c 起 Oracle 官方文档明确标注该语句为 deprecated,后续版本可能移除
- 即使你只想临时开 30 秒,也极难精准控制关闭时机;而会话级跟踪关了就停,无残留
- 真正需要全局诊断时,应该用
DBMS_MONITOR.DATABASE_TRACE_ENABLE(waits => true, binds => false),它可控、可过滤、自带自动关闭机制
复杂点在于:不同 Oracle 版本对跟踪参数的容忍度差异大,11g 的 sql_trace 参数行为和 19c 的 DBMS_MONITOR 输出结构也不完全一致。别图省事跳过版本核对——一个 SELECT * FROM v$version 花不了两秒,但能避免半天白忙。


















