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
BEGIN
insert into TB_ACESSOS_SAL values(sysdate, user);
END;
/
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
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
insert into TB_ACESSOS_SAL values(sysdate, user);
commit;
END;
/
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
BEGIN
GRAVA_AUD_UPD_SAL;
END;
/
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
Excelente explicação! Parabéns!
Muito bom !
Eu precisei usar a transação autônoma quando precisei que um grupo de boleto gerasse numero sequenciais ( ter o mesmo efeito de uma sequencia) sem precisar bloquear e outras transações ficasse em LOCK esperando a geração do boleto em lote.
Excelente!
Muito bom