Undo Retention Guarantee – Na prática
Neste artigo, minha proposta é demonstrar na prática o funcionamento do Undo Retention Guarantee. O primeiro passo é extrair algumas informações essenciais para entendermos o comportamento do sistema e como ele lida com a retenção de transações.
SHOW PARAMETER UNDO
No laboratório, criei uma nova tablespace de UNDO.
CREATE UNDO TABLESPACE tbs_undo_02 DATAFILE SIZE 1M AUTOEXTEND OFF;
ALTER SYSTEM SET UNDO_TABLESPACE = 'tbs_undo_02';
O que vemos acima é a criação de uma tablespace chamada TBS_UNDO_02, com tamanho inicial de 1 MB e o parâmetro autoextend desativado. Isso significa que, ao atingir o limite de 1 MB, a tablespace não irá se expandir automaticamente, controlando assim o uso de espaço.
SHOW PARAMETER UNDO
Assim, repetindo o comando, podemos ver que os novos parâmetros estão aplicados e que agora temos uma nova tablespace padrão para o banco, TBS_UNDO_02.
Ao observar o resultado, percebemos que a nova tablespace assume seu papel no banco como a padrão.
Imagine que seu armazém tem uma área reservada, e você decide garantir que essa área nunca será esvaziada, mesmo que haja alta demanda. Isso significa que, não importa o quão lotado o armazém esteja, aquela área sempre estará disponível para itens críticos, sem risco de ser ocupada por outros.
No contexto do Oracle, quando a tablespace está configurada com GUARANTEE, o banco de dados assegura que o UNDO nunca será sobrescrito, mesmo que o espaço fique apertado. Isso significa que, se a retenção do UNDO está garantida (GUARANTEE), o Oracle vai sempre manter os dados de transações por aquele período definido, mesmo que precise alocar mais espaço ou até mesmo suspender novas transações até que o UNDO seja liberado.
Essa configuração é ideal para ambientes onde a integridade das transações é crítica — como se você estivesse reservando uma área do armazém para itens que precisam ser protegidos a todo custo.
A partir de agora, vamos ver como esse parâmetro funciona na prática. Começarei pela criação de uma tabela.
CREATE TABLE armazem AS SELECT * FROM DBA_OBJECTS;
Tabela criada, agora vamos inserir os dados nela:
Agora, vamos entender juntos o que aconteceu e por que o erro ORA-30036 foi gerado. Primeiro, conseguimos criar a tabela armazem sem problemas, já que havia espaço suficiente no banco de dados para acomodá-la. No entanto, o espaço ao qual nos referimos aqui não é o da tablespace UNDO, mas o espaço disponível para a tabela em si.
Quando executamos o comando INSERT INTO armazem, o banco de dados tenta gravar as informações tanto no datafile quanto na tablespace UNDO, pois, em um banco com UNDO habilitado, toda transação DML, como o nosso INSERT, precisa gerar um registro de UNDO. Isso é fundamental para que o banco possa reverter a transação caso algo dê errado.
É justamente nesse ponto que o problema – ou a solução – aparece. (Digo problema/solução porque isso dependerá do seu objetivo.) A tablespace UNDO, que agora está com a retenção garantida (RETENTION GUARANTEE), ficou sem espaço para armazenar novos UNDO, o que gerou o erro ORA-30036. Em resumo, ao tentarmos inserir os dados, o banco de dados não conseguiu alocar mais espaço na tablespace UNDO para registrar as informações necessárias, resultando na falha.
Esse comportamento pode ser visto sob um prisma positivo: os dados contidos na tablespace UNDO estão seguros e não serão sobrescritos pelo período previamente estabelecido (que, neste caso, é de 900 segundos). Isso garante que, se for necessário emitir um comando ROLLBACK, teremos sucesso, pois esses dados estão assegurados e não foram sobrescritos.
A própria documentação da Oracle nos explica isso:
https://docs.oracle.com/en/error-help/db/ora-30036/?r=19c
A própria documentação nos sugere darmos COMMIT para resolver o problema. Essa recomendação é feita porque, ao dar o COMMIT, os dados que estão na tablespace UNDO estão liberados para serem sobrescritos, liberando espaço para o próximo extente. É exatamente isso que a imagem abaixo nos mostra.
Quando iniciamos uma transação, ela é automaticamente vinculada a um segmento de UNDO específico. Nesse segmento, cada uma de nossas transações grava seus dados em um “extente”. É importante saber que várias transações podem compartilhar o mesmo segmento. Contudo, cada bloco de dados dentro de um extente pertence exclusivamente a uma transação, evitando qualquer conflito.
Esse segmento de UNDO é formado por vários extentes organizados de forma circular, como uma roda giratória (como mostra a imagem acima). Imagine que estamos enchendo um balde de água. Quando ele está cheio, passamos para o próximo balde. Se todos os baldes estiverem cheios e nenhum estiver sendo utilizado ativamente, podemos esvaziar o primeiro balde e começar o processo novamente. No caso do banco de dados, se precisarmos de mais espaço, o Oracle irá procurar um extente disponível para continuar a operação. Isso garante que o ciclo funcione bem, desde que haja extentes livres.
Agora, vamos explorar esse comportamento dos segmentos de UNDO na prática. A documentação sugere realizar um COMMIT, o que libera espaço no UNDO, esta sugestão é valida, mas aqui está o detalhe interessante: neste exemplo, o espaço alocado para a tablespace UNDO é apenas 1M. Mesmo que executemos o COMMIT, vamos liberar espaço, mas não o suficiente para acomodar a transação que estamos realizando. A sugestão da documentação não resolveria o nosso problema; o que resolveria, neste caso, seria habilitar o AUTO EXTEND na tablespace UNDO.
Esse é um ótimo ponto para refletirmos sobre a importância de entender a arquitetura por trás das nossas ações no banco de dados. Ter conhecimento das ferramentas que estão ao nosso alcance e saber usá-las com sabedoria é fundamental.
O aprendizado contínuo nos ajuda a fazer ajustes finos e a otimizar o sistema para que ele funcione da maneira mais eficiente possível. Vamos sempre buscar entender o porquê das coisas e nos auto desafiar, pois isso nos torna cada vez mais proficientes!