Esse artigo faz parte da revista Clube Delphi edição 42. Clique aqui para ler todos os artigos desta edição

img

Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML. 

 

Transações no Firebird/InterBase

Conceitos, arquitetura e modos de isolamento

As transações em bancos de dados cliente/servidor são de extrema importância e seu uso representa uma das maiores evoluções quando se migra de um banco de dados desktop para um verdadeiro SGBD (Sistema Gerenciador de Banco de Dados). Em se tratando do Firebird/InterBase, as transações têm uma importância ainda maior, devido à arquitetura de versioning utilizada por esses servidores. Esta abordagem obriga que qualquer operação no banco de dados, mesmo um simples select, esteja dentro de uma transação.

Neste artigo serão mostrados conceitos de transações no Firebird/InterBase, detalhes da arquitetura de versioning, e as diferenças entre os vários tipos de isolamentos transacionais, além do relacionamento entre eles.

Arquitetura de versioning

Para entender o mecanismo de transações do FB/IB, é importante termos uma noção básica do que é versioning, o sistema gerenciador de concorrência utilizado no FB/IB, também chamado de Multi-Generational Architecture (MGA). No versioning, quando você altera alguma informação no banco de dados, versões temporárias dos registros alterados são criadas e permanecem “ativas” durante o tempo que for necessário, permitindo que o registro fique acessível – com seu conteúdo original – a outras transações, que enxergam sempre uma visão consistente dos dados.

As versões temporárias dos registros, obviamente, ocupam espaço no banco de dados. Quando os registros temporários não forem mais necessários, o processo de coleta de lixo (garbage collection) se encarrega de marcá-los como “lixo” para futuro reaproveitamento do espaço ocupado. Por essa razão, um banco de dados FB/IB nunca diminui de tamanho (a não ser quando um backup/restore é executado). Essa é uma medida de eficiência, pois a alocação de novo espaço em disco é muito mais onerosa do que o reaproveitamento de um espaço já alocado.

Devido à arquitetura de versioning, o FB/IB não precisa manter logs de transações como é feito em outros bancos relacionais (Oracle, SQL Server etc.). Esses logs são utilizados quando se deseja reverter o banco do seu estado atual para um anterior como, por exemplo, quando ocorre algum tipo de falha invalidando os dados atuais. Em uma situação desse tipo, o log é usado para desfazer as últimas operações, deixando o banco novamente em um estado consistente.

Como o versioning cria versões temporárias dos registros com que se está trabalhando, em uma situação de falha ou erro, o SGBD apenas marca o flag da transação como RolledBack, fazendo com que todos os registros associados a ela sejam descartados, deixando o banco de dados consistente em questão de segundos. Em outros servidores, dependendo do tamanho do log de transações, o processo pode levar muito mais tempo. Conseqüentemente, o BD ficará indisponível por um período maior.

Um efeito colateral gerado pelo versioning é que, como não existe um log de transações, não há possibilidade de realizar backups incrementais, pois não se sabe o que foi alterado desde o último backup. Já existem ferramentas de terceiros que implementam um log de alterações em bancos de dados FB/IB (veja por exemplo www.iblogmanager.com). Um log desse tipo é útil no caso do arquivo do banco de dados sofrer algum tipo de corrupção física, impedindo que o FB/IB ou seus utilitários de verificação corrijam o banco.

Hoje o Firebird e o InterBase são os únicos bancos de dados a utilizar versioning em sua arquitetura interna.

Transações na prática

Para quem não está acostumado com o conceito de transações, uma forma simples de entendê-lo é o seguinte: imagine que uma transação define um bloco de operações realizadas em uma ou mais tabelas no banco de dados, sendo que, se alguma dessas operações falhar, então todas serão desfeitas. A confirmação (Commit) ou o cancelamento (Rollback) da transação determina seu fim.

Em um exemplo prático, imagine um sistema de faturamento com uma operação de emissão de nota fiscal que automaticamente baixa os produtos do estoque e lança os movimentos no sistema de contas a receber. Nesse cenário, você pode fazer com que as operações realizadas nas tabelas envolvidas (notas, produtos, estoque, contas a receber, etc.) pertençam a uma única transação – caso haja um erro de estoque negativo para algum dos produtos, você pode reverter todas as alterações geradas pela nota com um simples Rollback, fazendo com que o banco permaneça em um estado consistente.

 

img

Figura 1. Ocorrência de uma queda de energia durante a execução de operações dentro de uma transação envolvendo várias tabelas

Indo além, imagine que, no meio do processo de gravação dos dados da nota fiscal, haja uma interrupção de energia. O servidor, nesse caso, irá reverter todas as operações que estavam sendo executadas pelas transações pendentes no momento da queda de energia, tão logo ele entre no ar novamente, mantendo  a consistência dos dados (veja a Figura 1).

O Firebird/InterBase permite que você tenha diversas transações ativas ao mesmo tempo. Também suporta transações distribuídas, onde uma transação pode estar ligada a mais de um banco de dados e bancos podem também estar em servidores diferentes. Se uma das operações em algum dos bancos falhar, todas as operações realizadas pela transação nos outros bancos serão descartadas também. É um processo chamado de "commit em duas fases" ( ...

Quer ler esse conteúdo completo? Tenha acesso completo