2014-09-18 63 views
0

我想爲Oracle寫kill_inactive會話存儲過程。
Oracle殺死非活動會話存儲過程

create or replace procedure kill_inactive_sessions as 
begin 
for rec in (select sid, serial# from sys.v_$session where status = 'INACTIVE') 
loop 
    execute immediate 'alter system kill session '''|| rec.sid || ',' || rec.serial# || ''' IMMEDIATE'; 
end loop; 
end kill_inactive_sessions; 

上不起作用(表或視圖不存在)。
但接下來的選擇工作完全適用於相同的用戶:

select sid, serial# from sys.v_$session where status = 'INACTIVE'; 

什麼我失蹤?

+1

首先,定義「不起作用」。它會拋出一個錯誤嗎?什麼錯誤?它沒有做你期望的事嗎?其次,你爲什麼要這樣做?你是否意識到絕大多數時間大多數會議都不活動?你會殺死每個不在該特定時刻運行SQL語句的會話。這將導致大量用戶出錯並立即立即登錄。 – 2014-09-18 23:04:58

+0

我受限於用戶連接的數量。我非常確定,在非正常關閉應用程序之後,大部分會話將不會被使用(在運行單元測試之後,應用程序被終止)。所以我試圖釋放那些不會被使用的會話。 – 2014-09-18 23:09:43

+0

你「如何限制用戶連接的數量」?你是指某種數據庫限制嗎?我假設你的應用程序是一個三層應用程序,所以「非正常關機」意味着應用程序服務器崩潰了。通常,我會在數據庫中啓用無連接檢測,以便數據庫可以清理客戶端更有效終止的連接。但在特定情況下,您肯定只想要終止特定用戶的會話,但並非所有非活動用戶。 – 2014-09-18 23:17:16

回答

3

ORA-00942:表或視圖不存在錯誤幾乎肯定表明您訪問v$session視圖是通過角色而不是直接授予。

如果要編寫定義者的權限存儲過程,則過程的所有者必須具有直接授予用戶的必要權限,而不是通過角色(並且記住DBA只是另一個角色)。最有可能的是,如果您在會話中禁用了角色,則該過程之外的SELECT聲明將不起作用。在SQL * Plus中,例如

SQL> set role none; 
SQL> select sid, serial# from sys.v_$session where status = 'INACTIVE'; 

可能會拋出相同的ORA-00942錯誤。假設它,你需要直接授予擁有存儲過程權限的用戶。例如

GRANT SELECT ANY DICTIONARY 
    TO user_that_owns_the_procedure; 

同樣的事情也將適用於ALTER SYSTEM命令,你正在構建和運行。存儲過程的所有者需要擁有特權才能通過直接授予而不是通過角色來運行該命令。

所有這一切說,殺死所有非活動會話的過程是非常成問題的。絕大多數會議在絕大多數時間都將不活躍。這並不意味着他們應該被殺死。即使在應用程序服務器崩潰後您正在清理,您也應該應用一些額外的謂詞(例如,從特定計算機查找以應用程序服務器崩潰之前建立的特定用戶身份登錄的會話) 。但長期來看,我建議enabling dead connection detection,這樣當客戶端進程意外死亡時,數據庫可以自動處理關閉會話。