Oracle 19c起dba_users新增last_login字段,但需启用统一审计才非空;11g/12c无此字段,必须开启标准审计后查DBA_AUDIT_TRAIL中ACTION_NAME='LOGON'记录。
查不到“最后登录时间”?先确认 Oracle 版本和审计是否开启
oracle 19c 之后才在 dba_users 里加了 last_login 字段;11g/12c 没这个字段,得靠审计日志。但前提是数据库开启了标准审计(audit_trail = db 或 os),否则 dba_audit_session 是空的。
检查命令:show parameter audit_trail
如果返回 none,那下面所有基于 dba_audit_session 的查询都无效——得先开审计,或换用其他线索(比如会话空闲时间、对象创建时间等)。
- 19c+:直接查
dba_users,注意过滤oracle_maintained = 'N'(排除系统用户) - 11g/12c:必须依赖
dba_audit_session,且确保审计已启用、日志未被清理 - 没开审计又想粗略判断?可结合
created时间 +dba_objects中该用户下对象的created或last_ddl_time做辅助判断
查出三个月没登录的非系统用户(19c 示例)
这是最干净的做法,但要注意字段格式和时区问题:last_login 是 timestamp 类型,直接跟 sysdate 相减会报错,得转成 date。
SELECT username, account_status,
TO_CHAR(last_login, 'yyyy-mm-dd hh24:mi:ss') AS last_login,
ROUND((SYSDATE - CAST(last_login AS DATE)) * 24) AS hours_since_login
FROM dba_users
WHERE oracle_maintained = 'N'
AND last_login IS NOT NULL
AND (SYSDATE - CAST(last_login AS DATE)) > 90;- 结果为空不等于“没休眠”,可能是审计没开,或该用户从没成功登录过(
last_login为 null) -
account_status为EXPIRED或LOCKED的用户,大概率已休眠,可一并纳入清理范围 - 别漏掉
username NOT IN ('ANONYMOUS','XS$NULL','GSMADMIN_INTERNAL')这类伪用户,它们不是真业务账号
查出长期空闲但仍在连接的 INACTIVE 会话
很多“休眠用户”其实还挂着 INACTIVE 会话,尤其是用连接池的应用——它不主动断开,数据库就一直留着 session,导致后续 drop user 直接报 ORA-01940。
查这类会话的关键是 last_call_et(秒数),不是 status:
SELECT sid, serial#, username, machine, program,
TO_CHAR(logon_time, 'yyyy-mm-dd hh24:mi') AS logon_time,
last_call_et AS idle_seconds,
ROUND(last_call_et / 3600, 1) AS idle_hours
FROM v$session
WHERE username IS NOT NULL
AND status = 'INACTIVE'
AND last_call_et > 3600 * 24 * 7 -- 空闲超一周
AND username NOT IN (SELECT username FROM dba_users WHERE oracle_maintained = 'Y');-
last_call_et是“上次调用至今的秒数”,比看logon_time更准 - 别只杀
ACTIVE会话——INACTIVE一样拦着drop user - 杀之前建议先
alter system kill session 'sid,serial#',而不是直接kill -9OS 进程,避免事务残留
清理前必须验证的三个硬性条件
跳过任何一条,drop user cascade 都可能失败或留隐患。
- 会话清零:
SELECT COUNT(*) FROM v$session WHERE username = 'YOUR_USER';必须返回0 - 状态归 OPEN:
ALTER USER YOUR_USER ACCOUNT UNLOCK;+ALTER USER YOUR_USER IDENTIFIED BY temp123;(哪怕只是临时重置) - 对象彻底清空:
SELECT COUNT(*) FROM dba_objects WHERE owner = 'YOUR_USER';必须为0;特别注意dba_dependencies里是否有其他用户依赖它的 type/package
删完用户后,表空间不会自动释放——drop tablespace XXX including contents and datafiles 是另一步,而且得先确认该表空间没被其他用户共用(查 dba_segments 的 owner 分布)。


















