Oracle中“被锁”状态包括LOCKED、LOCKED(TIMED)、EXPIRED & LOCKED等非OPEN组合值,LOCK_DATE为空不等于未锁定,需结合account_status字符串、数据库版本及ADG环境综合判断。
查 account_status 字段,到底哪些值算“被锁”?
直接看 account_status 的值,不是只有 locked 才算锁——oracle 用组合字符串表达多重状态,比如 expired & locked 或 locked(timed),都属于实际无法登录的锁定态。
-
LOCKED:DBA 手动执行ALTER USER ... ACCOUNT LOCK,无时间限制,LOCK_DATE可能有值,也可能为NULL(尤其在未修复 Bug 9693615 的旧版本中) -
LOCKED(TIMED):大概率是密码输错超限触发(由FAILED_LOGIN_ATTEMPTS控制),通常伴随非空的LOCK_DATE,但注意:某些补丁缺失版本里这个字段仍可能为NULL -
EXPIRED & LOCKED、EXPIRED(GRACE) & LOCKED(TIMED)等组合态:说明密码已过期 + 账户被锁,必须先改密再解锁,或同时处理
一条 SQL 查清所有异常用户,别只盯一个用户名
别等用户报障了才去查单个账号。日常巡检或排查时,应一次性拉出所有非 OPEN 状态的用户,并带上关键辅助字段。
- 执行:
SELECT username, account_status, lock_date, expiry_date, profile FROM dba_users WHERE account_status NOT IN ('OPEN', 'EXPIRED(GRACE)'); -
EXPIRED(GRACE)是宽限期,不算锁,可暂不干预;但EXPIRED & LOCKED就得立刻处理 - 加
profile列是为了后续快速定位策略来源——比如发现一堆用户都是LOCKED(TIMED),就该去查对应 profile 的FAILED_LOGIN_ATTEMPTS
为什么查出来是 OPEN,用户却登不上?小心 ADG 备库同步延迟
在 Oracle ADG 环境下,dba_users.account_status 在备库上可能滞后于主库,尤其是刚执行完 ALTER USER ... ACCOUNT UNLOCK 后立即切到备库验证,容易误判。
- 确认是否 ADG:查
SELECT database_role FROM v$database,备库返回PHYSICAL STANDBY - 主库上解锁后,需等待日志应用完成;可用
SELECT max(sequence#) FROM v$archived_log WHERE applied='YES'对比主备归档号 - 备库上不要依赖
dba_users做登录判断,真实连接测试或查v$session_connect_info更可靠
LOCK_DATE 为空 ≠ 没被锁,版本和补丁才是关键变量
看到 account_status = 'LOCKED(TIMED)' 但 lock_date IS NULL,第一反应不该是“数据不准”,而是查数据库版本和补丁号——这是 Oracle 已知行为,不是你的查询写错了。
- 运行:
SELECT banner_full FROM v$version;
和SELECT action, comments FROM dba_registry_history ORDER BY action_time DESC FETCH FIRST 5 ROWS ONLY;
- 若版本 ≤ 11.2.0.4 且未打 PSU 31103343 或更高,就极可能命中 Bug 9693615:自动锁定不写
LOCK_DATE - 此时更可靠的依据是
account_status字符串本身,以及结合dba_profiles中该用户 profile 的FAILED_LOGIN_ATTEMPTS设置
LOCK_DATE 更可信;而环境拓扑(比如是不是 ADG)、版本补丁细节,往往比 SQL 技巧更能决定你能不能快速定位问题。










