ora-28000是oracle profile安全策略生效所致,非数据库bug;根本原因是default(或指定)profile中failed_login_attempts参数默认值为10,用户累计输错密码达10次即锁定账户,状态变为locked,后续任何连接均报此错。

ORA-28000 锁定不是 bug,是 Profile 安全策略生效
Oracle 用户登录失败多次后被锁,根本原因不是数据库“抽风”,而是 DEFAULT(或用户指定的)PROFILE 中的 FAILED_LOGIN_ATTEMPTS 参数被触发。这个值默认为 10,只要该用户累计输错密码达 10 次(无论来自哪台客户端、哪个应用进程),账户状态就会变成 LOCKED,后续任何连接(哪怕密码正确)都会报 ORA-28000: the account is locked。
关键点在于:FAILED_LOGIN_ATTEMPTS 统计的是“该用户名下的失败次数”,不绑定 IP、不区分会话来源。一台应用服务器重试 7 次 + 另一台重试 3 次 = 立刻锁定。很多“刚解锁又锁”的情况,都是多个服务节点同时用旧密码重连导致的。
为什么设了 FAILED_LOGIN_ATTEMPTS 却没自动解锁?
只改 FAILED_LOGIN_ATTEMPTS 不设 PASSWORD_LOCK_TIME,等于埋了个雷:账户一旦被锁,就永远卡在 LOCKED 状态,除非 DBA 手动执行 ALTER USER ... ACCOUNT UNLOCK。
-
PASSWORD_LOCK_TIME单位是“天”,不是小时或分钟;写60是无效的,Oracle 直接忽略 - 设为
0:失败即锁,但不自动解锁(需人工干预) - 设为
1/24:锁 1 小时;设为1/1440:锁 1 分钟 - 设为
UNLIMITED:彻底锁死,只能 DBA 解锁 - 两个参数必须写在同一句
ALTER PROFILE里,分两次执行可能造成策略不一致
怎么查当前用户到底被谁、什么时候、因为什么锁的?
不能只看 dba_users.account_status,得交叉验证三处信息:
- 查锁定时间:
SELECT username, lock_date FROM dba_users WHERE username = 'SCOTT';(注意:解锁后再查就为空了) - 查失败计数(需 SYS 权限):
SELECT name, lcount FROM sys.user$ WHERE name = 'SCOTT';—— 这个lcount是实时累计值,比 profile 限制更“原始” - 查 profile 实际生效值:
SELECT resource_name, limit FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_name IN ('FAILED_LOGIN_ATTEMPTS', 'PASSWORD_LOCK_TIME'); - 如果怀疑是后台任务(如 job、dblink、scheduler),检查
alert_*.log或bdump下的 trace 文件,搜索ORA-28000和对应用户名
临时放行 or 长期治理?别只盯着 ALTER PROFILE
直接把 FAILED_LOGIN_ATTEMPTS 改成 UNLIMITED 能止痛,但等于关掉安全门。真正要解决反复锁定,得定位背后持续出错的源头:
- 应用配置文件(如 JDBC URL 中的密码)是否更新滞后?ETL 脚本、定时 job、DBLink 的密码有没有同步?
- 连接池是否配置了错误密码,并在启动时疯狂重试?有些框架(如 HikariCP)默认
connection-test-query失败会立即重连,加剧锁定速度 - 是否存在测试脚本、监控探针、开发本地工具,还在用旧凭据轮询连接?
- 修改密码前,务必确认所有依赖方——包括冷备系统、归档脚本、审计中间件——都已同步更新
Profile 参数本身很稳定,但它的效果完全取决于你有没有管住所有“伸手去试密码”的地方。锁住账户的从来不是 Oracle,是那些没被发现的、静默失败的连接请求。











