terça-feira, 9 de dezembro de 2008

Transactions com DBExpress 4 e MySQL 5

E ai pessoal. Antes de começar o Post, gostaria de agradecer aos meus amigos pelos comentários e pelos parabéns que tenho recebido por msn e orkut :).

Nesse Post falarei sobre Transaction no Mysql utilizando o próprio MySQL e/ou Delphi 2007 com DBExpress 4.0.

TRANSACÇÃO DE DADOS (TRANSACTION)

O que seria uma transacção de dados?
Transacção de dados, nada mais é do que um acordo entre duas operações, uma regra de negócio que para ser finalizada, todos os dados precisam estar completos e fazendo parte de um acordo.

Para exemplificar, imagina uma operação financeira. Dentro de uma conta a pagar, é necessário emitir 6 faturas e, essas faturas completam o valor total da conta criada.
Ficaria assim:
Valor total da conta a pagar: R$ 600
Total de faturas: 6 faturas de R$100,00

Agora imagina você cadastrando a conta e quando vai gerar as faturas, o servidor cai, seu computador desliga ou ocorre algum outro erro? O que acontece?
Seus dados podem não estar completos, gerando inconsistência nos dados e, ao invés de você cadastrar as 6 faturas, acaba registrando apenas 4. Fora os problemas e erros que podem gerar na base de dados.
É ai que a TRANSACTION entra em ação!

Resumindo e quase "desenhando" como a transaction age em nosso sistema e base de dados:

Sistema: Banco, esta ai? inicia uma transação ai pra mim.
Base de dados: Transação realizada.
Sistema: Ei banco vlw, registra pra mim essa conta.
Base de dados: Legal, conta registrada, pode continuar.
Sistema: Registra essa fatura:
Base de dados: Fatura registrada.
Sistema: Banco, registra essa outra fatura:
Sistema: Banco??? Banco???? Cadê vc????
Sistema: Como não consegui registrar tudo, entao vou cancelar a conta e a fatura já cadastrada para mais tarde quando a base voltar do banheiro, fazer tudo novamente.

Isso é uma transaction gerada pelo sistema. Você também pode fazer a mesma coisa dentro de uma Stored Procedure ou uma trigger, direto pelo banco, sem a utilização do seu sistema, independentemente se é feito em Delphi, PHP, C#, Java ou qualquer outra linguagem de programação.

Este tipo de utilização da transaction, depende do processo que você irá realizar.

Por exemplo, se você deseja armazenar dados em um relacionamento 1-N, a melhor forma de utilizar a transaction é pelo sistema, caso contrário, você pode fazer a transaction diretamente pelo banco, como em uma auditoria de cadastros e atualizações das entidades da sua base de dados.


TRANSACTION UTILIZANDO DBEXPRESS 4

Em uma transação, temos:
Inicio da transação
Comandos SQL DML
Se tudo deu certo, COMMIT (comete)
Se deu algo errado, ROLLBACK (Volta e desfaz tudo!)

Então, vamos la.

var
Trans: TDBXTransaction;
Qry: TSQLQuery;
begin
//Inicia a transacão com o componente de conexão com a base de dados, chamada de
//CONEXAO. Ele é um TSQLConnection da aba DBExpress
//Todos os objetos que se conectarem a essa conexão, estarão em transação
Trans := CONEXAO.BeginTransaction(TDBXIsolations.ReadCommitted);

//Aqui utilizamos um try para verificar se tudo vai ocorrer bem.
try
//Cria um objeto da classe TSQLQuery para conectar-se ao componente de conexao a
// base de dados criada anteriormente
Qry := TSQLQuery.Create(Self);
with Qry do
begin
SQLConnection := CONEXAO;
SQL.Text := 'INSERT INTO contas (documento, valor_original, valor_total) VALUES ('+QuotedStr('00043244')+', '+QuotedStr('35.50')+', '+QuotedStr('40.00')+')';
ExecSQL;

SQL.Text := 'INSERT INTO faturas (idconta, valor_total, data_lancamento, data_pagamento) VALUES ('+QuotedStr('1')+', '+QuotedStr('2008/08/03')+', '+QuotedStr('2008/08/10')+')';
ExecSQL;

SQL.Text := 'INSERT INTO faturas (idconta, valor_total, data_lancamento, data_pagamento) VALUES ('+QuotedStr('1')+', '+QuotedStr('2008/08/03')+', '+QuotedStr('2008/08/10')+')';
ExecSQL;

Close;
end;

//Caso tudo ocorreu normalmente, Comete a transação, ou seja. Insere todos os dados na
//base de dados
CONEXAO.CommitFreeAndNil(Trans);

Except
//Caso ocorreu algum erro, cancela TODAS as operações acima
DM1.CONEXAO.RollbackFreeAndNil(Trans);

end;

end;


Esse cadastro foi feito apenas para explicação. Crie sua base de dados e provoque erros no código para testar sua aplicação utilizando TRANSACTION.

TRANSACTION DIRETAMENTE PELO MYSQL

Para utilizar Transações no Mysql 5, o Engine das suas tabelas precisam estar como INNODB.
Por padrão, MySQL é executado em modo autocommit. Isto significa que assim que você executa uma instrução que atualiza (modifica) uma tabela, o MySQL armazena a atualização no disco.
você pode colocar o MySQL em modo não autocommit com o seguinte comando:
SET AUTOCOMMIT=0

Depois de disabilitar o modo autocommit configurando a variável AUTOCOMMIT com zero, você deve utilizar COMMIT para armazenar suas alterações em disco ou ROLLBACK se você deseja ignorar as alterações que você fez desde o início da sua transação.

Se você quiser disabilitar o modo autocommit para uma única série de instruções, você pode utiliar a instrução START TRANSACTION:


START TRANSACTION;

INSERT INTO contas(documento, valor_original, valor_total) VALUES ('343434', '45.50', '50.00');

INSERT INTO faturas(idfatura, data_vencimento, data_pagamento) VALUES (LAST_INSERT_ID(), '2008-12-01', '2008-12-01');

COMMIT;

Caso queira cancelar a transação, ao invés de COMMIT, use ROLLBACK.

Pessoal, tentei explicar da forma mais simples possível como utilizamos Transações pelo Delphi utilizando o componente DBExpress e diretamente pelo Mysql.

Blz pessoal?
Abraços e até mais.

2 comentários:

Eu disse...

VALEU MEU CHAPA! MUITO BOM! Me esclareceu muita coisa sobre transaçoes. :D

Anônimo disse...

valeu mesmo!
sua dica foi muito útil na passagem de um sistema de delphi 2006 para o 2010. não se esqueçam de declarar na uses dbxcommon