從上週起,服務器Oracle數據庫出現問題,用不到半天,就會報maxsession(150)的問題,確定是數據庫的會話超過最大數了。
因爲服務器跑的是文件傳輸應用,佔用的請求和會話確定很大,所以用戶數不大就已經讓oracle的會話數達到最大值。
處理方式不外乎兩種:擴大oracle最大session數以及清除inactive會話,固然還有,就是從數據庫鏈接池和程序bug上面下手。
從各處收集了一些查看當前會話的語句,記錄一下:
1.select count(*) from v$session;
select count(*) from v$process;
查看當前總會話數和進程數,這兩個視圖就是跟會話及進程有關的重要視圖啦,信息都是從這裏面取的。
2.查詢那些應用的鏈接數此時是多少
select b.MACHINE, b.PROGRAM , count(*) from v$process a, v$session b where a.ADDR = b.PADDR and b.USERNAME is not null group by b.MACHINE , b.PROGRAM order by count(*) desc;
3.查詢是否有死鎖
select * from v$locked_object;
若是查詢結果爲no rows selected,說明數據庫中沒有死鎖。不然說明數據庫中存在死鎖。
接下來講明一下會話的狀態:
1.active 處於此狀態的會話,表示正在執行,處於活動狀態。
2.killed 處於此狀態的會話,表示出現了錯誤,正在回滾,固然,也是佔用系統資源的。還有一點就是,killed的狀態通常會持續較長時間,並且用windows下的工具pl/sql developer來kill掉,是無論用的,要用命令:alter system kill session 'sid,serial#' ;
3.inactive 處於此狀態的會話表示不是正在執行的,好比select語句已經完成。我一開始覺得,只要是inactive狀態的會話,就是該殺,爲何不釋放呢。其實,inactive對數據庫自己沒有什麼影響,可是若是程序沒有及時commit,那麼就會形成佔用過多會話。解決inactive的方法最好的就是在oracle中直接設置超時時間,也是有兩種方法,區別暫時還不清楚:
1.修改sqlnet.ora文件,新增expire_time=x(單位是分鐘)
個人sqlnet.ora位置在D:\oracle\ora92\network\admin
2.經過ALTER PROFILE DEFAULT LIMIT IDLE_TIME 10; 命令修改,記得重啓下oracle。sql
===============數據庫
另一種解決方法:windows
select A.SID,B.SPID,A.SERIAL#,a.lockwait,A.USERNAME,A.OSUSER,a.logon_time,a.last_call_et/3600 LAST_HOUR,A.STATUS,
'orakill '||sid||' '||spid HOST_COMMAND,
'alter system kill session '''||A.sid||','||A.SERIAL#||'''' SQL_COMMAND
from v$session A,V$PROCESS B where A.PADDR=B.ADDR AND SID>6服務器
================session
一個自動殺 的job
CREATE OR REPLACE PROCEDURE "KILL_SESSION" AS
v_sid number;
v_serial number;
killer varchar2(1000);
CURSOR cursor_session_info is select sid,serial# from v$session where type!='BACKGROUND' and status='INACTIVE' and last_call_et>2700 and username='ICWEB' and machine='orc';
BEGIN
open cursor_session_info;
loop
fetch cursor_session_info into v_sid,v_serial;
exit when cursor_session_info%notfound;
killer:='alter system disconnect session '''||v_sid||','||v_serial||''' post_transaction immediate';
execute immediate killer;
end loop;
dbms_output.PUT_LINE(cursor_session_info%rowcount||' users with idle_time>2700s have been killed!');
close cursor_session_info;
END;
/oracle
這樣作其實仍是治標不治本,最好可以解決鏈接池自動釋放idle進程的問題工具