Oracle Transações (Parte I)
O meu objetivo com este post é apresentar de maneira simples o comportamento das transações no Oracle. Para melhor didática, dividi o conteúdo em duas partes. Vamos juntos explorar a primeira parte.
Imagine que o Oracle Database é como uma cozinha de um restaurante movimentado, onde diversas receitas (transações) estão sendo preparadas simultaneamente. Cada prato (transação) deve ser preparado de acordo com uma receita específica (instruções SQL), garantindo que todos os ingredientes (dados) sejam processados corretamente. Assim como um chefe de cozinha cuida para que cada prato saia perfeito, o Oracle Database garante a integridade e a confiabilidade dos dados através das transações.
O Oracle Database é mais do que apenas um banco de dados; é um ecossistema transacional dinâmico. Em seu âmago, reside a essência das transações, garantindo a integridade e a confiabilidade dos dados em um mundo cada vez mais interconectado.
As Propriedades ACID
Imagine uma transação como uma narrativa coesa, uma história lógica e atômica que agrupa instruções SQL em uma única unidade de trabalho. No Oracle Database, cada transação recebe um identificador único, uma espécie de assinatura digital que a distingue em meio ao fluxo de atividades. As transações no Oracle seguem as diretrizes fundamentais conhecidas como propriedades ACID: Atomicidade, Consistência, Isolamento e Durabilidade. Vamos usar uma analogia do cotidiano para entender melhor:
Essa analogia ajuda a entender como as propriedades do ACID se aplicam em um contexto do mundo real, como uma transação de compra em uma loja física, e como elas garantem a integridade e a confiabilidade dos dados em um banco de dados durante a execução de transações.
Controle de Acesso com Locks
O Oracle Database utiliza locks para controlar o acesso simultâneo aos dados. Os locks permitem que o usuário que está executando uma operação nos dados se torne temporariamente o “proprietário” dos dados, impedindo que outros usuários alterem esses dados até que a operação seja finalizada.
Demonstrando ACID em Ação Para demonstrar as propriedades ACID em ação, vamos nos conectar com mais de uma sessão, utilizando o recurso do MOBA. Reparem que na parte superior da imagem existem duas sessões iniciadas: user ALPHA e user BRAVO.
Primeiramente, criamos uma tabela e inserimos três valores na tabela recém-criada. Isso é uma ação cotidiana, mas junto com esta ação foi criada uma transação. Vamos observar isso de perto.
Com o comando DESC produtos, visualizamos a estrutura da tabela e confirmamos que os três produtos foram inseridos com o comando SELECT * FROM produtos. Isso é visível. A transação pode ser visualizada com a sintaxe apropriada.
SELECT XID, START_TIME, STATUS, NAME FROM V$TRANSACTION;
Onde podemos ver que existe um ID ‘03001100F7020000‘, a hora que iniciou, e seu status é ACTIVE.
Enquanto isso, na seção user BRAVO:
Na seção user BRAVO, conseguimos visualizar que existe uma transação em andamento com status ACTIVE. Curiosamente, com o comando DESC produtos, podemos ver a estrutura da tabela, mas não podemos visualizar os produtos inseridos. Isso acontece porque quando executamos um CREATE TABLE, estamos executando uma ação DDL, que tem um COMMIT embutido.
Isso acontece pois quando executamos um CREATE TABLE estamos executando uma ação DDL, agora vou abrir um parentese enorme e dizer: quando executamos um comando DDL existe um COMMIT embutido nesta ação, fecha parentese enorme.
Tenho a obrigação de destacar que esta ação comprova o ISOLAMENTO da TRANSAÇÃO, nenhuma outra sessão é possivel visualizar uma TRANSAÇÃO até que ela seja finalizada.
Lembrando que o COMMIT é:
Compreendendo o Isolamento e os Locks
Com o isolamento da transação, nenhuma outra sessão pode visualizar uma transação até que ela seja finalizada. Quando executamos um INSERT INTO produtos, este é um comando DML, que não tem nenhuma ação embutida. É importante destacar que isso não é uma questão de usuário, mas de sessão. Mesmo que o usuário seja o mesmo, a sessão é diferente, e a propriedade dos dados inseridos pertence à sessão até que ela seja finalizada por um comando DDL., veja só:
As imagens acima deixam bem claro que o que muda é a sessão mas o usuário é o mesmo, reafirmo que o dono dos dados inceridos na tabela é de propriedade da sessão, assim todo comando DML pertence a sessão até que ela seja finalizada por um comando DDL.
Explorando o ROLLBACK e SAVEPOINT
Até o momento, criamos a tabela na sessão ALPHA, que só pode ser vista pela sessão ALPHA. Vamos aplicar um comando DDL, que é o ROLLBACK. Comandos DDL finalizam uma transação. O ROLLBACK desfaz as alterações pendentes no banco de dados para a transação vigente, limpa todos os SAVEPOINTS, libera todas as linhas e/ou tabelas em estado lock, e finaliza a transação.
Após o ROLLBACK, os dados inseridos são revertidos, mas a tabela continua existindo porque o CREATE TABLE é um comando DDL e tem um COMMIT implícito.
Vejamos seu comportamento na prática.
A imagem nos ajuda a visualizar os dados existentes dentro da tabela até o ponto em que é executado o ROLLBACK.
Imagine que você está preparando uma refeição. Você começou a cozinhar e adicionou alguns ingredientes à panela. O ROLLBACK é como decidir que não gostou da combinação de sabores e, em vez de apenas retirar os ingredientes adicionados, você volta ao ponto inicial, onde a panela estava vazia.
A partir do momento em que se executa o ROLLBACK, que é um comando DDL, a ação reverte até o ponto da inserção dos valores na tabela. Comandos DDL só têm poder sobre comandos DML. Lembra que comentei acima que o comando ‘CREATE TABLE’ é um comando DDL e que comandos DDL têm um COMMIT implícito? Aqui conseguimos visualizar a prática dessa ação. O ROLLBACK desfaz a inserção dos dados, mas não refaz a criação da tabela. Por isso, a tabela continua existindo, mas os dados se foram.
É gostoso ver a coisa funcionando; o visual nos ajuda a fixar o conteúdo mais facilmente. Mas a coisa não para por aqui. Vamos inserir mais três dados na tabela e continuar com a prática. O que vamos fazer daqui para frente é trabalhar a ação do SAVEPOINT e seu comportamento.
Imagine que, enquanto cozinha, você decide experimentar um pouco e marca um ponto de controle. O SAVEPOINT é como uma marcação no meio do processo de cozimento. Se algo der errado, você pode voltar a esse ponto sem ter que começar tudo de novo.
Aproveito que a tabela existe e faço três inserções. Confirmo que a tabela existe com os seus três produtos inseridos e reparem que voltamos a ter uma nova TRANSAÇÃO. Sei que é uma nova TRANSAÇÃO pelo número do ID ‘0700050011030000’. Na sequência, executo um SAVEPOINT e dou o nome de ‘a’ a este SAVEPOINT, tudo isso dentro da sessão user ALPHA. O SAVEPOINT não muda o número da minha TRANSAÇÃO.
Acima, percebam que executo um UPDATE, confirmo que a atualização foi executada e, na sequência, executo o famoso COMMIT. Esta ação do COMMIT finaliza a TRANSAÇÃO, tanto é que não existe mais TRANSAÇÃO, mas a coisa não para por aí.
Pense em uma transação como uma receita de cozinha. O UPDATE é como adicionar um novo ingrediente e o COMMIT é como finalizar o prato e servir. Antes do COMMIT, os ingredientes ainda podem ser ajustados, mas uma vez que o prato é servido, ele está pronto e não pode ser alterado. Assim, o COMMIT finaliza a receita, garantindo que todas as mudanças feitas (ou ingredientes adicionados) estejam completas e prontas para serem saboreadas.
O COMMIT não só finalizou a TRANSAÇÃO como também encerrou o SAVEPOINT que estava salvo.
Conclusão
Assim como um chef de cozinha garante que cada prato saia perfeito, garantindo a satisfação dos clientes, o Oracle Database assegura que cada transação seja processada corretamente, mantendo a integridade e a confiabilidade dos dados. Cada ingrediente (dado) é tratado com cuidado, cada receita (transação) é executada com precisão, e o resultado final é um sistema de banco de dados robusto e confiável.
Ao longo deste post, vimos como as propriedades ACID (Atomicidade, Consistência, Isolamento e Durabilidade) se aplicam às transações no Oracle Database. Através de exemplos práticos, demonstramos como o Oracle gerencia transações, utilizando locks para controlar o acesso simultâneo aos dados e comandos DDL e DML para modificar e confirmar alterações.
Assim como na cozinha, onde a organização e a atenção aos detalhes são cruciais para o sucesso, no Oracle Database, a compreensão e a aplicação correta das transações são fundamentais para manter a integridade e a eficiência do sistema. Com o uso de comandos como COMMIT, ROLLBACK e SAVEPOINT, você pode garantir que suas transações sejam executadas de forma segura e eficaz.
Espero que este material tenha ajudado a esclarecer o funcionamento das transações no Oracle Database. Estou sempre aberto a expandir minhas conexões, compartilhar experiências e aprender com você. Vamos continuar trocando figurinhas e aperfeiçoando nossas habilidades, assim como um chef sempre busca aprimorar suas receitas.
Estou à disposição para conversar e trocar ideias sobre nossas práticas e desafios diários. Sinta-se à vontade para entrar em contato. Juntos, podemos criar um verdadeiro banquete de conhecimento e inovação!
Estou aprendendo muit com seus artigos.
Tem como você também disponibilizar os codigos em texto?Em imagem é ruim por que não da para copiar.
Olá, Fernanda. Tudo bem?
Agradeço por sua interação. Sim, tenho o código.
Ao estudar o código, você verá que ele é mais extenso do que o descrito no artigo. Isso ocorre porque, para manter o interesse do leitor e evitar que o artigo ficasse muito longo, dividi o conteúdo em duas partes. No entanto, o código é único; apenas resumi o artigo para focar no tema central de como o Oracle trata as transações.
Segue o código abaixo e bons estudos.
.
— exemplo de transação
CREATE TABLE produto (
codigo NUMBER(2),
nome VARCHAR2(20)
);
INSERT INTO produto VALUES (1, ‘banana’);
INSERT INTO produto VALUES (2, ‘laranja’);
INSERT INTO produto VALUES (3, ‘melancia’);
SELECT * FROM produto;
ROLLBACK; –> Finaliza transação atual
INSERT INTO produto VALUES (1, ‘banana’);
INSERT INTO produto VALUES (2, ‘laranja’);
INSERT INTO produto VALUES (3, ‘melancia’);
SELECT * FROM produto;
SAVEPOINT a;
UPDATE produto SET codigo = 10 WHERE codigo = 1;
COMMIT; –> Finaliza transação atual
DELETE FROM produto WHERE codigo = 2;
SAVEPOINT b;
UPDATE produto SET codigo = 30 WHERE codigo = 3;
SAVEPOINT c;
DELETE FROM produto WHERE codigo = 10;
ROLLBACK TO SAVEPOINT b; –> Não finaliza transação atual
COMMIT; –> Finaliza transação atual
— consultando transações
COL NAME FOR A50
SELECT XID, START_TIME, STATUS, NAME FROM V$TRANSACTION;
— ddl encerrando transação
DELETE FROM produto;
DROP TABLE produto;
— set transaction
CREATE TABLE product2 (
codigo NUMBER(2),
nome VARCHAR2(20)
);
SET TRANSACTION NAME ‘Transacao’;
INSERT INTO product2 VALUES (1, ‘banana’);
INSERT INTO product2 VALUES (2, ‘laranja’);
INSERT INTO product2 VALUES (3, ‘melancia’);
SELECT XID, START_TIME, STATUS, NAME FROM V$TRANSACTION;
CREATE TABLE product3 (
codigo NUMBER(2),
nome VARCHAR2(20)
);
SELECT XID, START_TIME, STATUS, NAME FROM V$TRANSACTION;
SELECT * FROM product2;
INSERT INTO product3 VALUES (1, ‘banana’);
commit;
update product3 set nome=’laranja’ where codigo=1;
SELECT XID, START_TIME, STATUS, NAME FROM V$TRANSACTION;
— nova sessao
SELECT * FROM product3;
update product3 set nome=’caneta’ where nome=’banana’;
SELECT XID, START_TIME, STATUS, NAME FROM V$TRANSACTION;
.