sexta-feira, 23 de abril de 2010

Fazendo Backup de um Repositório SVN

Um repositório do SVN é, na verdade, um banco de dados, embora tendo suas próprias peculiaridades. Assim, ele pode sofrer backup e pode ter seu conteúdo restaurado, total ou em parte. Este artigo ensina apenas a fazer backup do repositório. Há outros artigos nossos com outros tutoriais sobre o SVN que podem ser consultados: como configurar o SVN por túnel de SSH, os modos de configuração do SVN; configurando o SSH para atuar com o SVN.
Cada repositório SVN tem uma variável numérica que é incrementada a cada novo commit (efetivação), denominada "revision". Quando se faz backup, é interessante saber-se em qual número está o revision, ou para contabilizar a quantidade de alterações que foram enviadas, ou mesmo para saber se houve mudanças realmente desde o último backup. Para se obter o número da revisão mais recente, utilize o seguinte comando:

svnlook youngest [path e nome do repositório]

Exemplo:
$ svnlook youngest /var/svn/repo15
237
$

O comando anterior responde apenas o número da revisão, de forma que sua saída pode ser colocada diretamente em uma variável de um script. Para se obter mais informações sobre quem é o autor da última revisão e quando ele fez o commit, utilize o comando:

$ svnlook info /var/svn/repo15
fulano
2010-04-21 23:48:41 -0300 (Qua, 21 Abr 2010)
48
Esta é a mensagem que o autor deixou na revisão.

As linhas da resposta são: autor, data da revisão, número de caracteres da mensagem e a mensagem da revisão.
Ou, para inspecionar uma revisão anterior específica, use:

$ svnlook info /var/svn/repo15 -r 200
[sendo 200 a revisão antiga que se deseja inspecionar]

  • Backups Completos
O backup completo pode ser feito com o segunte comando:

$ svnadmin dump /var/svn/repo15 > repo15.r237

Isto fará o backup completo do repositório e o colocará no arquivo "repo115.r237", que pode ter o nome que você desejar. É claro que, quanto maior o repositório, mais lenta esta operação e maior será o arquivo (embora o arquivo de backup costume ser menor que o repositório em si). Muitas vezes, é isso mesmo que desejamos. No entanto, é possível se fazer backup de parte do repositório, a partir de números de revisão informados. Outra forma de backup pode ser:

Fazendo uma cópia direta do repositório para outro, que ficará idêntico ao primeiro:

svnadmin hotcopy /var/svn/repo15 /var/svn/repo16
[funciona exatamente como um comando "cp -r"]

Nesta opção, se você usa o Berkeley DB, você pode dar uma "limpada" nos arquivos de log que não são mais usados, diminuindo o tamanho do repositório. Para tanto use esta opção:

svnadmin hotcopy --clean-logs /var/svn/repo15 /var/svn/repo16

O novo repositório criado é completamente funcional e pode inclusive sofrer dump!!

  • Backups Parciais
Utilize o seguinte comando, para fazer backup de apenas uma faixa de revisões desejada:

[backup apenas da revisão 200]
$ svnadmin dump /var/svn/repo15 -r 200 > repo15.r200

[backup apenas da revisão 100 a 200]
$ svnadmin dump /var/svn/repo15 -r 100:200 > repo15.r100-200

Se o seu repositório é gigantesco, é possível que se crie vários arquivos de dump separados. Para tanto, deve-se usar a opção "--incremental". Exemplo:

$ svnadmin dump /var/svn/repo15 -r 0:1000 > dumpfile1
$ svnadmin dump /var/svn/repo15 -r 1001:2000 --incremental > dumpfile2
$ svnadmin dump /var/svn/repo15 -r 2001:3000 --incremental > dumpfile3

  • Recuperando o Backup
Como dizem as boas normas de segurança: não basta fazer o backup, mas é preciso se TESTAR O BACKUP!! Assim, vamos recuperar o backup para o repositório. Sem saber isso, de que valeria tê-lo, não é mesmo??

svnadmin load /var/svn/repo16 < repo15.r237

Isto fará um monte de commits, exatamente como seus autores o fizeram, alimentando o novo repositório com o conteúdo de dump do arquivo de backup.
Um backup direto pode ser feito sem a necessidade de arquivo de backup, da seguinte maneira:

svnadmin dump /var/svn/repo15 | svnadmin load /var/svn/repo16

Bom, espero ter ajudado com todas estas dicas... se este artigo te ajudou, atrapalhou, resolveu seu problema ou acabou de vez com sua vida, simplesmente: COMENTE!!!!

24 comentários:

Rafael Albani disse...

Muito bom o artigo, simples e objetivo, estava procurando a algum tempo um artigo que mostrasse o processo de forma direta, me ajudou muito.

O Pajé disse...

Muito obrigado, Rafael!! Fico feliz de ter podido ajudar!!

Anônimo disse...

Muito bom era o que eu precisava!

Elisa Zaroni Camargo disse...

Comentário, conforme pedido do autor.....

Post rápido, bem escrito e direto no ponto. Só fiquei uma dúvida: posso fazer um dump em uma instância e load em outra ? Ele consegue manter todo o histórico ?

E, para quê serve limpar as logs ? (essa eu vou ler no manual, mas se puder..., agradeço).

Tx a lot!

O Pajé disse...

Olá Elisa!!

Obrigado pelos elogios ao post!! Respondendo à sua pergunta:

Sim, é possível fazer o dump em uma instância e fazer o load em outra!!
Se o seu dump for completo, então o repositório onde será feito o load deverá ter sido recém-criado e, portanto, deverá estar vazio. Se o seu load for um "incremental", espera-se que o repositório de load esteja com o número de revisão imediatamente anterior à primeira revisão armazenada no arquivo de dump de incrementação.

Quanto à limpeza dos logs: o SVN tem o comportamento padrão de fazer registros de todas as operações em arquivos de log que ficam dentro dos repositórios. Assim, ele armazena não só commits, mas também updates, checkouts e outras operações que não são de escrita propriamente, gerando muitas vezes logs grandes, cheios de dados de checkouts e updates dos usuários. Imagine uma equipe enorme fazendo update toda hora, ou um SVN público de um projeto Open Source que sofre update e checkout do mundo inteiro a todo instante!! De vez em quando, o SVN até dá uma limpada mas, se você considera que estas informações não são úteis (ao menos não no disco, dentro do diretório do repositório), então é possível se livrar delas numa migração (um dump seguido de load), conforme mostrei acima. Isto pode te poupar espaço em disco e aumentar ligeiramente o desempenho do SVN, pois voltará a lidar com arquivos menores ou menor quantidade de arquivos, ou pelo menos acelerar a geração do dump e a carga do load.

Anônimo disse...

Gostei muito desse post, e como disse o Rafael logo no primeiro comentário, muito bom post - simples, direto ao assunto. Confesso que é preciso pensar um pouco para entender como os comandos funcionam e tal, mas essa é uma propriedade das coisas sucintas - demandam trabalho de entendimento. Me ajudou a dar os primeiros passos no assunto de dumps e loads. Preciso consertar um repo que tem uma revisão "quebrada" e estou tentando algumas idéias, como dump e recarga diferencial, pulando a versão defeituosa (svnadmin: Decompression of svndiff data failed). Muito obrigado!

O Pajé disse...

Muito obrigado pelo retorno, rapaz!! Fico feliz de ter podido ajudar!!
Com relação ao seu problema, se for possível, tente o seguinte:

1- Fazer o backup parcial, até a revisão imediatamente anterior ao commit quebrado;
2- Fazer o backup parcial, iniciando na versão imediatamente posterior ao commit quebrado e indo até o final;
(com isto pulamos uma revisão, a que está com problemas)
3- Fazer o load do primeiro backup;
4- Fazer um commit que substitua o commit quebrado;
5- Fazer o load do segundo backup.

Talvez isto o ajude a recuperar a saúde de seu repositório. Não apague nada antes de testar bastante. Faça o load sempre em um segundo repositório, ou seja, sem apagar ou danificar o original (ao menos até ter certeza de que tudo está certinho).

Fabio disse...

Nossa, valeu pelo retorno! De fato, é isso mesmo que eu estou tentando fazer e parece que está dando certo. A única coisa chata é que eu não consigo saber qual a operação exata foi feita no commit quebrado. Assim, quando eu retorno um dump que age sobre o que foi adicionado naquele commit quebrado, ele dá pau - mas nesse momento eu descubro como deveria ser, volto tudo, corrijo e avanço de novo... Eu olhei o log dos commits adiante e estou me guiando por eles.

Fabio disse...

Et voi-là! Resolvido! Apesar de aparentemente eu ter migrado meu repositório para uma versão mais nova, tudo está funcionando! Valeu pelo apoio!

O Pajé disse...

Beleza, Fabio!!

O caminho é este mesmo!! Parabéns pela resolução do problema!!
A versão nova não deve dar problemas com relação ao dump e ao load. Mas, tome cuidado se vc resolver voltar para uma versão antiga depois. E, claro, sempre bom fazer backups do repositório.

Alexandre Eugênio disse...

Excelente post! Me ajuda sempre!
Obrigado.

Uyara disse...

Valeu cara, ajudou sim, esclareceu tudo. Na empresa que estou estavam apenas compactando o arquivo para backup, mas não ia funcionar.

O Pajé disse...

Que bom que ajudou, fico feliz!!
Aproveitando, vale sempre a pena lembrar que, quando se trata de backup, devemos ter em mente uma regra mágica para o sucesso: testar o backup; ou seja, de quando em vez, pegue um backup que você gerou e tente recuperá-lo em um repositório diferente, criado apenas para efeito de testes. Assim, se tudo correr bem, seus backups estão realmente seguros e podem ser usados em qualquer emergência, a qualquer momento.

Cristiano disse...

Olá Rafael, tudo bem? Parabéns pelo artigo, muito bom. Tenho uma situação e gostaria de ver se você pode me ajudar. Tenho um repositório muito grande, que está ocupando muito espaço em disco. Supondo que o repo tenha 300 revisões... É possivel remover fisicamente do disco as 200 primeiras reviões e manter as 100 ultimas revisões? Caso sim, qual o procedimento? Desde já, agradeço!

O Pajé disse...

Olá Cristiano,

A recomendação do SVN é exatamente que não se faça isso. Remover revisões antigas vão prejudicar o que o SVN traz de mais interessante, que é a memória do histórico de alterações e a possibilidade de se retornar a qualquer estado anterior dos dados versionados.

Uma excelente prática seria vc trabalhar com mais de um repositório (exemplo: um repositório por projeto), de modo que não ocupe tanto espaço assim, ou isolar projetos que tenham muitos arquivos grandes (como imagens) em um repositório próprio.

A recomendação do SVN é que se tenha um repositório por projeto, e não um repositório para a empresa toda, como é, infelizmente, uma prática muito comum no mercado, até onde tenho visto.

Lembre-se de que o SVN é, em última análise, um banco de dados orientado a alterações dos arquivos originais. Significa que cada commit (um insert no banco) guarda apenas as alterações realizadas, e não o arquivo todo de novo. Por isso, é sempre importante se ter a versão anterior, para ser possível recuperar a parte do dado que não foi alterada.

Cristiano disse...

Bom Dia Rafael, desde já, agradeço pelo retorno.

Quanto a forma de utilização do SVN, trabalho exatamente da forma que você falou. Eu não tenho um repositório único para a empresa toda, pelo contrário, modularizei todo o SVN, e para cada sistema, há um repositório distinto. Porém, na nossa fábrica de software há mais de 300 sistemas, e 180 profissionais. Uma média de 15G de commits de artefatos por mês (código fonte, documentação, etc). Dentre esses repositórios, há alguns repositórios de sistemas legado que estão muito grandes. Para estes repositórios é que a minha intenção era remover fisicamente do disco as revisões mais antigas e deixar somente as revisões mais atuais. Acho que o jeito vai ser fazer um export do repositório, guardar esse export em uma mídia de BKP, remover o mesmo do servidor e construir um outro repositório do zero.

Abraço!

Jean Fernandes disse...

Prezado

Eu instalei o SVN Server da Collabnet numa máquina com windows 7, que acesso via ddns de fora da rede. Um questionamento que tenho é se é possível replicar esse SNV em outra máquina, para que eu possa ter além de segurança, a possibilidade de ter um hot stand by, ou seja ter o mesmo SNV em locais físicos distintos, aumentando a disponibilidade do serviço.

Eu li que é possível fazer um mirror. Entretanto, o SNV espelhado fica apenas como leitura.

Desde já agradeço pelas informações postadas. Excelente material.

Jean
Eng4Sys

O Pajé disse...

Olá Jean,

Ótima pergunta!! Até onde eu conheça, de dentro do SVN não é possível fazer essa configuração avançada. O SVN não tem tanta flexibilidade para trabalhar com múltiplas instâncias, como o MySQL, por exemplo. Contudo, é perfeitamente possível fazer o que vc quer. Lembre-se de que o repositório do SVN é, nada mais, que um diretório no sistema de arquivos com o banco de dados dele.

Assim, como resolver o seu problema? Vamos supor que vc tenha a seguinte configuração:

- servidor 01, principal;
- servidor 02, backup.

Todos os commits são dados no servidor 01, mas precisam ser imediatamente atualizados para o servidor 02, de modo que vc tenha uma cópia fiel e operacional do banco de dados do repositório.

A maneira mais simples de se fazer isso é usando um "post Hook". O que é isso?? "Hooks", para o SVN, são scripts (em python) que são disparados a partir de eventos do SVN, como um commit, por exemplo. Alguns já existem em seu SVN e provavelmente são carregados automaticamente. Outros, vc pode criar, configurar e utilizar livremente. Um "post Hook" é um script que é executado DEPOIS de um evento, ou seja, depois de um commit, por exemplo.

Portanto, vc deve escrever um script que faça o seguinte:

1- Acha a versão mais recente de ambos os servidores, como mostrado no artigo acima (svnlook youngest [path e nome do repositório]).
2- Compara uma com a outra para saber se são diferentes;
3- Caso sejam, fazer um backup parcial do repositório que tem a versão mais recente (seja ele o do servidor 01 ou do servidor 02);
4- Fazer commit no outro repositório, através da restauração do backup (load), utilizando o backup parcial gerado.

Este script vai manter ambos os repositórios em sincronia, ou até mais repositórios, se vc quiser. Agora, basta instruir o SVN para chamar este script sempre que for dado um commit. Isto deve ser feito na configuração do SVN, através de Post Hook, em ambos os servidores.

Mais informações sobre Hooks:

http://svnbook.red-bean.com/en/1.8/svn.reposadmin.create.html

Existem muitos sites não oficiais e fóruns ensinando como configurar um Hook, mas creio que o link acima vá te ajudar.
Depois q fizer, volte ao Pajé e conte sua experiência!!
Obrigado e boa sorte, amigo!!

Marcus Deserto disse...

Boa tarde,
Será que tem como migrar de um server para outro, pois troquei de server e estou com dificuldade de passar as configurações para outro server.

O Pajé disse...

Olá Marcus,

Tem como migrar sim, mas vc precisa dar mais informações sobre como está configurado seu SVN. Ele usa o WebDAV do Apache? A migração mais simples é a simples cópia binária de todo o repositório. Se vc usa WebDAV, SSH ou outro meio de acessar o repositório, então deve configurar estes serviços de modo semelhante ao servidor de origem.

Leonel Araújo disse...

Artigo, bem objetivo e muito útil para quem está iniciando com SVN como eu... parabéns!

O Pajé disse...

Obrigado, Leonel!! Creio que seja de seu interesse dar uma olhada nos nossos outros artigos sobre SVN. Clique no link "SVN" nos marcadores, para ver a listagem completa.

Abraços do Pajé!

Antonio Guedes disse...

Ótimo artigo, muito claro e direto. Acho que fiz algo errado, pois depois de fazer o backup, fiz a recuperação em um repositório novo. Porém, ao invés de recuperar no diretório TRUNK colocou os arquivos na raiz do repositório.
Também, recuperou a pasta Branches.
Você pode me ajudar? O quê fiz errado?
Obrigado
Antonio

O Pajé disse...

Olá Antonio,

Você poderia detalhar mais o que vc fez? Copie aqui a lista de comandos que vc aplicou. Você fez o dump do repositório todo, completo, ou de parte dele, a partir de uma determinada revisão? Quando vc fez o backup, usou qual método? O hotcopy ou o dump/load?

Abraços,

Pajé.