This post is also available in:
Sua aplicação parou de conectar e o erro é direto:
ORA-28000: the account is lockedou:
ORA-28001: the password has expiredAntes de sair rodando ALTER USER, o primeiro passo é descobrir o estado real da conta. Quem responde isso é a coluna ACCOUNT_STATUS da view DBA_USERS. Ela diz se a conta está aberta, bloqueada, com senha expirada, ou uma combinação disso. Cada estado pede uma ação diferente, e desbloquear no escuro só adia o problema.
Como checar o status
SELECT username, account_status
FROM dba_users
WHERE username = 'APP_USER';USERNAME ACCOUNT_STATUS
----------- --------------------------------
APP_USER LOCKED(TIMED)💡 Use sempre
DBA_USERSpara diagnóstico. AALL_USERStraz menos colunas e nem sempre te dá o status completo.
A fonte da verdade: user_astatus_map
Não decore a lista de valores. O próprio banco tem ela. A tabela user_astatus_map mostra todos os estados possíveis na sua versão:
SELECT * FROM user_astatus_map; STATUS# STATUS
---------- --------------------------------
0 OPEN
1 EXPIRED
2 EXPIRED(GRACE)
4 LOCKED(TIMED)
8 LOCKED
5 EXPIRED & LOCKED(TIMED)
6 EXPIRED(GRACE) & LOCKED(TIMED)
9 EXPIRED & LOCKED
10 EXPIRED(GRACE) & LOCKED
32 OPEN & IN ROLLOVER
33 EXPIRED & IN ROLLOVER
36 LOCKED(TIMED) & IN ROLLOVER
37 EXPIRED & LOCKED(TIMED) & IN ROLLOVER
40 LOCKED & IN ROLLOVER
41 EXPIRED & LOCKED & IN ROLLOVER💡 O
STATUS#é um bitmask. Cada estado é a soma de flags base. Se a sua versão não suportar gradual password rollover, você verá apenas os 9 primeiros valores (sem os& IN ROLLOVER).
O que cada estado significa
São 6 flags base. Todos os 15 valores do user_astatus_map são combinações deles somados.
| Flag base | STATUS# | O que aconteceu | Ação |
|---|---|---|---|
OPEN | 0 | Conta ativa, senha válida. | Nenhuma. |
EXPIRED | 1 | A senha expirou (política ou expiração manual). | Redefinir a senha. |
EXPIRED(GRACE) | 2 | A senha entrou no período de tolerância (PASSWORD_GRACE_TIME). Ainda conecta, mas avisa. | Trocar a senha antes de virar EXPIRED. |
LOCKED(TIMED) | 4 | Bloqueio automático após FAILED_LOGIN_ATTEMPTS tentativas erradas. | Desbloquear, ou esperar o PASSWORD_LOCK_TIME expirar. |
LOCKED | 8 | Bloqueio manual feito pelo DBA (ACCOUNT LOCK). | Desbloquear manualmente. Não se resolve sozinho. |
IN ROLLOVER | 32 | Senha em rollover gradual: a antiga e a nova valem ao mesmo tempo. | Concluir a migração e encerrar o período. |
A leitura das combinações é só a soma. Exemplos:
9 = 1 + 8=EXPIRED & LOCKED5 = 1 + 4=EXPIRED & LOCKED(TIMED)37 = 1 + 4 + 32=EXPIRED & LOCKED(TIMED) & IN ROLLOVER
⚠️ A distinção que mais confunde:
LOCKED(8) é ação humana, alguém rodouACCOUNT LOCK.LOCKED(TIMED)(4) é o banco bloqueando após N falhas de login. Se você vêLOCKED(TIMED)voltando toda hora, não é manutenção: é tentativa de login com senha errada (app com senha velha, job mal configurado, brute force). Ache a origem antes de só desbloquear.
IN ROLLOVER: o estado novo que pega gente desprevenida
Se o status traz & IN ROLLOVER, a conta está em gradual password rollover. Esse recurso chegou no Oracle 21c e foi backportado para o 19c a partir do 19.12. Ele permite trocar a senha de um usuário e manter a senha antiga válida por um período, para as aplicações migrarem sem downtime.
Durante esse período, a conta mostra, por exemplo:
OPEN & IN ROLLOVERe tanto a senha antiga quanto a nova funcionam ao mesmo tempo.
Ativar no profile (valor em dias, mínimo 1 hora = 1/24, máximo 60 dias ou o menor entre PASSWORD_LIFE_TIME e PASSWORD_GRACE_TIME):
ALTER PROFILE app_profile LIMIT PASSWORD_ROLLOVER_TIME 1;Encerrar o rollover antes do prazo (corta a senha antiga na hora):
ALTER USER app_user EXPIRE PASSWORD ROLLOVER PERIOD;Desligar o recurso no profile:
ALTER PROFILE app_profile LIMIT PASSWORD_ROLLOVER_TIME 0;Como resolver cada caso
Da ação mais segura para a mais agressiva.
Conta bloqueada (LOCKED ou LOCKED(TIMED)):
ALTER USER app_user ACCOUNT UNLOCK;⚠️ Se for
LOCKED(TIMED), desbloquear sem achar a origem das falhas só adia o problema: a conta trava de novo no próximo ciclo de tentativas erradas. Cheque o listener log e a auditoria para ver qual host está tentando com senha velha.
Senha expirada (EXPIRED ou EXPIRED(GRACE)):
⚠️ Trocar a senha de um usuário de aplicação derruba conexões que ainda usam a senha antiga. No 19.12+ e 21c, prefira o gradual password rollover para fazer a troca sem downtime.
ALTER USER app_user IDENTIFIED BY nova_senha;Bloqueada e expirada ao mesmo tempo (ex.: EXPIRED & LOCKED):
ALTER USER app_user ACCOUNT UNLOCK;
ALTER USER app_user IDENTIFIED BY nova_senha;Reproduzindo cada estado em lab
Quer provocar cada estado e ver o account_status mudar? Crie três profiles dedicados e um usuário de teste. Cada cenário só aponta o profile certo, sem ALTER PROFILE de ida e volta. Rode tudo dentro de uma PDB.
Setup
-- Profiles dedicados (cria uma vez)
CREATE PROFILE lab_base LIMIT
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LOCK_TIME 1/1440; -- 1 min: garante LOCKED(TIMED) e auto-unlock rapido
CREATE PROFILE lab_grace LIMIT
PASSWORD_LIFE_TIME 1/1440 -- 1 min
PASSWORD_GRACE_TIME 1/1440; -- 1 min
CREATE PROFILE lab_rollover LIMIT
PASSWORD_LIFE_TIME UNLIMITED
PASSWORD_GRACE_TIME UNLIMITED
PASSWORD_ROLLOVER_TIME 1/24; -- 1 hora (minimo permitido)
-- Usuario de teste, comeca no profile base
CREATE USER lab_user IDENTIFIED BY "Senha#123" PROFILE lab_base;
GRANT CREATE SESSION TO lab_user;
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- OPEN⚠️ Não dá pra juntar tudo num profile só. O
PASSWORD_ROLLOVER_TIMEprecisa ser no mínimo 1 hora e no máximo o menor entrePASSWORD_LIFE_TIMEePASSWORD_GRACE_TIME. Como o cenário de grace usa 1 minuto, grace curto e rollover são mutuamente exclusivos no mesmo profile. Juntar os dois retornaORA-65211.
⚠️ Se o
PASSWORD_LOCK_TIMEforUNLIMITED, o bloqueio por falhas aparece comoLOCKED(sem TIMED), porque a conta nunca destrava sozinha. Por isso olab_basefixa um valor finito.
LOCKED (bloqueio manual)
ALTER USER lab_user PROFILE lab_base;
ALTER USER lab_user ACCOUNT LOCK;
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- LOCKED
ALTER USER lab_user ACCOUNT UNLOCK;
-- volta para OPENLOCKED(TIMED) (bloqueio automático)
Esse cenário depende do FAILED_LOGIN_ATTEMPTS e do PASSWORD_LOCK_TIME, então garanta o lab_base antes:
ALTER USER lab_user PROFILE lab_base;
-- erre a senha 3x (FAILED_LOGIN_ATTEMPTS), cada uma retorna ORA-01017
CONNECT lab_user/senha_errada
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- LOCKED(TIMED)O auto-unlock por tempo é lazy: o Oracle só reavalia o lock no próximo login, não por um timer em background. Por isso a DBA_USERS continua mostrando LOCKED(TIMED) mesmo depois do PASSWORD_LOCK_TIME passar, até alguém tentar conectar.
-- opcao 1: desbloqueio manual, imediato
ALTER USER lab_user ACCOUNT UNLOCK;
-- opcao 2: passado o PASSWORD_LOCK_TIME (1 min neste lab), conecte com a senha correta.
-- o login dispara a reavaliacao, conecta, e o status volta para OPEN
CONNECT lab_user/"Senha#123"⚠️ Consultar a
DBA_USERSnão destrava nada. Só uma tentativa de login reavalia oPASSWORD_LOCK_TIME. Esperar e darSELECTde novo vai continuar mostrandoLOCKED(TIMED).
EXPIRED (expiração manual)
ALTER USER lab_user PROFILE lab_base;
ALTER USER lab_user PASSWORD EXPIRE;
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- EXPIRED
ALTER USER lab_user IDENTIFIED BY "Senha#123";
-- volta para OPENEXPIRED(GRACE) (tolerância por tempo)
Esse depende de tempo passar. Troque para o lab_grace, reinicie o relógio da senha, espere e conecte:
ALTER USER lab_user PROFILE lab_grace;
ALTER USER lab_user IDENTIFIED BY "Senha#123"; -- reinicia o relogio da senha
-- espere ~1 minuto e conecte (a conexao dispara a verificacao)
CONNECT lab_user/"Senha#123"
-- Aviso ORA-28002: the password will expire within ... days
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- EXPIRED(GRACE)Passado o PASSWORD_GRACE_TIME, o status vira EXPIRED. Para limpar, volte ao profile base e redefina a senha:
ALTER USER lab_user PROFILE lab_base;
ALTER USER lab_user IDENTIFIED BY "Senha#123";OPEN & IN ROLLOVER (rollover gradual)
Precisa de 19.12+ ou 21c. Troque para o lab_rollover e mude a senha:
ALTER USER lab_user PROFILE lab_rollover;
ALTER USER lab_user IDENTIFIED BY "NovaSenha#123";
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- OPEN & IN ROLLOVERDurante o rollover, as duas senhas conectam. Encerre antes do prazo (só a nova continua válida):
ALTER USER lab_user EXPIRE PASSWORD ROLLOVER PERIOD;
-- volta para OPENCombinações
É só somar os gatilhos. Exemplo de EXPIRED & LOCKED (no lab_base):
ALTER USER lab_user PROFILE lab_base;
ALTER USER lab_user PASSWORD EXPIRE;
ALTER USER lab_user ACCOUNT LOCK;
SELECT account_status FROM dba_users WHERE username = 'LAB_USER';
-- EXPIRED & LOCKEDLimpeza
DROP USER lab_user CASCADE;
DROP PROFILE lab_base;
DROP PROFILE lab_grace;
DROP PROFILE lab_rollover;Checklist rápido
-- 1. Ver o status atual
SELECT username, account_status FROM dba_users WHERE username = 'APP_USER';
-- 2. Conferir os valores possíveis na sua versão
SELECT * FROM user_astatus_map;
-- 3. Desbloquear
ALTER USER app_user ACCOUNT UNLOCK;
-- 4. Redefinir a senha (cuidado com downtime)
ALTER USER app_user IDENTIFIED BY nova_senha;Referências
- Oracle Database Reference: DBA_USERS
- ORACLE-BASE: Gradual Database Password Rollover Time (PASSWORD_ROLLOVER_TIME)
