【问题标题】:Dropping connected users in Oracle database删除 Oracle 数据库中的已连接用户
【发布时间】:2013-03-17 21:25:20
【问题描述】:

我想使用 sqlplus 删除 Oracle DB 中的一些用户,但出现错误:

SQL> DROP USER test CASCADE;
DROP USER test CASCADE
*
ERROR at line 1:
ORA-01940: cannot drop a user that is currently connected

我按照 SO 中的链接查找会话 - Dropping a connected user from an Oracle 10g database schema

但是当我运行命令时,我没有得到任何结果:

SQL> select sid,serial# from v$session where username = 'test';

no rows selected

请帮助我在这种情况下如何删除用户。

【问题讨论】:

  • 你的答案可能在这里:anilanbu.blogspot.com/2012/02/…
  • 我试过了,但是当我试图找出会话时,我没有得到任何行。
  • 我发现了为什么我没有得到会话记录,我的 where 条件应该是 username='TEST'
  • @user2065083-如果您仍然得到 ORA-01940:... 则再次检查查询。

标签: oracle


【解决方案1】:

v$session(和数据字典视图)中的用户都是大写字母。如果您匹配大写字母,您应该会找到要杀死的会话。

SELECT s.sid, s.serial#, s.status, p.spid 
  FROM v$session s, v$process p 
 WHERE s.username = 'TEST' --<<<--
  AND p.addr(+) = s.paddr
 /

为用户 TEST 传递实际 SID 和 SERIAL# 值,然后删除用户...:

ALTER SYSTEM KILL SESSION '<SID>, <SERIAL>'
/

【讨论】:

  • @SkylarSaveland select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v$session where username = '&lt;your_schema&gt;' 会为你做这件事。
  • 如下所述,可能需要执行alter system kill ... immediate;
  • 只有在 v$session 中有一行的情况下才能解决问题。如果没有——这发生在我之前的 drop 命令中途失败时——那么只有stackoverflow.com/a/21700385/1081849 中描述的关机/重启对我有用。
【解决方案2】:

解决方案:

以 sysdaba 身份登录:

sqlplus  / as sysdba

然后:

sql>Shutdown immediate;

sql>startup restrict;

sql>drop user TEST cascade;

如果您想正常重新激活数据库,请重置服务器或:

sql>Shutdown immediate;

sql>startup;

:)

【讨论】:

  • 实际的最佳解决方案。
  • 您还可以使用以下命令恢复 RESTRICT 选项:ALTER SYSTEM DISABLE RESTRICTED SESSION;
  • 拜托,重新启动服务器以删除帐户远非最佳解决方案。考虑生产环境。这是一个非常糟糕的主意。为了防止用户在您终止会话时重新连接,您可以先锁定帐户,然后终止使用该用户名的所有会话,然后删除该帐户。无需为此重新启动服务器。
  • 如果你连接到一个可插拔的数据库,SHUTDOWN IMMEDIATE 可以锁定你。就我而言,我立即收到“ORA-12514:TNS:listener 目前不知道连接描述符中请求的服务”并断开连接。幸运的是,机器上的另一个帐户已正确设置其环境以连接并重新启动。
  • OP 已使用错误的大小写搜索用户,因此未找到任何行。但是,在我的情况下,之前的 drop user 命令在中途失败,使我的数据库处于无法再删除用户和用户但无法在 v$session 中找到行的状态。只有这个答案为我解决了。
【解决方案3】:

问题已通过以下程序解决:

DECLARE
  v_user_exists NUMBER;
  user_name CONSTANT varchar2(20) := 'SCOTT';
BEGIN
  LOOP
    FOR c IN (SELECT s.sid, s.serial# FROM v$session s WHERE upper(s.username) = user_name)
    LOOP
      EXECUTE IMMEDIATE
        'alter system kill session ''' || c.sid || ',' || c.serial# || ''' IMMEDIATE';
    END LOOP;
    BEGIN
      EXECUTE IMMEDIATE 'drop user ' || user_name || ' cascade';
      EXCEPTION WHEN OTHERS THEN
      IF (SQLCODE = -1940) THEN
        NULL;
      ELSE
        RAISE;
      END IF;
    END;
    BEGIN
      SELECT COUNT(*) INTO v_user_exists FROM dba_users WHERE username = user_name;
      EXIT WHEN v_user_exists = 0;
    END;
  END LOOP;
END;
/

【讨论】:

    【解决方案4】:

    做一个查询:

    SELECT * FROM v$session s;

    找到您的用户并执行下一个查询(使用适当的参数):

    ALTER SYSTEM KILL SESSION '&lt;SID&gt;, &lt;SERIAL&gt;';

    【讨论】:

      【解决方案5】:

      进入管理工具中的服务并选择 oracleserviceSID 并重新启动它

      【讨论】:

        【解决方案6】:

        我试图按照此处描述的流程进行操作 - 但没有运气完全终止会话。然后我喜欢这里的额外步骤:
        http://wyding.blogspot.com/2013/08/solution-for-ora-01940-cannot-drop-user.html

        我做了什么:
        1. select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v$session where username = '&lt;your_schema&gt;'; - 如下所述。
        输出将是这样的:
        alter system kill session '22,15' immediate;
        2. alter system disconnect session '22,15' IMMEDIATE ; - 22-sid, 15-serial - 对从前一个命令返回的每个会话重复该命令
        3. 重复步骤 1-2 而select... 不返回空表
        4. 打电话 drop user...

        错过了什么 - 为 select 'alter system kill session '.. 返回的每个会话调用 alter system disconnect session '22,15' IMMEDIATE ;

        【讨论】:

        • 您应该在第一个答案中添加评论。
        【解决方案7】:

        如果您使用 RAC,则需要使用 GV$* 视图而不是 V$*。 尝试通过

        找到您的会话
        select * from gv$session where username = 'test';
        

        然后你可以通过

        终止会话
        alter system kill session 'sid, serial#, @inst_id' immediate;
        

        【讨论】:

          【解决方案8】:

          这可以很简单:

          SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
          
          SQL> DROP USER test CASCADE;
          
          SQL> ALTER SYSTEM DISABLE RESTRICTED SESSION;
          

          【讨论】:

            【解决方案9】:

            我遇到了同样的问题,默认的 Oracle 配置会影响字母寄存器。确切地说,我的 Scheme_Name 全部是大写字母。如果您使用的是 Oracle S,您可以在“其他用户”选项卡上看到您的 Scheme_Name

            【讨论】:

              【解决方案10】:

              基本上我认为杀死所有会话应该是解决方案,但是......

              我发现了类似的讨论 - https://community.oracle.com/thread/1054062 来解决我的问题,那是我没有针对该用户的会话,但我仍然收到错误消息。我也尝试了第二个最佳答案:

              sql>Shutdown immediate;
              
              sql>startup restrict;
              
              sql>drop user TEST cascade;
              

              最后对我有用的是以用户身份登录,手动删除所有表 - 选择创建删除语句是

              select 'drop table ' || TABLE_NAME || ';'  from user_tables;
              

              (因引用需要重新运行多次)

              我不知道这有什么关系,我还删除了函数和序列(因为这就是我在架构中的全部内容)

              当我这样做并注销时,我在v$session 表中有几个会话,当我杀死这些会话时,我能够删除用户。

              我的数据库仍以受限模式启动(不确定是否重要)。

              可能会帮助别人。

              顺便说一句:我的 Oracle 版本是 Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

              【讨论】:

                【解决方案11】:

                有时Oracle drop user 需要很长时间才能执行。在这种情况下,用户可能已连接到数据库。更好的是,您可以终止用户会话并删除用户。

                SQL&gt; select 'alter system kill session ''' || sid || ',' || serial# || ''' immediate;' from v$session where username ='&amp;USERNAME';

                SQL&gt; DROP USER barbie CASCADE;

                【讨论】:

                  【解决方案12】:
                  //'SYS' is username from where you wanted to kill session'
                  SELECT * FROM DBA_TAB_PRIVS WHERE GRANTEE = 'SYS';
                  
                  **Step 1:**
                  
                  CREATE OR REPLACE PROCEDURE sys.kill_session(p_sid NUMBER, p_serial NUMBER)
                  AS
                  v_user VARCHAR2(30);
                  BEGIN
                  SELECT MAX(username)
                  INTO v_user
                  FROM v$session
                  WHERE sid = p_sid
                  AND serial# = p_serial;
                  **Step 2**
                  create or replace procedure kill_session( p_sid in number, p_serial# in number)
                   is v_count pls_integer;
                   BEGIN
                   select count(*) into v_count
                   from V$session
                   where username = 'SYS'
                   and sid = p_sid
                   and serial# = p_serial# ;
                   if ( v_count = 1 )
                   then
                   execute immediate '
                   alter system kill session ''' ||
                   to_char(p_sid,'999999')||','||
                   to_char(p_serial#,'999999')||'''';
                   else
                   raise_application_error( -20001,
                   'You do not own session ''' ||
                   p_sid || ',' || p_serial# ||
                   '''' );
                  end if;
                   END;
                   /
                   
                  **Step 3**
                   grant execute on kill_session to SYS;
                  **Step 4**
                  select inst_id, sid, serial#, username, action, program, service_name, con_id from gv$session where username like 'FCM_469';
                  Check there will be no sessions now
                  **Step 5**
                  DROP USER USER_345 CASCADE;
                  Output:User Dropped
                   
                  

                  【讨论】:

                    【解决方案13】:

                    以下是我在 Oracle 数据库中“自动”删除连接用户的方法:

                    # A shell script to Drop a Database Schema, forcing off any Connected Sessions (for example, before an Import) 
                    # Warning! With great power comes great responsibility.
                    # It is often advisable to take an Export before Dropping a Schema
                    
                    if [ "$1" = "" ] 
                    then
                        echo "Which Schema?"
                        read schema
                    else
                        echo "Are you sure? (y/n)"
                        read reply
                        [ ! $reply = y ] && return 1
                        schema=$1
                    fi
                    
                    sqlplus / as sysdba <<EOF
                    set echo on
                    alter user $schema account lock;
                    -- Exterminate all sessions!
                    begin     
                      for x in ( select sid, serial# from v\$session where username=upper('$schema') )
                      loop  
                       execute immediate ( 'alter system kill session '''|| x.Sid || ',' || x.Serial# || ''' immediate' );  
                      end loop;  
                      dbms_lock.sleep( seconds => 2 ); -- Prevent ORA-01940: cannot drop a user that is currently connected
                    end;
                    /
                    drop user $schema cascade;
                    quit
                    EOF
                    

                    【讨论】:

                      猜你喜欢
                      • 2010-09-10
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-11-11
                      • 2015-09-11
                      相关资源
                      最近更新 更多