【问题标题】:Oracle kill inactive sessions stored procedureOracle 杀死非活动会话存储过程
【发布时间】:2014-11-13 10:50:29
【问题描述】:

我想为 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';

我错过了什么?

【问题讨论】:

  • 首先,定义“不起作用”。它会抛出错误吗?什么错误?它不会做你期望它做的事情吗?其次,你到底为什么要这样做?您是否意识到大多数会话在绝大多数时间都处于非活动状态?您将杀死在那个特定时刻没有运行 SQL 语句的每个会话。这将导致大量用户出现错误并立即重新登录。
  • 我受限于用户连接数。我很确定,在我的应用程序非正常关闭后,大多数会话都不会被使用(在运行单元测试之后,应用程序就被杀死了)。所以我正在尝试释放不再使用的会话。
  • 您如何“受限于用户连接数”?您是指某种数据库限制吗?我假设您的应用程序是一个三层应用程序,因此“非正常关闭”意味着应用程序服务器崩溃。一般来说,我会在数据库中启用死连接检测,以便数据库可以更有效地清理客户端终止的连接。但是,在特定情况下,您肯定只想终止特定用户的会话,而不是所有非活动用户。

标签: oracle stored-procedures plsql


【解决方案1】:

ORA-00942: table or view does not exist 错误几乎肯定表明您对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 以便在客户端进程意外终止时数据库可以自动处理关闭会话。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-03
    • 2014-12-07
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 2011-10-29
    相关资源
    最近更新 更多