trilha

Tecnologias/02 - Bancos de Dados/01 - Relacionais/03 - Oracle7 min

Redo, Undo e Consistência de Leitura

Conceito

O Oracle implementa MVCC como o InnoDB — versões antigas no undo — mas com um mecanismo de leitura mais explícito e um erro famoso que sai dele.

SCN: o relógio lógico do banco

O SCN (System Change Number) é um contador monotônico que marca cada mudança confirmada. Ele é o equivalente do LSN do Postgres e aparece em tudo: recuperação, Data Guard, Flashback, consistência de leitura.

Consistência de leitura, passo a passo

Quando sua query começa, o Oracle registra o SCN atual. Ao ler um bloco:

o bloco contém mudança com SCN > o meu SCN de início?
  └─ sim → vá ao UNDO e RECONSTRUA o bloco como ele era no meu SCN
           (isso se chama "consistent read" — CR)
  └─ não → leia direto

Duas consequências importantes:

  1. Leitura nunca bloqueia escrita e vice-versa — o slogan histórico da Oracle, e é verdade.
  2. Reconstruir custa I/O de undo. Uma query longa sobre uma tabela muito alterada faz muito trabalho de reconstrução, mesmo lendo "pouco".

ORA-01555: snapshot too old

O undo é circular: espaço de transações confirmadas é reciclado quando alguém precisa. Se sua query longa pede uma versão antiga cujo undo já foi sobrescrito, o Oracle não tem como reconstruir — e falha:

14:00  query começa (SCN = 1000)
14:02  outras transações alteram a tabela, confirmam, e o undo delas expira
14:35  a query chega naquele bloco e precisa da versão do SCN 1000
       → ORA-01555

O erro é sempre a mesma combinação: query longa + tabela quente + undo pequeno. As saídas, em ordem de preferência:

-- 1) encurtar a query (a correção de verdade)
-- 2) dar retenção suficiente ao undo
ALTER SYSTEM SET UNDO_RETENTION = 10800;            -- segundos (3 h)
ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;      -- prioriza retenção
                                                     -- (⚠ pode fazer DML falhar por falta de undo)
-- 3) aumentar o undo tablespace

E o antipadrão histórico que causa o erro: COMMIT dentro do laço que percorre um cursor. Cada commit libera undo que a própria query em andamento ainda vai precisar. Ver 6. PL-SQL na Prática.

Redo, ARCHIVELOG e recuperação

transação → redo log buffer (SGA) → LGWR → redo log online (grupos, circulares)
                                              └→ ARCn → archived redo log (para PITR)

Redo logs online são circulares (tipicamente 3+ grupos, multiplexados em discos diferentes). Quando o grupo 1 enche, o banco muda para o 2 e ARCn arquiva o 1.

O incidente mais comum de Oracle

Se o destino de arquivamento enche, ARCn não consegue arquivar; o banco não pode reciclar o redo online não arquivado; e ele congela toda a atividade de escrita. O app trava sem erro claro. Monitore %USED do db_recovery_file_dest (a FRA) como métrica de primeira linha.

-- espaço da Fast Recovery Area: monitore isto
SELECT name, space_limit/1024/1024/1024 AS gb_limite,
       space_used/1024/1024/1024 AS gb_usado,
       ROUND(100*space_used/space_limit, 1) AS pct
  FROM v$recovery_file_dest;

Flashback: o recurso sem equivalente

Como o undo guarda as versões anteriores, o Oracle expõe isso em SQL:

-- consultar o passado (limitado pelo UNDO_RETENTION)
SELECT * FROM pedidos AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE)
 WHERE id = 4711;

-- ver todas as versões de uma linha e quem as mudou
SELECT versions_starttime, versions_operation, versions_xid, status
  FROM pedidos VERSIONS BETWEEN TIMESTAMP
       (SYSTIMESTAMP - INTERVAL '1' HOUR) AND SYSTIMESTAMP
 WHERE id = 4711;

-- desfazer um UPDATE errado sem restore (precisa de ROW MOVEMENT habilitado)
ALTER TABLE pedidos ENABLE ROW MOVEMENT;
FLASHBACK TABLE pedidos TO TIMESTAMP (SYSTIMESTAMP - INTERVAL '15' MINUTE);

-- tabela dropada por engano: vem da recycle bin
FLASHBACK TABLE pedidos TO BEFORE DROP;

-- e o nível nuclear: o banco inteiro (exige flashback logs habilitados)
FLASHBACK DATABASE TO SCN 12345678;

FLASHBACK DATABASE reverte o banco todo em minutos, em vez de horas de restore de backup. É o recurso que mais claramente justifica o preço em ambientes onde RTO é contratual — ver RTO e RPO e Estratégias de Disaster Recovery.

Trade-offs

Undo dá rollback correto e transação longa envenena o sistema. Diferente do Postgres (onde a transação longa bloqueia a limpeza e gera bloat), aqui ela consome retenção de undo e provoca ORA-01555 em outras sessões. O sintoma aparece longe da causa.

Flashback é maravilhoso e limitado pelo undo. AS OF TIMESTAMP só alcança até UNDO_RETENTION. Para dias ou semanas atrás é preciso Flashback Data Archive (Total Recall) — que é opção paga — ou restore de backup.

RETENTION GUARANTEE troca um erro por outro. Ele garante retenção de undo, e quando o tablespace de undo lota, DML começa a falhar (ORA-30036). Você trocou "query longa falha" por "escrita falha" — decida qual dói menos.

NOARCHIVELOG é mais rápido e indefensável em produção. Sem arquivamento não há PITR: qualquer recuperação volta ao último backup completo. Só faz sentido em ambiente descartável.

O trade-off central: o Oracle centralizou no undo três funções — rollback, MVCC e viagem no tempo. Isso é elegante e cria um recurso compartilhado disputado: a mesma configuração que protege a leitura consistente pode derrubar a escrita, e a decisão de dimensionamento é sua.

Exemplo prático

Diagnosticar ORA-01555

-- quem são as transações longas consumindo/segurando undo
SELECT s.sid, s.username, s.event,
       t.start_time, t.used_ublk * 8192/1024/1024 AS undo_mb,
       ROUND((SYSDATE - TO_DATE(t.start_time,'MM/DD/YY HH24:MI:SS'))*24*60) AS minutos
  FROM v$transaction t JOIN v$session s ON s.saddr = t.ses_addr
 ORDER BY t.start_time;

-- o histograma de uso de undo: quanto de retenção eu REALMENTE tenho?
SELECT begin_time, tuned_undoretention,
       undoblks, maxquerylen AS maior_query_seg, ssolderrcnt AS erros_01555
  FROM v$undostat ORDER BY begin_time DESC FETCH FIRST 12 ROWS ONLY;

maxquerylen vs tuned_undoretention é a comparação decisiva: se a maior query dura mais que a retenção efetiva, ORA-01555 é questão de tempo.

Recuperação: os dois níveis

-- erro de aplicação em uma tabela (minutos atrás): Flashback resolve
FLASHBACK TABLE pedidos TO TIMESTAMP (SYSTIMESTAMP - INTERVAL '20' MINUTE);

-- perda de datafile / corrupção: RMAN
-- $ rman target /
-- RMAN> RESTORE DATABASE;
-- RMAN> RECOVER DATABASE UNTIL TIME "TO_DATE('2026-09-08 14:31','YYYY-MM-DD HH24:MI')";
-- RMAN> ALTER DATABASE OPEN RESETLOGS;

Configuração defensável

-- arquivamento ligado, com dois destinos
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1 = 'LOCATION=USE_DB_RECOVERY_FILE_DEST';
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 200G;

-- undo com retenção coerente com a maior query legítima
ALTER SYSTEM SET UNDO_RETENTION = 7200;

-- redo grande o bastante para não trocar de grupo a cada minuto
-- (alvo: uma troca a cada 15-20 min em pico)
SELECT group#, bytes/1024/1024 AS mb, members, status FROM v$log;

-- flashback database, se o RTO justificar o custo em disco
ALTER DATABASE FLASHBACK ON;
ALTER SYSTEM SET DB_FLASHBACK_RETENTION_TARGET = 1440;   -- minutos (24 h)

Como isso falha em produção

Erro/sintoma Causa
ORA-01555 snapshot too old query longa + undo insuficiente; ou COMMIT dentro do laço do cursor
Banco congelado, escrita parada FRA/destino de archive cheio
ORA-30036: unable to extend segment in undo tablespace RETENTION GUARANTEE + undo pequeno
log file sync alto COMMIT por linha, ou redo em disco lento
log file switch (archiving needed) arquivamento não acompanha a geração de redo
Flashback não alcança o momento desejado UNDO_RETENTION menor que o necessário
Recuperação impossível banco em NOARCHIVELOG

Aprofundamento aplicado

Uma consulta longa precisa reconstruir o passado

Uma consulta começa em um ponto lógico e outras sessões continuam modificando os dados. Ao encontrar blocos alterados, o Oracle pode precisar de undo para reconstruir a versão adequada. Se essa informação não estiver mais disponível, a consulta pode falhar com ORA-01555; isso não significa que a linha atual desapareceu. Referência: consistência de leitura.

Cenário: um relatório leva duas horas sobre uma tabela muito atualizada. As opções incluem reduzir a duração por plano e índices, dimensionar retenção/espaço de undo conforme a carga ou executar a análise sobre uma cópia com estratégia própria. Uma réplica ou exportação altera também atualidade e operação, então precisa de contrato.

Exercício: desenhe a linha do tempo com início da consulta, alteração concorrente, reutilização do undo e leitura tardia do bloco. Resultado esperado: localizar a informação histórica necessária e distinguir redo, usado na recuperação, de undo, que participa da reconstrução da visão e do rollback.

Relacionado


Parte de MOC Oracle · Concepts Guide (docs)

Buscar

Busca por título, seção e texto das notas