Jak*_*sel 6 oracle oracle-11g-r2
我希望能够终止给定用户的活动会话,然后删除该用户,并在单个数据库调用中执行此操作。这是我到目前为止所拥有的:
DECLARE
cursor c is select *
from v$session
where username = 'USER_9FFB9';
c_row c%ROWTYPE;
begin
open C;
loop
FETCH c INTO c_row;
EXIT WHEN c%NOTFOUND;
execute immediate 'alter system kill session ''' ||
c_row.sid || ',' || c_row.serial# || '''';
execute immediate 'drop user user_9FFB9 cascade';
end loop;
end;
/
Run Code Online (Sandbox Code Playgroud)
这样做的问题是,当我在终止会话调用后立即添加 drop user 调用时,我会返回此错误:
ORA-01940: cannot drop a user that is currently connected
Run Code Online (Sandbox Code Playgroud)
但是,如果我在单独的语句中仅等待几秒钟后执行 drop user 语句,它就可以正常工作。我需要做什么才能终止会话并一次性删除用户?v$session 上是否有我应该做的循环,检查它是否仍然打开?
更新 我已经将我的脚本更新为:
DECLARE
cursor c is select *
from v$session
where username = 'USER_abc';
c_row c%ROWTYPE;
begin
open C;
loop
FETCH c INTO c_row;
EXIT WHEN c%NOTFOUND;
execute immediate 'alter user USER_abc ACCOUNT LOCK';
execute immediate 'alter system kill session ''' ||
c_row.sid || ',' || c_row.serial# || '''';
end loop;
DBMS_LOCK.SLEEP(5);
end;
/
drop user user_abc cascade
Run Code Online (Sandbox Code Playgroud)
但是,我仍然收到此错误:
ORA-01940: cannot drop a user that is currently connected
Run Code Online (Sandbox Code Playgroud)
是否有commit
我需要添加的类似内容?
完成的脚本
在 Justin Cave 的帮助下,这是我的最终脚本,效果很好:
DECLARE
l_cnt integer;
BEGIN
EXECUTE IMMEDIATE 'alter user user_#databaseName# account lock';
FOR x IN (SELECT *
FROM v$session
WHERE username = 'USER_#databaseName#')
LOOP
EXECUTE IMMEDIATE 'alter system disconnect session ''' || x.sid || ',' || x.serial# || ''' IMMEDIATE';
END LOOP;
-- Wait for as long as it takes for all the sessions to go away
LOOP
SELECT COUNT(*)
INTO l_cnt
FROM v$session
WHERE username = 'USER_#databaseName#';
EXIT WHEN l_cnt = 0;
dbms_lock.sleep( 2 );
END LOOP;
EXECUTE IMMEDIATE 'drop user user_#databaseName# cascade';
END;
Run Code Online (Sandbox Code Playgroud)
显然#databaseName# 是一个简单值的占位符,比如 ABC。谢谢贾斯汀!
当您发出 时ALTER SYSTEM KILL SESSION
,Oracle 仅将会话标记为已终止并执行异步终止会话的实际工作。这可能只需要几秒钟,如果会话有一个未提交的事务,它做了很多现在必须回滚的工作,或者如果会话需要保持在终止状态以通知客户端,他们的会话已终止。因此,可能需要大量等待才能让用户掉线。
你可以做这样的事情,你的循环将无限期地等待所有会话消失。
DECLARE
l_cnt integer;
BEGIN
EXECUTE IMMEDIATE 'alter user abc_user account lock';
FOR x IN (SELECT *
FROM v$session
WHERE username = 'ABC_USER')
LOOP
EXECUTE IMMEDIATE 'alter system kill session ''' || x.sid || ',' || x.serial# || '''';
END LOOP;
-- Wait for as long as it takes for all the sessions to go away
LOOP
SELECT COUNT(*)
INTO l_cnt
FROM v$session
WHERE username = 'ABC_USER';
EXIT WHEN l_cnt = 0;
dbms_lock.sleep( 10 );
END LOOP;
EXECUTE IMMEDIATE 'drop user abc_user cascade';
END;
Run Code Online (Sandbox Code Playgroud)
不过,一般来说,我会质疑您要解决的问题。我想不出很多次在您决定发布删除时删除具有活动会话的用户是有意义的。在绝大多数情况下,活动会话的存在强烈暗示不应删除该帐户。
归档时间: |
|
查看次数: |
14559 次 |
最近记录: |