1. 程式人生 > >plsql連線oracle特別慢

plsql連線oracle特別慢

監聽故障(plsql 連線資料庫慢)

問題診斷分析

先簡單地介紹系統的環境:是執行在 HP-UX 11.31 下的10.2.0.4的一套rac

  1. 監聽採用配置,比較簡單。在配置中使用的是主機名。
  2. 客戶端TNSPING 測試的結果為 260ms左右。
  3. PLSQL 連線資料庫的時間,在 10s 左右。
  4. 連線上資料庫後,執行 SQL 正常,SELECT返回大批量資料的速度也正常,資料庫中也沒有異常的 NET 方面的等待。
  5. 使用作業系統工具 PING 資料庫主機,返回的結果相當快,只有幾毫秒。
  6. 在資料庫主機上使用TNSPING以及通過監聽連線資料庫,其結果與在客戶端機器上一致。但是不通過監聽,直接使用 sqlplus “/ as sysdba”這樣的方式連線資料庫,速度非常快。
  7. 檢查資料庫主機/etc 目錄下的 resolv.conf、hosts、nsswitch.conf 等配置檔案,hosts 檔案沒有問題,而 resolv.conf 和 nsswitch.conf 檔案不存在。
  8. 檢查 listener.log 檔案的內容,可以發現連線資料庫比較頻繁。
  9. 重新啟動監聽後,在較短的時間段內,資料庫連線速度比較快,但是很快就會回到速度非常慢的狀況。檢查監聽程序的記憶體使用情況,發現消耗的記憶體並不多。
  10. 檢查 sqlnet.log 檔案內容,沒有發現異常。

如果把通過監聽連線資料庫看作執行一條 SQL,那麼連線資料庫所花的時間,可用 響應時間=服務時間+等待時間
來計算。這裡響應時間為從客戶端發起資料庫連線到最終連線上資料庫所經過的時間,服務時間為從連線過程中監聽和 Server Process 真正處理連線請求所消耗的時間,而等待時間就是在連線過程中排隊等待處理的時間。

從 listener.log 來看,監聽處理一個連線的時間並不是很長,在這個檔案中記錄的時間戳沒有精確到毫秒,平均來看在100ms 左右,平均每秒只能處理 10個連線。如果每秒的連線數在 10 個,最理想的情況每個連線請求都沒有排隊,那麼每連線的時間為100ms 左右,然而,如果在某一時刻,有一個突發的連線高峰,將導致產生連線排隊,而導致後續的連線請求所花的時間加長。假如連線佇列中有 10 個請求,那麼將導致後面的每個請求將需要 1100ms 左右。

監聽的工作原理

使用 tusc 時,ps -ef | grep tnslsnr 得到監聽程序 tnslsnr 的程序號(pid)。要注意的是,可能有多個tnslsnr 程序,我們所要的是父程序(ppid)為 1 的監聽程序號。
sfc12rc1:/home/oracle$ ps -ef | grep tnslsnr
oracle 5861 1 0 Oct 1 ? 45:20 /apps/oracle/product/10.2.0/bin/tnslsnr LISTENER_SFC12RC1 -inherit
oracle 19622 5716 0 14:05:46 pts/ta 0:00 grep tnslsnr
1.在資料庫主機上執行 tusc 命令:
tusc –T hires –fp 5861 > 1.log
2.在客戶端使用 sqlplus 連線資料庫,並得到對應的 Server Process 的程序號:
SQL> select spid from v p

r o c e s s w h e r e a d d r = ( s e l e c t p a d d r f r o m v process where addr=(select paddr from v session where sid=(select sid
from v$mystat where rownum=1));
spid
------------
19190
3.在資料庫主機上按 CTRL+C,中止 tusc 的執行。在得到的輸出檔案 1.log 中,內容格式如下:
( Attached to process 4595 ("/apps/oracle/product/10.2.0/bin/tnslsnr LISTENER_SFC12RC1 -inherit")[64-bit] )
1244792894.476963 [4595] read(17, 0x9fffffffffff6950, 64) … [sleeping]
1244792894.487425 [4595] read(17, “N T P 0 1 9 1 8 5 \n”, 64) … = 11
1244792894.488420 [4595] getpid() … = 4595 (1)
1244792894.488498 [4595] fcntl(17, F_SETFD, 1) … = 0
1244792894.488735 [4595] write(16, "\0\0\0= ", 4) … = 4
1244792894.489328 [4595] write(16, "( A D D R E S S = ( P R O T O C "…, 61) … = 61
1244792894.489445 [4595] write(16, “\0\00401”, 4) … = 4
判斷時間是否正常,實際測試確實請求佇列過長,導致了連線等待時間變得很長。

監聽的連線處理過程

在這裡插入圖片描述

問題的解決
針對這個監聽的問題,解決辦法有以下 3 種:
1.將使用短連線方式的應用,修改為使用連線池方式,這是最根本最徹底的解決方案,但是卻須花費很
長的時間來修改應用。
2.增加更多的監聽,以增加監聽處理能力。
3.由於每個連線的處理時間需要 100ms 左右,時間偏長,進行優化,這個難度太大,短期內不會有效果,同時不一定能成功。根據系統的實際情況,只能以增加更多的監聽來解決問題。

監測:可以建兩個表
首先建一個表,用於儲存使用者登入時的會話資訊。
程式碼如下:
create table LOG_INFORMATION(
LOGON_TIME TIMESTAMP,
HOST_NAME VARCHAR2(100),
USERNAME VARCHAR2(40),
SCHEMANAME VARCHAR2(40),
SESSIONUSER VARCHAR2(40),
IP_ADDRESS VARCHAR2(100)
);
然後我們建一個登入觸發器來記錄登入時的會話資訊:
CREATE OR REPLACE TRIGGER TR_LOGIN_RECORD
AFTER LOGON ON DATABASE
BEGIN
INSERT INTO LOG_INFORMATION
select
systimestamp,
sys_context(‘USERENV’, ‘HOST’),
sys_context(‘USERENV’, ‘CURRENT_USER’),
sys_context(‘USERENV’, ‘CURRENT_SCHEMA’),
sys_context(‘USERENV’, ‘SESSION_USER’),
sys_context(‘USERENV’, ‘IP_ADDRESS’)
from dual;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
/
經過一段時間後,我們再來檢視記錄的資料:
SQL> select host_name,sessionuser,ip_address,count()
from log_information group by host_name,sessionuser,ip_address
having count(
)>=20
order by 4;