ORA-01940报错本质是v$session中存在目标用户名的会话记录,无论状态为ACTIVE、INACTIVE或KILLED,只要该行未清除,DROP USER即失败;需用ALTER SYSTEM KILL SESSION ... IMMEDIATE强制清理,并检查scheduler job、schemaname及OS进程残留。

ORA-01940 报错本质是会话残留,不是“人还在连”
Oracle 报 ORA-01940: cannot drop a user that is currently connected,根本不是因为你看到有人在用 SQL*Plus 登录——哪怕所有客户端早已关闭、应用也重启过,只要 v$session 里还存着该用户名对应的记录(status 是 ACTIVE、INACTIVE 甚至 KILLED),DROP USER ... CASCADE 就会拒绝执行。
关键点在于:Oracle 不看“连接是否活跃”,只认 v$session 表中是否存在该 username 的行。哪怕状态已是 KILLED,只要那行没消失,就视为“当前已连接”。
ALTER SYSTEM KILL SESSION 后仍删不掉用户?加 IMMEDIATE
ALTER SYSTEM KILL SESSION 'sid,serial#' 默认只是发信号,把状态设为 KILLED,后续靠 PMON 异步清理。如果会话正回滚大事务、持有锁或 PMON 卡住,v$session 记录可能挂几分钟不消失,此时立刻 DROP USER 必然再报 ORA-01940。
- 必须用
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE—— 它跳过等待,强制中断并加速资源释放 - 批量杀时,可用子查询生成语句:
SELECT 'ALTER SYSTEM KILL SESSION ''' || sid || ',' || serial# || ''' IMMEDIATE;' FROM v$session WHERE username = 'XXX';
- 执行后不要马上删用户,先查:
SELECT sid, serial#, status FROM v$session WHERE username = 'XXX',确认结果为空再继续
查不到会话但还是删不掉?检查 scheduler job 和 schemaname
有时 SELECT * FROM v$session WHERE username = 'XXX' 返回空,但 DROP USER 仍失败。原因常是:
- 用户名大小写不匹配:Oracle 默认转大写,查询必须写
WHERE username = 'XXX',不能写小写或混合 - 后台作业以该用户身份运行:
SELECT job_name, owner FROM dba_scheduler_jobs WHERE owner = 'XXX',存在就得先DROP JOB或DISABLE - 连接未显式指定用户名(如 JDBC 连接池复用、监听器转发),导致
username为空,但schemaname是目标用户:SELECT sid, serial#, program, machine FROM v$session WHERE schemaname = 'XXX'
status 已是 KILLED,v$session 还有残留?得杀 OS 进程
当 v$session 显示某会话 status = KILLED,但行一直不消失,说明底层 OS 进程(spid)卡死未回收。这时必须手动终结:
- 查 OS 进程号:
SELECT p.spid, s.sid, s.serial# FROM v$process p, v$session s WHERE p.addr = s.paddr AND s.username = 'XXX';
- Linux 上执行:
kill -9 spid;Windows 上用:orakill <ORACLE_SID> spid - 杀完立刻查
v$session,若仍有残留,别硬删——说明 PMON 没响应或实例异常,此时最稳妥是重启监听器(lsnrctl stop/start),而非直接重启整个实例
真正麻烦的从来不是命令记不住,而是看到 KILLED 就以为万事大吉。OS 层进程没死,数据库就永远认为那个用户“还在连”。


















