我想为Oracle编写kill_inactive会话存储过程
之类的东西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';
我缺少什么?
答案 0 :(得分: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,这样当客户端进程意外死亡时,数据库可以自动处理关闭会话。