last_successful_login_time常为空,因该字段异步更新、仅非-sys用户触发、受认证方式和补丁竞态影响;推荐用v$active_session_history或统一审计追踪登录。

LAST_SUCCESSFUL_LOGIN_TIME 字段在 DBA_USERS 视图中确实存在,但默认不可见——它只对具备 SELECT_CATALOG_ROLE 或 DBA 权限的用户开放,且在 19c 中该字段值可能为空或不更新,尤其当数据库未启用对应审计/登录跟踪机制时。
直接查 DBA_USERS.LAST_SUCCESSFUL_LOGIN_TIME 为什么常为空?
这个字段不是实时写入的,而是由 Oracle 内部异步刷新(通过后台 job 或登录触发),且受以下条件限制:
- 仅非-
SYS用户的登录才会尝试更新该字段(SYS用户始终为NULL) - 若数据库启用了
SEC_CASE_SENSITIVE_LOGON=FALSE或使用了外部认证(如 OS auth、LDAP),该字段通常不会更新 - 从 12c 到 19c 的多个 RU 补丁中,该字段更新逻辑存在竞态问题,导致部分登录成功后仍不写入
-
DBA_USERS查询本身不触发刷新,它只是读快照;你看到的空值,大概率是“还没来得及写”,不是“没发生过”
用 V$SESSION 和 V$ACTIVE_SESSION_HISTORY 倒推最近登录
更可靠的方式是查会话历史,因为只要用户连进来执行过语句,就会留下痕迹。关键点:
-
V$SESSION只保留当前活跃会话,断开即消失 -
V$ACTIVE_SESSION_HISTORY(ASH)保留最近 1 小时(默认)的采样记录,可通过SAMPLE_TIME和USER_ID关联用户 - 需要
SELECT_CATALOG_ROLE或DBA才能访问V$视图
示例 SQL(查过去 7 天内每个用户的最后活动时间):
SELECT u.username,
MAX(ash.sample_time) AS last_active_time
FROM v$active_session_history ash
JOIN dba_users u ON ash.user_id = u.user_id
WHERE ash.sample_time > SYSDATE - 7
GROUP BY u.username
ORDER BY last_active_time DESC;
启用 AUDIT 才能真正捕获“登录成功”事件
如果业务要求精确到秒级的登录时间(含失败尝试),必须开启标准审计:
- 执行
AUDIT CREATE SESSION;(需ADMINISTER DATABASE AUDIT OPERATIONS权限) - 审计记录存于
UNIFIED_AUDIT_TRAIL(统一审计)或DBA_AUDIT_SESSION(传统审计) - 查成功登录:
SELECT username, event_timestamp FROM unified_audit_trail WHERE audit_type = 'STANDARD' AND action_name = 'LOGON' AND return_code = 0 ORDER BY event_timestamp DESC; - 注意:开启审计会带来 I/O 开销,生产环境建议只对关键用户或时间段启用
别依赖 LAST_SUCCESSFUL_LOGIN_TIME 做权限清理决策
很多 DBA 想靠它识别“僵尸账号”然后批量 DROP,这是高危操作。真实场景中:
- 应用连接池复用会话,
LAST_SUCCESSFUL_LOGIN_TIME显示的是连接池首次建连时间,而非业务最后一次调用时间 - 某些 ETL 工具或定时任务只连一次、跑完就断,时间戳会严重滞后
- 查询
V$SESSION_CONNECT_INFO中的LOGON_TIME更接近真实连接时刻,但它只存在于当前会话中,无法回溯
真要清理闲置用户,建议组合策略:查 UNIFIED_AUDIT_TRAIL + 查应用日志 + 人工确认,而不是单看一个字段。











