Pular para o conteúdo
WaitScope Entrar Solicitar acesso (por e-mail) Menu

Espera por bloqueio de outra sessão

O achado BLOQUEIO aparece quando a classe Application pesa no tempo total: como achar a sessão que segura o lock e corrigir a causa.

Vale para: Traces 10046 com esperas (nível 8 ou 12)

Tempo esperando lock de outra sessão não se resolve no SQL de quem espera: a causa está na transação que segura o lock, e essa transação não aparece no trace. O trabalho é achar quem segura e por quê.

Sintomas

No Diagnóstico, aparece o achado Espera por bloqueio de outra sessão (BLOQUEIO). O texto diz quanto do tempo total ficou na classe de espera Application, em percentual e em segundos, lista os eventos da classe que pesaram e termina com Ver perfil por classe.

O achado aparece quando a classe Application pesa no tempo total. A severidade é média e passa a alta quando a classe pesa mais. Se um evento da classe domina o perfil, o relatório não repete o achado de componente dominante: este achado já trata desse tempo.

Entram na classe Application estes eventos, pela wait_class do Oracle 19c:

  • enq: TX - row lock contention: linha alterada por outra transação que ainda não terminou.
  • enq: TM - contention: lock da tabela inteira.
  • enq: UL - contention: lock pedido pela própria aplicação com DBMS_LOCK.
  • enq: KO - fast object checkpoint e enq: RO - fast object reuse: gravação ou descarte dos blocos do objeto antes de leitura direta, TRUNCATE ou DROP.
  • SQL*Net break/reset to client e SQL*Net break/reset to dblink: chamada interrompida ou erro devolvido ao cliente.

Evento que o relatório não classifica aparece no perfil como Não classificado e não conta para este achado.

Causa

A sessão pediu um lock que outra sessão segurava e ficou parada até ele ser liberado. O título do achado fala em bloqueio, mas o evento que pesa diz o que aconteceu:

  • enq: TX - row lock contention: transação longa ou commit tardio segurando linhas; várias sessões atualizando o mesmo registro (contador, saldo, próximo número de documento); duas sessões inserindo a mesma chave única.
  • enq: TM - contention: quase sempre chave estrangeira sem índice. Ao alterar a chave ou apagar a linha da tabela pai, o Oracle trava a tabela filha inteira. LOCK TABLE e DDL também causam essa espera.
  • enq: UL - contention: o processo que segura o lock da aplicação demora para soltar.
  • SQL*Net break/reset to client: não é bloqueio. A chamada foi interrompida ou devolveu erro à aplicação.

Resolução

Comece pelo evento que o achado lista primeiro. Os casos vão do mais comum ao menos comum.

Achar a sessão que segura o lock

Enquanto a espera acontece, a sessão bloqueada mostra quem a segura. Rode no banco do trace; em RAC, gv$session cobre todas as instâncias:

select inst_id, sid, serial#, username, event, seconds_in_wait,
       blocking_instance, blocking_session,
       final_blocking_instance, final_blocking_session,
       sql_id, row_wait_obj#
  from gv$session
 where blocking_session is not null
 order by seconds_in_wait desc;

A sessão de final_blocking_session é a do começo da fila. Veja o que ela executou por último e desde quando a transação dela está aberta:

select s.inst_id, s.sid, s.serial#, s.username, s.module, s.status,
       s.sql_id, s.prev_sql_id, t.start_time
  from gv$session s
  join gv$transaction t
    on t.inst_id = s.inst_id
   and t.addr = s.taddr
 where s.inst_id = &inst_id
   and s.sid = &sid;

Se a espera já passou, o ASH guarda blocking_session por amostra em v$active_session_history e dba_hist_active_sess_history. O ASH exige a licença do Oracle Diagnostics Pack. Outra saída é ligar o trace também na sessão que segura o lock, na próxima vez.

Encurtar a transação que segura as linhas

  • Faça o commit ao fim de cada unidade de trabalho, sem deixar a transação aberta esperando o usuário, outro sistema ou um arquivo.
  • Em registro que muitas sessões atualizam (contador, saldo, controle de numeração), troque a linha única por sequence ou por linhas separadas por sessão ou por faixa.
  • Quando a regra permitir, trave antes de alterar com select ... for update wait e um tempo limite, ou skip locked em fila de trabalho, em vez de esperar sem limite.

Lock de tabela: indexar a chave estrangeira

Para enq: TM - contention, liste as chaves estrangeiras do esquema sem um índice que comece pelas colunas delas, na mesma ordem. Troque EXEMPLO pelo dono das tabelas:

select c.owner, c.table_name, c.constraint_name
  from dba_constraints c
 where c.constraint_type = 'R'
   and c.owner = 'EXEMPLO'
   and not exists (
         select 1
           from dba_cons_columns cc
           join dba_ind_columns ic
             on ic.table_owner = cc.owner
            and ic.table_name = cc.table_name
            and ic.column_name = cc.column_name
            and ic.column_position = cc.position
          where cc.owner = c.owner
            and cc.constraint_name = c.constraint_name
          group by ic.index_owner, ic.index_name
         having count(*) = (select count(*)
                              from dba_cons_columns x
                             where x.owner = c.owner
                               and x.constraint_name = c.constraint_name))
 order by c.table_name, c.constraint_name;

Crie o índice na tabela filha com as colunas da chave, na ordem da constraint:

create index exemplo.filha_pai_ix on exemplo.filha (pai_id);

Em tabela grande e em uso, create index ... online (Enterprise Edition) não trava a DML durante a criação. Para saber qual tabela foi travada, o campo object # da linha WAIT do enq: TM - contention no trace é o object_id dela:

grep "enq: TM - contention" arquivo.trc | head

A documentação da Oracle sobre concorrência e consistência de dados explica os locks de DML e o efeito da chave estrangeira sem índice.

Mesma chave inserida por duas sessões

Na linha WAIT do enq: TX - row lock contention, o campo name|mode diz o modo do lock. 1415053318 é modo 6: a linha foi alterada por outra transação. 1415053316 é modo 4: em geral, duas sessões inserindo a mesma chave única ou primária, ou índice bitmap sob DML concorrente. Para contar as esperas em modo 4:

grep "enq: TX - row lock contention" arquivo.trc | grep -c "name|mode=1415053316"

No modo 4, revise como a aplicação gera a chave e se a mesma carga roda duas vezes ao mesmo tempo. Em tabela de OLTP, troque o índice bitmap por um índice B-tree.

Outros eventos da classe

  • enq: UL - contention: peça os locks de DBMS_LOCK sempre na mesma ordem e solte cedo, com release_on_commit ou DBMS_LOCK.RELEASE.
  • SQL*Net break/reset to client: siga para os erros Oracle no trace. A espera some quando o erro deixa de acontecer.
  • enq: KO - fast object checkpoint: leitura direta de uma tabela que muda o tempo todo. Confira o plano do comando que esperou.
  • enq: RO - fast object reuse: TRUNCATE ou DROP repetido, muitas vezes dentro de laço.

Como confirmar

O bloqueio depende do que as outras sessões fazem ao mesmo tempo. Um trace tirado num momento calmo não prova a correção: meça no mesmo horário e com a mesma carga da medição anterior.

  1. Aplique uma correção por vez: o índice, o commit mais cedo ou a ordem dos locks.
  2. Ligue o trace da mesma operação com esperas (ligar o trace com o DBMS_MONITOR).
  3. Envie o arquivo novo e abra o relatório.
  4. Compare a linha Application em Por classe de espera e as linhas dos eventos no perfil.

Resultado: a classe Application deixa de pesar no tempo total e o achado some do Diagnóstico. No perfil, o evento que pesava cai em Ocorrências e em Duração (s).

No relatório

O relatório de exemplo não tem espera da classe Application; os links abrem as mesmas seções nele.

Se as sessões chegaram a esperar umas pelas outras em ciclo, o Oracle devolve o ORA-00060: veja deadlock entre sessões.

Atualizado em 29/10/2026. Relatar erro nesta página