當Oracle查詢出現效率問題時,我們往往須要了解問題所在,這樣才干針對問題給出解決方式。Oracle提供了SQL運行的trace信息,當中包括了SQL語句的文本信息。一些運行統計,處理過程中的等待,以及解析階段(如生成運行計划)產生的信息。
這些信息有助於你分解sql語句的服務時間和等待時間,並了解所用資源和同步點的具體信息,從而幫助你診斷存在的性能問題。
這篇文章介紹了怎么開啟SQL跟蹤和獲取trace文件,具體信息例如以下。
開啟SQL跟蹤
從內部技術細節看,SQL跟蹤是基於10046調試事件的,以下是支持的等級:
0
禁止調試事件
1
調試事件是激活的。
針對每一個被處理的數據庫調用。給定例如以下信息:SQL語句、響應時間、服務時間
處理的行數、處理的行數、邏輯讀數量、物理讀與寫的數量、運行計划以及一些額外信息
4
假設等級1。包含綁定變量的額外信息。
主要是數據類型、精度以及每次運行時所用的值
8
同等級1。加上關於等待時間的細節信息。為了處理過程中的每一個等待,提供例如以下信息:等待時間的名字、持續時間,以及一些額外的參數,可標明所等待的資源
12
同一時候啟動等級4和等級8
在Oracle 9i或者之前,以下SQL語句針對所在會話激活SQL跟蹤:
alter session set sql_trace = true
還可通過dbms_session包中的set_sql_trace存儲過程,或者通過dbms_system包的set_sql_tarce_in_session存儲過程方法,但這些都僅僅是在等級1激活SQL跟蹤,在實踐中用處不大,就不詳述了。
更實用的是指定級別的方式,以下是對所在會話開始等級12的SQL跟蹤:
alter session set events '10046 trace name context forever, level 12'
相應的對所在會話禁止SQL跟蹤的語句例如以下:
alter session set events '10046 trace name context off'
也能夠通過dbms_system包中的set_ev存儲過程。這里也不詳述了,我以下重點講講Oracle 10g之后提供的方法。
Oracle 10g之后提供了dbms_monitor包來開啟或關閉SQL跟蹤。提供了在會話、client、組件以及數據庫層級開啟SQL跟蹤方法。注意僅僅有dba角色的用戶才同意使用。
會話級
以下的PL/SQL為ID為122。序列號為6734的會話開啟第8級的SQL跟蹤:
begin dbms_monitor.session_trace_enable(session_id => 122, serial_num => 6734, waits => true, binds => false); end;
session_id
session標識。相應v$session視圖中的SID列。以下是獲取當前會話id的方法:
select userenv('sid') from dual
serial_num
相應v$session視圖中的SERIAL#列,因為SID會重用。當SID被重用時,SERIAL#添加。獲取方法例如以下:
select serial# from v$session where sid = 122
waits
相應v$session視圖中的SQL_TRACE_WAITS,表示等待事件跟蹤是否被激活,默覺得true。
binds
相應v$session視圖中的SQL_TRACE_BINDS,表示綁定跟蹤是否被激活。默認false。
當運行成功后。v$session視圖中的SQL_TRACE被改動為ENABLED,SQL_TRACE_WAITS和SQL_TRACE_BINDS為你設置的相應值。
以下的PL/SQL用於關閉SQL跟蹤:
begin dbms_monitor.session_trace_disable(session_id => 122, serial_num => 6734); end;
client級
以下的PL/SQL調用為全部具有指定client標記的會話開啟第8級的SQL跟蹤:
begin dbms_monitor.client_id_trace_enable(client_id => 'test', waits => true, binds => false); end;
須要注意client標記區分大寫和小寫,能夠通過以下的方法看是否設置成功:
select primary_id as client_id, waits, binds from dba_enabled_traces where trace_type = 'CLIENT_ID'
當設置成功后,每次查詢前指定相應的client標記就能夠開啟SQL跟蹤,指定client標記的方法例如以下:
begin DBMS_SESSION.SET_IDENTIFIER('test'); end; //該會話的SQL跟蹤已經開啟
當你為一個session設置了標記后,能夠在v$session的client_identifier列查看該標記。
以下的PL/SQL用於關閉SQL跟蹤:
begin dbms_monitor.client_id_trace_disable(client_id => 'test'); end;
組件級
以下的PL/SQL調用為全部具有指定client標記的會話開啟第8級的SQL跟蹤:
begin dbms_monitor.serv_mod_act_trace_enable(service_name => 'ly', module_name => 'PL/SQL Developer', action_name => 'SQL 窗體 - 新建', waits => true, binds => false, instance_name => null); end;
參數中的service_name相應v$session視圖的service_name,module_name相應v$session視圖的的module,action_name相應v$session視圖的action。查詢方式例如以下:
SELECT sid, serial#, client_identifier, service_name, action, module FROM V$SESSION
設置之后能夠通過例如以下方法查看設置:
select primary_id as service_name, qualifier_id1 as module_name, qualifier_id2 as action_name, waits, binds from dba_enabled_traces where trace_type = 'SERVICE_MODULE_ACTION'
以下的PL/SQL用於關閉SQL跟蹤:
begin dbms_monitor.serv_mod_act_trace_disable(service_name => 'ly', module_name => 'PL/SQL Developer', action_name => 'SQL 窗體 - 新建', instance_name => null); end;
數據庫級
以下的PL/SQL調用開啟了數據庫的12級SQL跟蹤:
begin dbms_monitor.database_trace_enable(waits => true, binds => true, instance_name => null); end;
以下的方法查看設置是否成功:
select instance_name, waits, binds from dba_enabled_traces where trace_type = 'DATABASE'
以下的PL/SQL用於關閉SQL跟蹤:
begin dbms_monitor.database_trace_disable(instance_name => null); end;
trace文件里的計時信息
以下的語句用於為trace文件提供計時信息:
alter session set timed_statistics = true
普通情況下默認都為true,假設不提供計時信息。trace文件就沒有什么用了,因此開啟SQL跟蹤之前,最好確認一下參數被設置為true。
獲取生成的trace文件
開啟SQL跟蹤后。會生成一個trace文件,通過初始化參數user_dump_dest配置其所在文件夾,該參數的值能夠通過以下方法獲取到:
select name, value from v$parameter where name = 'user_dump_dest'
但假設我們須要定位到詳細的文件。則須要了解trace文件的命名。trace文件的名字是獨立於版本號和平台的,在大部分常見的平台下。命名結構例如以下:
{instance name}_{process name}_{process id}.trc
1)instance name
初始化參數instance_name的小寫值。通過v$instance視圖的instance_name列能夠得到這個值。
2)process name
產生跟蹤文件進程的名字的小寫值。對於專有服務器進程。使用ora,對於共享服務器進程,能夠通過v$diapatcher或v$shared_server視圖的name列獲得。對於並行從屬進程,能夠通過v$px_process視圖server_name列獲得。對於其它多數后台進程來說。能夠通過v$bgprocess視圖的name列獲得。
3)process id
操作系統層面的進程標記。
這個值能夠通過v$process視圖的spid列獲取。
依據這些信息,能夠通過以下的方式獲取trace文件名稱:
select s.SID, s.SERVER, lower(case when s.SERVER in ('DEDICATED', 'SHARED') then i.INSTANCE_NAME || '_' || nvl(pp.SERVER_NAME, nvl(ss.NAME, 'ora')) || '_' || p.SPID || '.trc' else null end) as trace_file_name from v$instance i, v$session s, v$process p, v$px_process pp, v$shared_server ss where s.PADDR = p.ADDR and s.SID = pp.SID(+) and s.PADDR = ss.PADDR(+) and s.TYPE = 'USER' and s.SID = 'your sid' order by s.SID
將上面的'your sid'替換為你的session的sid就能夠查出指定session生成的trace文件的名字,session的sid在v$session視圖中得到,或者直接查詢當前session的sid:
select userenv('sid') from dual
將路徑(user_dump_dest)和文件名稱結合在一起。我們就得到了trace文件的完整路徑。
而在Oracel 11g中。查詢當前會話生成的trace文件則很easy:
select value from v$diag_info where name = 'Default Trace File'