当前位置:首页 > 问答 > 正文

Oracle数据库里删用户时遇到那个连接着的不能删,咋整啊?

主要综合自Oracle官方文档的常见操作指南、Oracle技术社区如OTN和Oracle Base的实践经验分享,以及像CSDN、博客园这类国内技术平台上DBA们的常见处理方案)

你遇到的这个问题太常见了,几乎每个管Oracle数据库的人都会碰到,你想删一个用户,结果数据库告诉你“不行,这哥们儿还连着线呢”(错误提示通常是ORA-01940: cannot drop a user that is currently connected),这感觉就像你想请一个客人离开房间,但他还在里面打电话,你得先让他挂断电话才能请他出来。

核心思路就一句话:先把这用户的所有连接都断掉,然后再删。

下面就是几种最常用、最直接的办法,你可以根据你手头的权限和现场情况选一个来用。

第一招:查清楚谁在连着,然后精准踢人。

这是最规范、最推荐的做法,你不能蛮干,得先看看是谁、在哪儿连着这个用户。

Oracle数据库里删用户时遇到那个连接着的不能删,咋整啊?

  1. 先查连接情况: 你得用有管理员权限的账号(比如SYSTEM或者SYS)连上数据库,然后跑下面这个查询语句,这个语句在Oracle技术社区里是标准查法。

    SELECT sid, serial#, username, program, machine, status
    FROM v$session
    WHERE username = '你要删的那个用户名'; -- 记得把单引号里的名字换成实际要删的用户名

    跑完这个语句,你会看到一个结果列表,这里面每一行就代表一个连接会话,你要重点关注几个信息:SIDSerial#,这俩合起来是这个会话的唯一身份证;Program 是啥程序连的(比如SQLPlus、某个应用软件);Machine 是从哪台机器连过来的,这样你就知道都是谁在用了。

  2. 再踢掉连接: 看清楚之后,就可以动手踢了,针对每一个你想断开的会话,执行下面的命令:

    ALTER SYSTEM KILL SESSION 'SID, Serial#' IMMEDIATE;

    比如你查到一个会话的SID是123,Serial#是4567,那你的命令就写成 ALTER SYSTEM KILL SESSION '123, 4567' IMMEDIATE;,那个 IMMEDIATE 的意思是让数据库别磨蹭,马上断,并且回滚这个会话里还没提交的事务,Oracle Base网站上的操作指南特别强调了要加这个参数。

    Oracle数据库里删用户时遇到那个连接着的不能删,咋整啊?

    你查到的有几个连接,就执行几次这个命令,确保把所有以这个用户名义连上来的会话都清干净。

  3. 最后删用户: 踢光之后,再执行你原本想做的删除用户命令就行了:

    DROP USER 用户名 CASCADE;

    那个 CASCADE 很重要,意思是把这个用户下面的所有东西(表啊、视图啊什么的)都一块儿删掉,不然如果用户底下有对象,光写DROP USER 用户名还是会报错。

第二招:如果连接太多,图省事儿的办法。

Oracle数据库里删用户时遇到那个连接着的不能删,咋整啊?

你可能发现这个用户的连接一大堆,几十上百个,一个一个踢太麻烦了,这时候有个更粗暴的办法(同样需要管理员权限),就是直接断掉这个用户的所有会话,根据很多DBA在CSDN上分享的脚本,可以这么做:

BEGIN
  FOR session_info IN (SELECT sid, serial# FROM v$session WHERE username = '你要删的用户名')
  LOOP
    EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || session_info.sid || ',' || session_info.serial# || ''' IMMEDIATE';
  END LOOP;
END;
/

这其实是一个PL/SQL的小脚本,它自动帮你把第一招里的查询和踢人动作给批量完成了,跑一下这个脚本,它就会自动清理掉该用户的所有活动连接,完了之后,你再执行 DROP USER ... CASCADE 即可。

第三招:更狠的,重启大法(慎用!)。

如果上面两招都因为某些奇怪的原因不好使(比如会话状态卡死了,成了“幽灵”会话,KILL SESSION 命令也干不掉),或者这个数据库是个测试环境,可以随便折腾,那最后的大招就是重启数据库实例,这是Oracle官方文档里也承认的终极解决方案,因为一重启,所有连接自然就都断了。

这一招杀伤力太大,在生产环境(就是正在跑重要业务的环境)绝对不能用! 除非是在万不得已、并且得到了上级明确批准的情况下,重启会影响所有用户,会导致业务中断。

总结一下和几点提醒:

  • 核心动作: 删用户前,先断其所有连接。v$session 视图是你的情报中心,ALTER SYSTEM KILL SESSION 是你的武器。
  • 权限是关键: 上面这些操作(查询v$sessionKILL SESSIONDROP USER)都需要比较高的数据库权限,通常你得用SYSTEM、SYS或者其他被授予了DBA角色的用户来操作,如果你只是个普通用户,那得找管理员帮你。
  • CASCADE别忘记: 删用户命令一定要加 CASCADE,除非你确认这个用户下面啥东西都没有。
  • 分清环境: 在生产环境操作要格外小心,最好在业务低峰期进行,并提前通知相关人员,踢人之前,最好能确认一下那些连接是啥业务,能不能踢,避免误伤重要的作业。
  • 治本之策: 有时候用户被连接上,是因为有自动化的作业(比如定时任务JOB)或者数据库链接(DBLINK)一直在用,光踢掉会话可能一会儿又连上了,这时候需要找到根源,比如停掉相关的作业,才能彻底解决问题。

希望这些直接从实践中来的方法能帮你搞定这个问题,操作数据库,尤其是删库删用户这种危险动作,小心一点总没错。