程式運作起來之後,發現比較慢,這就是個性能問題。性能問題常常需要追蹤到sql的路線問題,本文就想談談在oracle上面sql的追蹤方式。 軟體的架構一般為: Clients->Application Servers->Database Servers, 其中用戶端就是大量的使用者,它們經過TCP(其上的協定可以為:HTTP, RMI, IIOP,Texedo, CICS等)連接配接到Application Servers;Application Servers在于千兆的速度與資料庫進行連接配接(傳輸的則為SQL),Application Servers可以是一個叢集環境; 資料庫是整個的即時,它同樣可以有叢集來構成,Oracle提供的RAC技術就是用來做叢集的。
Application Servers端:通過ps -ef | grep *, 查處其程序id。
Database: Oracle的transaction隐式的開始于發起的修改資料的sql語句,結束于顯示的送出、復原、SAVEPOINT、ROLLBACK TO <SAVEPOINT>、SET Transaction.
desc v$transaction; select addr from v$transaction;--從中可以看出已經存在了一個transaction, 當用戶端顯示的commit之後,這條記錄已經不存在了。
v$session --目前有多少使用者連接配接到了oracle服務區, desc v$session; select sid, username, status from v$session;--查出來,其中username為空的, 為oracle自己的背景程序, 重點關注非空的使用者(在用戶端用show user顯示發起端的使用者是哪個)。
在linux上面使用netstat檢視, 使用netstat -anp | more可以查出PID、本地位址local address和遠端的socket位址(在windows上用ipconfig可以看到自己的ip位址, windows的位址正好就是linux上面netstat -anp查出的遠端位址foreign address; 同時在windows上面,可以使用netstat -b找出windows上發起相應ip:port的程序究竟是哪一個, 它的本地位址就是自己,它的遠端位址就是linux上面的前面提到的本地位址, 同時可以看出windows上面程序的PID和程序名字, 也可以通過任務管理中pid查出程式名)。 通過ps -ef | grep PID, 可以知道這個程序就是負責和遠端連接配接的dedicated server程序。
v$transaction --伺服器上有哪些transaction
v$process --transaction是屬于哪個用戶端的使用者,則查v$process
v$sql --目前正在執行的sql語句
select addr, ses_addr from v$transaction; --查找出目前正在執行的transaction; 通過查出來的ses_addr值, 在v$session中去查找, 使用select saddr,sid, paddr, username, status from v$session; 通過select saddr, sid, paddr, username, status from v$session查找出是哪個程序發起的這個transaction。 通過剛才查到的paddr(在v$process中叫addr, 見上圖)查找表v$process, 通過語句select addr, spid from v$process查出spid對應的程序号。 通過程序号,查出相應的程序資訊(ps -ef | grep 程序号(即spid)), 還需要通過netstat -anp查出其具體的程序資訊(包括本地位址和遠端位址)。 使用select sid, prev_sql_addr, username, status from v$session找出其prev_sql_addr關聯到v$sql的address字段, 通過select sql_text, address from v$sql where address='***'; (其中***代表剛才v$session中查到的prev_sql) 此時, 你就可以看到你剛才在用戶端執行的sql語句就出現在你的面前。
一些簡化的連接配接可以加快定位問題: select sid, username, process, program from v$transaction t, v$session s where t.ses_addr=s.saddr;
總結如下:
col sql_text format a40;
(1)直接查出執行的SQL: select sql_text, address from v$sql where address in (select s.prev_sql_addr from v$session s, v$transaction t where t.ses_addr=s.saddr);
或者 select sql_text as "執行的SQL", address from v$sql where address in (select s.prev_sql_addr from v$session s, v$transaction t where t.ses_addr=s.saddr);
(2) 查出session與transaction的關聯:select s.saddr,s.sid, s.paddr, s.username, s.status, s.prev_sql_addr from v$session s, v$transaction t where t.ses_addr=s.saddr;