Desenvolvimento - Office

Replicando bancos de dados com o Access

Saiba como replicar um banco de dados Access para trabalhar de forma desconectada, sincronizar os dados e resolver os conflitos de atualização.

por Luiz Cláudio Cosenza V. Rocha



Introdução

A grande maioria dos aplicativos comerciais são projetados para funcionamento em ambientes multi-usuário. A estrutura a ser adotada pela solução depende tanto das ferramentas utilizadas como das necessidades do cliente.

No caso do Access, o uso compartilhado quase sempre se baseia numa rede local (LAN). O caminho, já bastante conhecido e documentado, é dividir a aplicação em front-end e back-end, de forma que cada estação rode o motor Jet e acesse o arquivo de dados centralizado no servidor. Esta estrutura é chamada Arquivo-Servidor (File-Server).

Uma outra estrutura possível com o Access é a Cliente-Servidor (Client-Server), em que o Access é usado como front-end de um banco de dados SQL Server ou MSDE, sendo que todos os dados são gerenciados pelo servidor.

O que fazer, porém, quando não houver uma rede disponível? Imagine, por exemplo, que você tenha uma equipe de vendedores que fazem visitas externas e precisam lançar dados no sistema, sem estarem conectados a uma rede. Qual seria a solução?

Para estes e outros casos, a solução pode estar nos bons (e pouco explorados) recursos de replicação de bancos de dados Jet, que você conhecerá melhor ao longo desta matéria.

O que é a replicação do Access

Vimos que o Access pode ser compartilhado numa estrutura Arquivo-Servidor ou Cliente-Servidor. A replicação é a terceira maneira de se compartilhar uma base de dados Jet. Cada usuário trabalha isoladamente na sua própria réplica do BD, e com alguma periodicidade os dados são sincronizados, atualizando-se as cópias.

Esta estrutura é especialmente útil quando os usuários não têm acesso à rede e não precisam ter em tempo real as atualizações feitas por outros usuários. A replicação também funciona melhor quando o trabalho com o BD envolve mais a adição de novos registros do que a edição de registros existentes.

Imagine, por exemplo, que seu cliente lhe procure com a seguinte solicitação: “Tenho duas lojas e quero que as informações de vendas sejam diariamente trazidas ao meu escritório, para que eu possa carregar no meu sistema administrativo. Também quero que o cadastro de clientes seja único, ou seja, se uma pessoa preencher seus dados na Filial 1, não quero que a Filial 2 lhe peça novamente as mesmas informações se um dia ele fizer compras por lá”.

Este cenário pode ser bastante interessante para se usar BDs replicados: o cliente não precisa dos dados atualizados em tempo real (o dia anterior já lhe é suficiente), o trabalho de cada filial consiste basicamente em inserir novos registros e eventualmente atualizar registros já existentes, e os custos de uma rede seriam elevados.

A solução de seu cliente poderia ser, então, usar uma réplica do banco de dados em cada filial, e periodicamente sincronizar os dados.

As três etapas

O trabalho com BDs replicados envolve três etapas: criação das réplicas, sincronização e resolução de conflitos.

A réplica do banco de dados não é uma simples cópia de arquivo: para que a sincronização possa ser feita, o Jet utiliza tabelas de sistema e campos adicionais nas tabelas de usuário, os quais são incluídos no momento da criação da réplica.

A sincronização é o processo em que os dados são sincronizados, resultando num novo conjunto de dados. Como um mesmo registro pode ter sido atualizado por dois ou mais usuários, há a possibilidade de conflitos a serem resolvidos.

Você verá com mais detalhes cada uma das etapas ao longo desta matéria.

Mecanismos para gerenciamento de replicação

Para trabalhar com estruturas replicadas, é necessário ter mecanismos para gerar réplicas, fazer a sincronização e resolver os conflitos resultantes. Temos à disposição os seguintes métodos:

- Porta-Arquivos do Windows (Windows Briefcase): é um mecanismo relativamente simples (o usuário só precisa arrastar e soltar arquivos), mas bastante limitado.

- Menus internos do Access: oferece a maioria dos recursos suportados pelo Jet 4, e também uma ferramenta visual para solução de conflitos. É simples de se usar, mas requer o Access instalado na máquina. É o mecanismo que será usado nesta matéria.

- Código JRO: é o principal e mais completo recurso de programação disponível ao desenvolvedor para se trabalhar com replicação. É usado para automatizar soluções de forma a não precisar da intervenção do usuário, e nem do Access instalado na máquina. Não oferece mecanismo já pronto para solução de conflitos, mas é possível codificar um.

- Código DAO: é outro recurso de programação disponível ao desenvolvedor, mas não é tão completo quanto o JRO.

- Replication Manager: é uma ferramenta visual disponível a quem tem a versão Developer do Microsoft Office. Oferece diversos recursos de replicação e sincronização, sem precisar ter o Access instalado na máquina.

Nível de rastreamento

A partir do Access 2000 (Jet 4), foi introduzida uma inovação importante nos recursos de replicação: a propriedade de rastreamento em nível de campo. Até então, o rastreamento era feito apenas em nível de linha, ou seja, se um usuário alterasse o nome de um cliente e outro usuário alterasse o telefone deste mesmo cliente (campos diferentes), ainda assim ocorreria um conflito, pois o Jet não identificava os campos individualmente, apenas o registro todo.

Com o Jet 4, o rastreamento em nível de campo foi introduzido como padrão. Se por alguma razão o desenvolvedor quiser alterar esta configuração, basta clicar com o botão direito sobre a tabela (na tela principal do MDB), selecionar Propriedades e assinalar Rastreamento em nível de linha (Figura 1). Se a caixa não estiver marcada, o rastreamento será em nível de coluna.

Figura 1: Propriedades de tabela - nível de rastreamento

Esta configuração deve ser feita antes de se replicar o banco de dados, pois não poderá ser alterada posteriormente.

Preparando o BD para testes

O aplicativo em que trabalharemos será bem simples: uma tabela de clientes (tblClientes) com dois campos: nome e telefone (Figura 2). O arquivo, chamado bdMatriz.mdb, está disponível para download no site da revista, com registros já preenchidos para você fazer os testes.

Figura 2: Estrutura da tabela de testes

Se você preferir lançar registros por conta própria (ao invés de fazer download com a tabela já preenchida), lance-os neste momento, antes de fazer a replicação. Embora a tabela de exemplo tenha cerca de 90 registros, você não precisará mais que 10 linhas para seguir as instruções seguintes.

Criação da estrutura-mestre e réplicas

Como foi visto anteriormente, a replicação consiste no processo de criação de múltiplas cópias de uma aplicação. Esse conjunto recebe o nome de conjunto de réplicas, e é formado por uma única estrutura-mestre (cópia onde são feitas as atualizações na estrutura) e uma ou mais réplicas (demais cópias, sem acesso ao modo estrutura).

Para converter o exemplo bdMatriz.mdb em estrutura-mestre, abra-o e clique no menu Ferramentas > Replicação > Criar réplicas. O Access pedirá uma confirmação antes de fechar e criar a estrutura-mestre (Figura 3), e em seguida perguntará se você quer criar uma cópia de back-up (Figura 4), o que é bastante recomendável.

Figura 3: Confirmação para criação de estrutura-mestre

Figura 4: Aviso de criação de backup

Em seguida será aberta a janela para você selecionar o local e o nome da primeira réplica. Use o nome bdFilial1.mdb e mantenha as demais configurações como estão (Prioridade = Padrão, caixa Impedir Exclusões desmarcada). Estas propriedades serão explicadas logo adiante.

Não ocorrendo erros, você receberá uma mensagem de êxito e o BD de estrutura-mestre será aberto. Veja que a tabela replicada (tblCliente) é sinalizada com o ícone de replicação (Figura 5).

Cada tabela e consulta tem a propriedade Replicável, podendo haver no MDB objetos replicáveis e objetos locais. Para alterar esta propriedade, basta clicar com o botão direito do mouse sobre o objeto (na tela principal do MDB) e abrir a janela de propriedades. Tabelas relacionadas, entretanto, ou são locais ou são replicadas, não sendo possível relacionar uma tabela local a uma tabela replicada.

Quanto aos outros objetos (formulários, relatórios, macros, módulos e páginas), eles podem ser replicados para terem sua estrutura atualizada no momento da sincronização. Ou são todos replicados (em conjunto) ou não. Isto ocorre porque eles são salvos como um objeto binário único, diferentemente do que ocorria na versão anterior do Jet. Importante: esta decisão deve ser tomada antes da criação da estrutura-mestre. Para ajustar a propriedade Replicável destes objetos, vá ao menu Arquivo > Propriedades do Banco de Dados > Personalizar. Se o MDB foi convertido a partir de uma versão anterior ao Jet 4, a propriedade não estará disponível: você precisará criar um novo MDB e importar todos os objetos.

Quando o banco de dados se torna replicável, algumas tabelas e campos adicionais são criados para gerenciar a edição e posterior sincronização de registros. Para exibi-los, vá ao menu Ferramentas > Opções > Exibir e assinale a caixa Objetos do Sistema. O resultado será semelhante ao da Figura 5.

Figura 5: janela do MDB estrutura-mestre

Com a exibição de objetos do sistema ativa, podemos ver que às tabelas de usuário replicadas (tabelas criadas pelo desenvolvedor, como tblCliente) foram adicionados alguns campos:

- s_Generation: se tem o valor zero, indica linha nova ou linha alterada. Se o valor for diferente de zero, representa a geração da réplica em que a alteração foi feita.

- s_GUID: valor que identifica a linha de forma única entre as réplicas, mesmo que o valor da chave primária mude. Exemplo de GUID (Globally Unique Identifier): {BC046CFC-8EBC-43A0-8BBA-2D81AA225A92}

- s_Lineage: rastreia o histórico de alterações do registro. Decide quem prevalece em caso de conflito.

- s_colLineage: é adicionado a tabelas com rastreamento em nível de colunas. Decide quem prevalece em caso de conflito.

O Jet também criou tabelas de sistema adicionais, como MSysConflicts (armazena informações sobre os conflitos), MSysFilters (armazena informações sobre os filtros de réplicas parciais), MSysReplicas (armazena o GUID de cada réplica do conjunto de réplicas), e diversas outras.

A terceira modificação importante feita pelo Jet na base de dados é a alteração de campos autonuméricos seqüências para autonuméricos aleatórios. Isto reduz bastante a chance de duas réplicas criarem o mesmo valor, visto que a seleção varia entre -2 bilhões e +2 bilhões.

A modificação do comportamento dos campos autonuméricos quase sempre afeta negativamente as aplicações existentes, pois geralmente tal campo é usado como um ID seqüencial e lhe é atribuído um significado prático. Neste caso, a única saída é criar um campo numérico comum (Inteiro Longo) e adotar uma rotina de numeração personalizada com o VBA.

Depois de criada e configurada a estrutura-mestre e a primeira réplica, vá novamente ao menu Ferramentas > Replicação > Criar réplicas para criar a segunda réplica. Use o nome bdFilial2.mdb.

Veja na Figura 6 que a janela de diálogo de criação de réplica permite definir algumas propriedades adicionais, como a visibilidade (BD global, local ou anônimo), a prevenção de exclusão de registros nas réplicas e o nível de prioridade da réplica.

Figura 6: Criação de réplica

Visibilidade - cada réplica pode ter três níveis de visibilidade: global, local ou anônimo. A réplica Global pode ser sincronizada com outras réplicas globais e com as réplicas geradas a partir dela própria. A réplica Local, por sua vez, pode ser sincronizada apenas com a réplica global que a gerou, tendo como principal utilidade a criação de diferentes topologias no conjunto de réplicas (veja a Figura 7). Por fim, existem também as réplicas Anônimas, as quais funcionam de maneira semelhante às locais, porém suas informações não ficam permanentemente armazenadas na tabela MSysReplicas. É útil para réplicas que raramente são sincronizadas, e também para cenários envolvendo Internet.

Prevenindo exclusões: para evitar que o usuário de uma determinada réplica exclua registros existentes (o que teria efeitos nos outros BDs no momento da sincronização), a criação de réplicas por meio do menu do Access permite assinalar a opção de Impedir Exclusões. Esta é uma das pouquíssimas opções não oferecidas na criação de réplicas por código JRO.

Prioridade: em versões anteriores do Jet, a solução de conflitos era resolvida conforme a quantidade de atualizações do registro: a cópia mais vezes alterada vencia. No Jet 4 esse confuso mecanismo foi bastante melhorado. Cada réplica recebe um nível de prioridade (entre 0 e 100), que será usado para resolver os conflitos de sincronização. Por padrão, a estrutura-mestre recebe o nível 90, e cada réplica recebe 90% da réplica que a gerou (Parent Replica). Em caso de empate, a réplica com o menor ID (ou seja, a mais antiga) vence.

O Jet 4 trabalha com prioridade histórica. Se eu tenho um BD1 com prioridade 90, um BD2 com prioridade 80 e um BD3 com prioridade 70, os três com conflito de atualização em um dado registro, quem vencerá? Se eu sincronizar o BD1 com o BD3, o BD1 vencerá, pois tem maior prioridade. E se logo em seguida eu sincronizar o BD3 com o BD2, o que acontecerá? Pelo conceito de prioridade histórica, o BD3 vencerá, mesmo tendo menor prioridade que o BD2, pois tal registro veio do BD1, que tem maior prioridade. Isto garante que, no final das contas, o BD com maior prioridade prevalecerá, independente da ordem de sincronização.

Figura 7: Topologias de replicação para LAN

Lançando registros

Agora que a estrutura-mestre e as réplicas estão prontas, você lançará alguns registros para testar situações como inclusão, exclusão e edição de registros, além de conflitos. Siga o passo a passo a seguir:

1. Abra a réplica bdFilial1.mdb.

2. Abra a tabela tblCliente e adicione um novo registro: nome = James Boyce, telefone = (11)3232-0001. Note que o campo autonumérico não recebe mais números seqüenciais, e sim aleatórios. Se o BD estiver configurado para exibir objetos de sistema, veja também que o campo s_Generation recebe o valor 0, conforme explicado anteriormente.

3. Ainda com a tabela aberta, exclua os dois registros anteriores: Matti Karttunen (Cód. 90) e Zbyszek Piestrzeniewicz (Cód. 91).

4. Vá ao primeiro registro (Maria Anders) e apague o valor do campo Telefone.

5. Vá ao segundo registro (Ana Trujillo) e altere o nome para Ana Trujillo Garcia.

6. Vá ao terceiro registro (Antonio Moreno), altere o nome para Antonio Moreno Jr. e o telefone para (5) 555-0000.

7. Feche a réplica bdFilial1.mdb e abra bdFilial2.mdb.

8. No bdFilial2, abra a tabela tblCliente.

9. Adicione um novo registro: nome = Jim Buyens, telefone = (11)3232-0002.

10. Vá ao registro anterior (Zbyszek Piestrzeniewicz, Cód. 91) e altere o telefone para (11)3232-0003.

11. Vá ao segundo registro (Ana Trujillo) e altere o telefone para (11)3232-0004.

12. Vá ao terceiro registro (Antonio Moreno), altere o nome para Andy Wigley e o telefone para (11)3232-0005.

A Tabela 1 resume as alterações que foram feitas:

Tabela 1: Alterações feitas nas réplicas

Registro

bdFilial1

bdFilial2

1-Maria Anders

Telefone alterado

(sem alterações)

2-Ana Trujillo

Nome alterado

Telefone alterado

3-Antonio Moreno

Nome e telefone alterados

Nome e telefone alterados

90-Matti Karttunen

Excluído

(sem alterações)

91- Zbyszek Piestrzeniewicz

Excluído

Telefone alterado

Novo-James Boyce

Nome e telefone incluídos

(inexistente)

Novo-Jim Buyens

(inexistente)

Nome e telefone incluídos

Sincronização

A sincronização é o processo de atualização de dados e estrutura das réplicas.

Durante a sincronização, apenas as alterações nos objetos assinalados como replicáveis são consideradas. Os objetos locais não são sincronizados.

Quanto aos registros, apenas os sinalizados como alterados (s_Generation = 0) são atualizados (e não o banco de dados inteiro).

Para fazer a sincronização dos registros alterados na seção anterior, abra a estrutura-mestre (bdMatriz.mdb) e clique no menu Ferramentas > Replicação > Sincronizar agora. Será aberta uma janela para selecionar a réplica para sincronização (Figura 8). Selecione o bdFilial1.mdb e clique em OK. Aparecerá uma mensagem informando que o BD precisa ser fechado; clique em Sim para prosseguir.

Figura 8: Seleção de réplica a sincronizar

Depois de sincronizar, abra a tabela tblCliente para ver o resultado parcial: os registros 90 e 91 foram excluídos, o registro James Boyce foi adicionado e os registros 1, 2 e 3 foram alterados. Em todos eles, o campo s_Generation, que era 0, recebeu o número de geração da réplica.

Agora vá novamente ao menu Ferramentas > Replicação > Sincronizar e faça a sincronização com o bdFilial2.mdb.

Ao abrir o bdMatriz, aparecerá uma mensagem (Figura 9) informando que há conflitos a serem resolvidos. Clique em Sim para abrir o Visualizador de Conflitos (Figura 10).

Figura 9: Aviso de conflitos

Figura 10: Visualizador de conflitos lista de tabelas

Selecione a tabela com conflitos (tblCliente – 2 conflitos) e clique no botão Exibir para abrir a janela de detalhes do conflito (Figura11), onde você escolherá o vencedor e o perdedor em cada caso. Os 2 conflitos são:

1. Cliente 3, que teve o nome e o telefone alterados tanto pelo bdFilial1 como pelo bdFilial2.

2. Cliente 91, que foi excluído pelo bdFilial1 e editado pelo bdFilial2.

Escolha, para cada caso, a solução de sua preferência, e veja os resultados finais na tblCliente.

Figura 11: Visualizador de conflitos - escolha do vencedor

Observações:

- O registro do cliente 2 não apresentou conflitos porque cada BD alterou um campo diferente, e a tabela está configurada para fazer rastreamento em nível de campo. Se estivesse configurada para rastreamento em nível de linha, aí sim haveria conflito.

- O registro 90 (excluído pelo bdFilial1 e não alterado pelo bdFilial2) foi excluído após as sincronizações, mesmo tendo sido deletado apenas pelo bdFilial1 e mantido pelo bdFilial2. A exclusão de registros sempre tem prioridade no momento da sincronização (independente do nível de prioridade da réplica), exceto se o mesmo registro tiver sido editado por outro BD, o que causará um conflito.

Obs.: se a exclusão de registros por usuários descuidados for um problema para você, assinale a opção Impedir exclusões quando for criar as réplicas (assunto abordado na seção Criação da estrutura-mestre e réplicas).

Neste pequeno exemplo que fizemos, ocorreram os dois tipos de conflitos mais comuns:

- Um mesmo campo foi editado simultaneamente em duas ou mais réplicas.

- Um registro foi excluído em uma réplica e editado na outra.

Existem ainda outros tipos de conflito que podem ocorrer:

- Dois registros recebem a mesma chave primária.

- Um registro contém campo com valor que viola regra em nível de tabela.

- Quebra de integridade referencial por exclusão: uma réplica deleta a chave primária, enquanto outra réplica lança registros que dependem de tal chave.

- Quebra de integridade referencial por atualização: uma réplica altera o valor da chave primária, enquanto outra réplica lança registros que dependem de tal chave.

- Violação de chave estrangeira como resultado de registro envolvido em outro conflito.

- Bloqueio: a atualização não pode ser sincronizada porque outro usuário está bloqueando o registro no momento. Este erro não será colocado na lista de conflitos, portanto a sincronização deverá ser feita novamente quando a tabela não estiver bloqueada.

Réplica parcial, bloqueio de exclusão e visibilidade local

Por fim, você vai criar uma réplica parcial sem permissão para excluir registros e com visibilidade parcial.

Réplica parcial é aquela que não inclui todos os registros do banco de dados original; o mesmo é filtrado por um critério introduzido pelo usuário.

Abra a réplica bdFilial1 e clique no menu Ferramentas > Replicação > Assistente de réplica parcial.

No assistente, selecione Criar uma nova réplica parcial e avance. Em seguida, dê o nome de bdSubFilial1.mdb à nova réplica, selecione a opção Eu gostaria que essa fosse uma réplica local e assinale a caixa Eu gostaria que essa fosse uma réplica ‘Impedir Exclusões’. Na próxima janela, coloque a seguinte expressão de filtro: [ClienteID] >= 50 (Figura 12). Depois basta avançar e concluir para criar a nova réplica.

Figura 12: Assistente de réplica parcial

Abra agora o bdSubFilial1 e veja que a tabela de clientes tem apenas os registros cujo ClienteID é maior ou igual a 50. Se tentar excluir registros, não terá permissão.

Por ter visibilidade local, a sincronização do bdSubFilial1 só pode ser feita a partir da réplica que o gerou, o bdFilial1 (concentrador). Com as outras réplicas ele não é sincronizável, nem mesmo com a estrutura-mestre.

Conclusão

Vimos neste artigo como funcionam os recursos de replicação do Jet e percorremos todos os passos: criação da estrutura-mestre e das réplicas, lançamento de registros, sincronização e solução de conflitos.

Com as linhas gerais aqui passadas, você já pode planejar sistemas mais sofisticados, e se for o caso, aprofundar os estudos para desenvolver soluções automatizadas por meio de código JRO. É possível até mesmo usar código para resolver conflitos de sincronização sem intervenção do usuário.

Nos casos em que for possível adotar as estruturas File-Server ou Client-Server, a replicação provavelmente não será a melhor solução, pois as outras abordagens permitem evitar conflitos e fornecem aos usuários os dados sempre atualizados. A replicação é interessante por ser o único recurso disponível para se trabalhar de forma não conectada, ou como alternativa para aliviar redes sobrecarregadas.

Como os dispositivos de mobilidade (laptops, tablets, etc.) têm sido cada vez mais utilizados, é interessante ao desenvolvedor contar com os recursos de replicação na hora de planejar a solução para o seu cliente, visto que em alguns cenários a implantação de redes pode representar um gasto alto e desnecessário, especialmente quando a disponibilidade imediata dos dados de outros usuários não for crítica.

Luiz Cláudio Cosenza V. Rocha

Luiz Cláudio Cosenza V. Rocha - Diretor da IT Lab Consultoria (www.itlab.com.br), em São Paulo, especializada em desenvolvimento customizado, .NET, Office (VBA/VSTO), SharePoint e ALM. Nomeado pela Microsft como MVP de Office System desde 2003, tem dezenas de artigos publicados, material de treinamento, participa diariamente dos fóruns MSDN e escreve o blog OfficeDev (http://msmvps.com/blogs/officedev/).