Oracle釋放無用連接


給甲方做了一個數據統計分析系統,上百號人在用這個系統,數據庫采用的是oracle9i ,遇到了一個問題: 客戶們經常連接不上服務器,查看了日志文件才發現,連接數量默認最大設置是150,實際上這個連接數是滿足不了要求的,而且不排除這些連接里面有廢掉的。所以通過網絡查找了一些相關資料,可以按照下面的方法解決ORACLE自動刪除廢掉的連接:

 

通過profile可以對用戶會話進行一定的限制,比如IDLE時間。 
  
  將IDLE超過一定時間的會話斷開,可以減少數據庫端的會話數量,減少資源耗用。 
  
  使用這些資源限制特性,需要設置resource_limit為TRUE:

   [oracle@test126 udump]$ sqlplus "/ as sysdba"
 
  SQL> show parameter resource
 
  NAME                                TYPE        VALUE
 
  ------------------------------------ ----------- ------------------------------
 
  resource_limit                      boolean    TRUE
 
  resource_manager_plan                string
 
  該參數可以動態修改:
 
  SQL> alter system set resource_limit=true;
  
  數據庫缺省的PROFILE設置為:
 
  SQL> SELECT * FROM DBA_PROFILES;
 
  PROFILE              RESOURCE_NAME                    RESOURCE LIMIT
 
  -------------------- -------------------------------- -------- ---------------
 
  DEFAULT              COMPOSITE_LIMIT                  KERNEL  UNLIMITED
 
  DEFAULT              SESSIONS_PER_USER                KERNEL  UNLIMITED
 
  DEFAULT              CPU_PER_SESSION                  KERNEL  UNLIMITED
 
  DEFAULT              CPU_PER_CALL                    KERNEL  UNLIMITED
 
  DEFAULT              LOGICAL_READS_PER_SESSION        KERNEL  UNLIMITED
 
  DEFAULT              LOGICAL_READS_PER_CALL          KERNEL  UNLIMITED
 
  DEFAULT              IDLE_TIME                        KERNEL  UNLIMITED
 
  DEFAULT              CONNECT_TIME                    KERNEL  UNLIMITED
 
  DEFAULT              PRIVATE_SGA                      KERNEL  UNLIMITED
 
  DEFAULT              FAILED_LOGIN_ATTEMPTS            PASSWORD 10
 
  DEFAULT              PASSWORD_LIFE_TIME              PASSWORD UNLIMITED
 
  PROFILE              RESOURCE_NAME                    RESOURCE LIMIT
 
  -------------------- -------------------------------- -------- ---------------
 
  DEFAULT              PASSWORD_REUSE_TIME              PASSWORD UNLIMITED
 
  DEFAULT              PASSWORD_REUSE_MAX              PASSWORD UNLIMITED
 
  DEFAULT              PASSWORD_VERIFY_FUNCTION        PASSWORD NULL
 
  DEFAULT              PASSWORD_LOCK_TIME              PASSWORD UNLIMITED
 
  DEFAULT              PASSWORD_GRACE_TIME              PASSWORD UNLIMITED
 
  16 rows selected.
 
  創建一個允許3分鍾IDLE時間的PROFILE:
 
  SQL> CREATE PROFILE KILLIDLE LIMIT IDLE_TIME 3;
 
  Profile created.
新創建PROFILE的內容:
 
  SQL> col limit for a10
 
  SQL> select * from dba_profiles where profile='KILLIDLE';
 
  PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
 
  ------------------------------ -------------------------------- -------- ----------
 
  KILLIDLE                      COMPOSITE_LIMIT                  KERNEL  DEFAULT
 
  KILLIDLE                      SESSIONS_PER_USER                KERNEL  DEFAULT
 
  KILLIDLE                      CPU_PER_SESSION                  KERNEL  DEFAULT
 
  KILLIDLE                      CPU_PER_CALL                    KERNEL  DEFAULT
 
  KILLIDLE                      LOGICAL_READS_PER_SESSION        KERNEL  DEFAULT
 
  KILLIDLE                      LOGICAL_READS_PER_CALL          KERNEL  DEFAULT
 
  KILLIDLE                      IDLE_TIME                        KERNEL  3
 
  KILLIDLE                      CONNECT_TIME                    KERNEL  DEFAULT
 
  KILLIDLE                      PRIVATE_SGA                      KERNEL  DEFAULT
 
  KILLIDLE                      FAILED_LOGIN_ATTEMPTS            PASSWORD DEFAULT
 
  KILLIDLE                      PASSWORD_LIFE_TIME              PASSWORD DEFAULT
 
  PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
 
  ------------------------------ -------------------------------- -------- ----------
 
  KILLIDLE                      PASSWORD_REUSE_TIME              PASSWORD DEFAULT
 
  KILLIDLE                      PASSWORD_REUSE_MAX              PASSWORD DEFAULT
 
  KILLIDLE                      PASSWORD_VERIFY_FUNCTION        PASSWORD DEFAULT
 
  KILLIDLE                      PASSWORD_LOCK_TIME              PASSWORD DEFAULT
 
  KILLIDLE                      PASSWORD_GRACE_TIME              PASSWORD DEFAULT
 
  16 rows selected.
 
  測試用戶:
 
  SQL> select username,profile from dba_users where username='EYGLE';
 
  USERNAME                      PROFILE
 
  ------------------------------ --------------------
 
  EYGLE                          DEFAULT
 
  修改eygle用戶的PROFILE使用新建的PROFILE:
 
  SQL> alter user eygle profile killidle;
 
  User altered.
 
  SQL> select username,profile from dba_users where username='EYGLE';
 
  USERNAME                      PROFILE
 
  ------------------------------ --------------------
 
  EYGLE                          KILLIDLE
 
  進行連接測試:
 
  [oracle@test126 admin]$ sqlplus eygle/eygle@eygle
 
   
  SQL> select username,profile from dba_users where username='EYGLE';
 
  USERNAME                      PROFILE
 
  ------------------------------ ------------------------------
 
  EYGLE                          KILLIDLE
 
  當IDLE超過限制時間時,連接會被斷開:
 
  SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
 
  TO_CHAR(SYSDATE,'YY
 
  -------------------
 
  2006-10-13 08:08:41
 
  SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
 
  select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
 
  *
 
  ERROR at line 1:
 
  ORA-02396: exceeded maximum idle time, please connect again

 

 

1.sqlplus /nolog  
2.打開sqlplus  
3.  
4.  
5.connect system/bianqiwei@orcltns as sysdba   
6.使用具有dba權限得用戶登陸oracle  
7.  
8.  
9.show parameter resource_limit  
10.顯示資源限定是否開啟,value為true是開啟,為false是關閉  
11.  
12.  
13.alter system set resource_limit=true  
14.如果未開啟,則使用此命令開啟資源限定功能  
15.  
16.  
17.create profile profileName limit connect_time 60 idle_time 30  
18.創建profile文件,profileName任意起,connect_time設置連接超過多少分鍾后強制釋放,idle_time設置連續不活動的會話超過多少分鍾后強制釋放  
19.  
20.alter user oracleUser profile profileName  
21.將profile文件作用於指定用戶 

 

   從上周起,服務器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。

 

修改ORACLE 中的SESSION和PROCESS

會話sessions和進程pocesses的關系 
一個process可以有0個、1個或者多個session,一個session也可以存在若干個process中,並行同樣是一個session對應一個process,主session是coordinator session,每個parallel process同樣會對應數據庫里一個單獨的session。可以從v$px_session和v$session中驗證這點。 
連接connects,會話sessions和進程pocesses的關系

每個sql login稱為一個連接(connection),而每個連接,可以產生一個或多個會話,如果數據庫運行在專用服務器方式,一個會話對應一個服務器進程(process),如果數據庫運行在共享服務器方式,一個服務器進程可以為多個會話服務。

Oracle的sessions和processes的數量關系是:sessions=1.1 * processes + 5

下面我們用兩種方法修改PROCESS的最大值 
一、通過Oracle Enterprise Manager Console在圖形化管理器中修改 
以系統管理員的身份登入,進入界面 數據庫的例程 - 配置 - 一般信息 - 所有初始化參數,修改processes的值

二、在SQLPLUS中修改 
以DBA權限登錄,修改PROCESS的值(SESSION的值會跟着改);創建pfile;重新啟動數據庫。輸入的SQL命令如下,回顯信息省略了 
SQL> connect sys/sys as sysdba 
SQL> alter system set processes=400 scope = spfile; 
SQL> create pfile from spfile; 
SQL> shutdown immediate; 
SQL> startup

 

Oracle中Kill session的研究

我們知道,在Oracle數據庫中,可以通過kill session的方式來終止一個進程,其基本語法結構為:

alter system kill session 'sid,serial#' ;

被kill掉的session,狀態會被標記為killed,Oracle會在該用戶下一次touch時清除該進程.

我們發現當一個session被kill掉以后,該session的paddr被修改,如果有多個session被kill,那么多個session
的paddr都被更改為相同的進程地址:

 

SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

SADDR           SID    SERIAL# PADDR    USERNAME                       STATUS
-------- ---------- ---------- -------- ------------------------------ --------
542E0E6C         11        314 542B70E8 EYGLE                          INACTIVE
542E5044         18        662 542B6D38 SYS                            ACTIVE


SQL> alter system kill session '11,314';

System altered.

SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

SADDR           SID    SERIAL# PADDR    USERNAME                       STATUS
-------- ---------- ---------- -------- ------------------------------ --------
542E0E6C         11        314 542D6BD4 EYGLE                          KILLED
542E5044         18        662 542B6D38 SYS                            ACTIVE


SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

SADDR           SID    SERIAL# PADDR    USERNAME                       STATUS
-------- ---------- ---------- -------- ------------------------------ --------
542E0E6C         11        314 542D6BD4 EYGLE                          KILLED
542E2AA4         14        397 542B7498 EQSP                           INACTIVE
542E5044         18        662 542B6D38 SYS                            ACTIVE

SQL> alter system kill session '14,397';

System altered.

SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

SADDR           SID    SERIAL# PADDR    USERNAME                       STATUS
-------- ---------- ---------- -------- ------------------------------ --------
542E0E6C         11        314 542D6BD4 EYGLE                          KILLED
542E2AA4         14        397 542D6BD4 EQSP                           KILLED
542E5044         18        662 542B6D38 SYS                            ACTIVE


 


在這種情況下,很多時候,資源是無法釋放的,我們需要查詢spid,在操作系統級來kill這些進程.

但是由於此時v$session.paddr已經改變,我們無法通過v$session和v$process關聯來獲得spid

那還可以怎么辦呢?

我們來看一下下面的查詢:

   SQL> SELECT s.username,s.status,
  2  x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO,x.KSLLID1R,x.KSLLRTYP,
  3  decode(bitand (x.ksuprflg,2),0,null,1)
  4  FROM x$ksupr x,v$session s
  5  WHERE s.paddr(+)=x.addr
  6  and bitand(ksspaflg,1)!=0;


USERNAME                       STATUS   ADDR       KSLLAPSC   KSLLAPSN KSLLASPO       KSLLID1R KS D
------------------------------ -------- -------- ---------- ---------- ------------ ---------- -- -
                                        542B44A8          0          0                       0
                               ACTIVE   542B4858          1         14 24069                 0    1
                               ACTIVE   542B4C08         26         16 15901                 0    1
                               ACTIVE   542B4FB8          7         46 24083                 0    1
                               ACTIVE   542B5368         12         15 24081                 0    1
                               ACTIVE   542B5718         15         46 24083                 0    1
                               ACTIVE   542B5AC8         79          4 15923                 0    1
                               ACTIVE   542B5E78         50         16 24085                 0    1
                               ACTIVE   542B6228        754         15 24081                 0    1
                               ACTIVE   542B65D8          1         14 24069                 0    1
                               ACTIVE   542B6988          2         30 14571                 0    1

USERNAME                       STATUS   ADDR       KSLLAPSC   KSLLAPSN KSLLASPO       KSLLID1R KS D
------------------------------ -------- -------- ---------- ---------- ------------ ---------- -- -
SYS                            ACTIVE   542B6D38          2          8 24071                 0
                                        542B70E8          1         15 24081               195 EV
                                        542B7498          1         15 24081               195 EV
SYS                            INACTIVE 542B7848          0          0                       0
SYS                            INACTIVE 542B7BF8          1         15 24081               195 EV

16 rows selected.
    
 
 我們注意,紅字標出的部分就是被Kill掉的進程的進程地址.


簡化一點,其實就是如下概念:

SQL> select p.addr from v$process p where pid <> 1  2  minus  3  select s.paddr from v$session s;ADDR
--------
542B70E8
542B7498

 
 Ok,現在我們獲得了進程地址,就可以在v$process中找到spid,然后可以使用Kill或者orakill在系統級來殺掉這些進程.

實際上,我猜測:

當在Oracle中kill session以后, Oracle只是簡單的把相關session的paddr 指向同一個虛擬地址.

此時v$process和v$session失去關聯,進程就此中斷.

然后Oracle就等待PMON去清除這些Session.所以通常等待一個被標記為Killed的Session退出需要花費很長的時間.

如果此時被Kill的process,重新嘗試執行任務,那么馬上會收到進程中斷的提示,process退出,此時Oracle會立即啟動PMON
來清除該session.這被作為一次異常中斷處理

 

轉載於:https://my.oschina.net/sunchenbin/blog/632978


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM