O que é e como/quando utilizar Autonomous Transactions (transações Autônomas) no RDBMS Oracle

Autonomous Transactions

Em uma ocasião recente, um colega ficou em dúvida sobre Autonomous Transactions. Este artigo visa dar algumas explicações à respeito, para tanto, antes de chegarmos ao ponto de Transação Autônoma, vamos dar um pequeno passo para trás e ver o que é uma TRANSAÇÃO.

O fato é: Há anos atrás, quando foi estabelecida a arquitetura chamada relacional para databases, uma das exigências estruturais criada foi a integridade transacional, ie : o SGBD Tem que permitir ao usuário enviar um conjunto de N comandos de manipulações de dados e é por conta do usuário indicar que o conjunto de comandos INTEIRO vai poder ser efetivado (via comando COMMIT) ou deve ser descartado (com o comando ROLLBACK). Para isso, o SGBD TEM que possuir mecanismos internos que permitam a qualquer momento esse encerramento de transação. Além disso, os dados manipulados dentro de uma transação não efetivada PRECISAM ser ‘invisíveis’/inacessíveis aos outros usuários/outras sessões do database (não pode NUNCA haver a chamada ‘leitura suja’, ie, dados ainda não confirmados serem lidos), e enquanto não ocorrer o encerramento da transação, os outros usuários/outras sessões TEM que enxergar os dados como estavam antes.

Isto exposto, aí fica simples de entender o conceito de Autonomous Transaction/Transação Autônoma, que é simplesmente uma rotina que é executada sob OUTRA transação, independente da transação que esteja aberta no momento. A maior vantagem disso são situações tais como INSERTs em tabelas de auditoria, que devem ser gravadas SEJA ou NÃO encerrada com sucesso a transação original.

Exemplo: Por necessidade de segurança/auditoria do negócio, digamos que sempre que se tentou alterar a coluna SAL da tabela EMP seja exigido guardar na tabela TB_ACESSOS_SAL.

  • Primeiro, preciso ter a tabela de “Auditoria” criada
scott@DESENV:SQL>create table TB_ACESSOS_SAL(DT_ACESSo date, USERNAME varchar2(33));

Tabela criada.
  • Depois crio uma trigger que faz DML : sem especificar uma Transação autônoma, o DML na tabela de Audit vai pertencer à mesma Transação relacionada com o UPDATE que disparou a trigger
scott@DESENV:SQL>create or replace trigger TRG_UPD_SAL after UPDATE OF SAL ON EMP for each row
2 BEGIN
3 insert into TB_ACESSOS_SAL values(sysdate, user);
4 END;
5 /

Gatilho criado.
  • Executo um UPDATE, o que por sua vez dispara a trigger
scott@DESENV:SQL>update emp set sal=3001 where empno=7935;

1 linha atualizada.
  • Transação é encerrada com “desfazimento”
scott@DESENV:SQL>rollback; 

Rollback concluído.
  • O DML na tabela de Audit, como foi disparado na mesma transação encerrada, foi desfeito também
scott@DESENV:SQL>select * from TB_ACESSOS_SAL;

não há linhas selecionadas
  • Agora, vamos fazer o INSERT na tabela de audit numa transação separada
scott@DESENV:SQL>create or replace procedure GRAVA_AUD_UPD_SAL is
   2     PRAGMA AUTONOMOUS_TRANSACTION;
   3  BEGIN
   4     insert into TB_ACESSOS_SAL values(sysdate, user);
   5     commit;
   6  END;
   7  /

 Procedimento criado.
  • Alterarei a trigger para chamar essa rotina AT
scott@DESENV:SQL>create or replace trigger TRG_UPD_SAL after UPDATE OF SAL ON EMP for each row
   2   BEGIN
   3      GRAVA_AUD_UPD_SAL;
   4  END;
   5  /

Gatilho criado.
  • Novamente, executo UPDATE que dispara a trigger
scott@DESENV:SQL>update emp set sal=3001 where empno=7935;

1 linha atualizada.
  • MESMO que a transação original seja desfeita, a transação INDEPENDENTE não será desfeita
scott@DESENV:SQL>rollback;

Rollback concluído.

scott@DESENV:SQL>select * from TB_ACESSOS_SAL;

DT_ACESSO           USERNAME
------------------- ------------
23/04/2021 10:54:32 SCOTT

scott@DESENV:SQL>

O uso de Transação Autônoma para contorno das limitações de triggers de DML, como é sabido, as triggers disparadas após um DML (INSERT, UPDATE ou DELETE) em tabela possuem duas restrições: Primeiro, não podem conter comandos de encerramento de transação (seja COMMIT seja ROLLBACK) e segundo, não podem realizar nem SELECT nem DML na tabela à qual a trigger de DML está associada.

Uma opção para contornar tais restrições é o uso de Autonomous Transaction, com os comandos que violam as restrições contidos em um PL/SQL em modo de Autonomous Transactions. Há muitas outras possibilidades para isso (por exemplo, COMPOUND TRIGGERs) mas o uso de uma transação autônoma contendo os comandos desejados pode ser viável, também

Abraços