posts - 262,  comments - 221,  trackbacks - 0
【1.业务需求】
作为开发人员,最大的噩梦莫过于自己辛辛苦苦开发的程序由于各种原因而丢失了。所以定期备份资料乃是开发人员的一大美德(我自己重要的资料备份了4份,分别放在不同的地方)。SVN作为代码和文档汇聚之地,定期备份的重要性更是不容置疑。

【2.基本思路】
通常我们备份的方式无非有:完全备份和增量备份两种。完全备份适用于版本库的大小比较小的情况,对于版本库比较大或者已经存在版本库的情况下,则没有必要也不可能使用完全备份了。这时增量备份就是一个很好的选择。

除了完全备份和增量备份,我们还有另外一种方式:版本库同步。这种方法可以在源版本库和目标版本库之间做同步(通常是单向的)。一旦源版本库发生了改变则可以马上通知目标版本库做出相同的改变。

注意:版本库的备份不能简单地使用copy-paste的方法来拷贝复杂版本库的db目录,否则有可能出现数据不完全的情况。

所以我们的备份策略是:
 ①首次备份采用完全备份,后续备份采用增量备份和版本库同步
 ②完全备份在晚上定时进行,增量备份和版本库同步在用户提交时进行

注意:这个策略实际上是有较大问题的(包括备份的方式,频度,时间):通常完全备份会在每周,月进行一次。而增量备份会,版本库同步会在每天晚上定时执行,而不是在每次用户提交后执行,以缩短请求响应。但这里因为本着简单的原则,只是抽取了最简单的策略

【3.相关命令】
SVN用于备份的命令有以下三个,分别对应于完全备份,增量备份,版本库同步。

 ①svnadmin hotcopy
 ②svnadmin dump [--incremental]
 ③svnsync init|sync

关于这三个命令的具体用法,请大家自行参考SVN的用户手册以获得更多资讯。

【4.示例操作】
注:本示例代码均为网上下载,非本人原创。

Example 1:完全备份

fullbackup.bat
@echo off

@echo 不同的系统平台和时间格式设置会影响目录的创建,请先用echo命令输出日期格式并做相应调整

rem Subversion的安装目录
set SVN_HOME=C:\Develop\Subversion

rem 所有版本库的父目录
set SVN_ROOT=C:\Develop\svntest\testRepos

rem 备份的根目录
set BACKUP_SVN_ROOT=C:\Develop\svntest\svnbackup\full

rem 每次备份的子目录
set BACKUP_DIRECTORY=%BACKUP_SVN_ROOT%\%date:~4,14%

rem 如果备份的子目录不存在则先创建
if exist %BACKUP_DIRECTORY% goto checkBack
echo 建立备份目录%BACKUP_DIRECTORY%
>>%BACKUP_SVN_ROOT%/backup.log
mkdir %BACKUP_DIRECTORY%

rem 验证目录是否为版本库,如果是则取出名称备份
for /r %SVN_ROOT% %%I in (.) do @if exist "%%I\conf\svnserve.conf" %SVN_ROOT%\dofullBackup.bat "%%~fI" %%~nI
goto end

:checkBack
echo 备份目录%BACKUP_DIRECTORY%已经存在,请清空。
goto end
:
end

dofullbackup.bat
@echo 正在备份版本库%1
@%SVN_HOME%
\bin\svnadmin hotcopy %1 %BACKUP_DIRECTORY%\%2
@echo 版本库%1成功备份到了%
2

由于批处理文件中%date命令的输出格式受平台的控制(实际上是控制面板中的时区设置)影响,所以对于文件中使用到date函数的地方,读者要特别注意。需要首先在DOS下确认日期输出格式,然后根据实际情况进行截取。

将这两个文件放在repository的同级目录下,执行之则可以。读者可以自行修改上面的环境变量设置

Example 2:增量备份

post-commit.bat
echo off

set SVN_HOME=C:\Develop\Subversion
set SVN_ROOT=C:\Develop\svntest\testRepos
set UNIX_SVN_ROOT=C:/Develop/svntest/testRepos
set DELTA_BACKUP_SVN_ROOT=C:\Develop\svntest\svnbackup\delta
set LOG_FILE=%DELTA_BACKUP_SVN_ROOT%\backup.log

@echo 不同的系统平台和时间格式设置会影响目录的创建,请先用echo命令输出日期格式并做相应调整

rem  版本库增量导出
for /r %SVN_ROOT% %%I in (.) do  if %UNIX_SVN_ROOT%/%%~nI== %1 echo 备份开始  版本路径:%SVN_ROOT%\%%~nI  版本号:%2 >>  %LOG_FILE% | %SVN_ROOT%\%%~nI\hooks\deltaBackup.bat %%~nI %2
goto end

:
end

这个批处理文件的重点在于%UNIX_SVN_ROOT%/%%~nI == %1这句话。它的作用是判断当前提交的目标版本库是不是和循环中的变量值相同,如果是那么认为该修改是提交到这个版本库的,就可以进行增量备份了。我在运行这个文件时,一开始老是失败,后来发现原因居然是路径的写法问题。

请注意UNIX_SVN_ROOT这个变量的路径值写法,如果你换成SVN_ROOT看看,肯定是不会成功的。因为路径的写法不同! 

deltaBackup.bat
@echo 正在备份版本库%2 
@%SVN_HOME%
\bin\svnadmin dump %SVN_ROOT%\%1 --incremental --revision %2 >> %DELTA_BACKUP_SVN_ROOT%\%1-%date:~4,14%.dump
@echo 版本库%2成功备份到了%
3

这个文件里面特别要注意的就是--incremental这个参数,如果你不加上去的话以后再执行load就会提示版本库已经存在的错误了!而--revision则用于指定备份的版本。

将以上两个文件放置在repository的hooks目录下即可。

Example 3:版本库同步

首先创建一个版本库用于同步(目标版本库),其次要在源版本库和目标版本库之间建立联系。这是通过svnsync init来达到的。

svnsync init 目标库URL 源库URL

这个命令执行过程中可能需要增加两个参数--username和--password用于指明目标版本库的用户名和密码。

其次在目标版本库的hooks目录下建立一个空的文件并命名为pre-revprop-change.bat。这一步很重要,否则会出现鉴权失败的错误。最后就是在源版本库的hooks目录下建立一个名为post-commit.bat的文件,如下所示:

echo off

rem 版本库同步
%SVN_HOME%\bin\svnsync sync  --non-interactive svn://localhost/newRepo_backup

但用户在源版本库执行了相应的修改动作之后,你会发现目标版本库也出现了同样的修改!

附件:完整测试目录及脚本文件


-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2008-12-30 17:35 Paul Lin 阅读(2477) 评论(5)  编辑  收藏 所属分类: 项目管理


FeedBack:
# re: 【版本控制之路】版本库的备份
2008-12-30 19:04 | 激情
just test!!!  回复  更多评论
  
# re: 【版本控制之路】版本库的备份
2008-12-31 20:00 | 梦想在这里起飞
写得不错啊,看看我这个
开源的报表ireport项目web应用
http://ireport.cubebi.com


  回复  更多评论
  
# re: 【版本控制之路】版本库的备份[未登录]
2009-01-01 11:01 | Paul Lin
@梦想在这里起飞

支持国产软件,很不错!
  回复  更多评论
  
# re: 【版本控制之路】版本库的备份
2009-01-02 11:43 | 爱吃鱼头
svn很重要!备份很重要!向lz学习了!  回复  更多评论
  
# re: 【版本控制之路】版本库的备份
2010-03-30 11:01 | 醉月茶
很好,拜读了~  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2008年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

留言簿(21)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜