浏览 2038 次
锁定老帖子 主题:数据库(增量恢复)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-10-09
最后修改:2009-10-10
生产线的sqlserver数据库infoservice星期日做全盘备份,备份名为:infoservice_database.7,星期一做差异备份:infoservice_database.1,星期二:infoservice_database.2...
对应的本地模拟库infoserviceonline要定期恢复,恢复顺序与备份顺序相反. 如今天是星期一,要先还原 上个星期日的全盘备份,再还原今天的差异备份. 本程序支持在数据库服务器恢复,也支持在工作站恢复. 断开数据库的存储过程(创建于master库): Create proc DisconnectDB(@dbname varchar(20),@reason nvarchar(200)=null,@delay varchar(8)='00:00:30') declare @sql nvarchar(500),@cmd nvarchar(500) declare @spid int declare @hostname nvarchar(255),@pgname nvarchar(255) declare @flag bit set @reason=isnull(@reason,N'未知') set @flag=0 set @sql='declare getspid cursor for select spid,hostname,program_name from master..sysprocesses where dbid=db_id('''+@dbname+''')' exec (@sql) open getspid print 'ready' fetch next from getspid into @spid,@hostname,@pgname while @@fetch_status <>-1 begin set @flag=1 set @cmd='net send '+ltrim(rtrim(@hostname))+' 请及时保存你的程序:'+ltrim(rtrim(@pgname))+'的相关数据,'+'数据库:'+@dbname+'将于'+@delay+'后断开连接.'+'原因:'+@reason print @cmd exec master.dbo.xp_cmdshell @cmd fetch next from getspid into @spid,@hostname,@pgname end close getspid deallocate getspid if @flag=1 waitfor delay @delay exec (@sql) open getspid fetch next from getspid into @spid,@hostname,@pgname while @@fetch_status <>-1 begin exec('kill '+@spid) fetch next from getspid into @spid,@hostname,@pgname end close getspid deallocate getspid print 'disconnect db:'+@dbname+' completely!' return 0 python脚本 import logging import os,shutil,subprocess import re import datetime from datetime import timedelta from datetime import date global_log='D:\\tmp\\RestoreInfoServiceDB.log' global_smb_db_filepath='\\\\192.168.0.84\\f$\\ftproot\\infoservice.online\\' global_localtmpdir='d:\\tmp\\' global_notify_user=['192.168.0.129','192.168.0.124'] global_sqlserver_user='sa' global_sqlserver_password='hpsystem' global_sqlserver_source='192.168.0.86' global_sqlserver_db='infoserviceonline' global_disconnectdb_delay='00:00:30' # filemode='r',只读,清除原有内容(默认方式) filemode='r+',读写,清除原有内容 # filemode='w',只写,创建一个新的文件覆盖旧的 filemode='w+',读写,创建一个新的文件覆盖旧的 # filemode='a',只写,追加 filemode='a+',读写,追加 # filemode='b',二进制模式 logging.basicConfig(level=logging.DEBUG,format='[%(asctime)s] [%(levelname)s] %(message)s',filename=global_log,filemode='a') logging.getLogger(global_log) def NotifyUser(level,message): logging.debug("进入消息通知函数:NotifyUser") if level==1: messagekind='提示:' if level==2: messagekind='警告:' if level==3: messagekind='错误:' for user in global_notify_user: hint=messagekind+message cmd=['net','send',user,hint] rst=subprocess.call(cmd) def search_file(filename, search_path): logging.debug("进入文件搜索函数:search_file") dbfilelist=os.listdir(search_path) for dbfile in dbfilelist: p=re.compile(filename) m=p.match(dbfile) if m: if os.path.exists(search_path+m.group()): return m.group() else: continue return None def CopyFileFromSmbToLocal(host,local,format): logging.debug("进入文件拷贝函数:CopyFileFromSmbToLocal") i=date.today().weekday() tmpdate=date.today()-datetime.timedelta(days=i+1) while tmpdate<=date.today(): filename=tmpdate.strftime(format) filefullname=search_file(filename,host) if filefullname: localfile=local+filefullname if os.path.exists(localfile): tmpdate=tmpdate+datetime.timedelta(days=1) continue else: hostfile=host+filefullname shutil.copy(hostfile,localfile) else: logging.info('数据库压缩文件:'+filefullname+'不存在') NotifyUser(2,'数据库压缩文件:'+filefullname+'不存在') return None tmpdate=tmpdate+datetime.timedelta(days=1) logging.info('拷贝文件成功') return 1 def pickfile(filename): logging.debug("进入文件提取函数:pickfile") destfile='*infoservice_database.*' cmd=['winrar','e',filename,destfile,'-r','e',global_localtmpdir] rst=subprocess.call(cmd) if rst==0: return 1 else: return 0 def Decompress(local,format): logging.debug("进入解压函数:Decompress") i=date.today().weekday() tmpdate=date.today()-datetime.timedelta(days=i+1) i=tmpdate.weekday() while tmpdate<=date.today(): localdbfile='infoservice_database.'+str(i+1) filename=tmpdate.strftime(format) filefullname=search_file(filename,local) if os.path.exists(local+localdbfile): tmpdate=tmpdate+datetime.timedelta(days=1) i=tmpdate.weekday() continue else: source=local+filefullname pickfile(source) tmpdate=tmpdate+datetime.timedelta(days=1) i=tmpdate.weekday() logging.info('解压文件成功') return 1 def RemoveOldFile(local): logging.debug("进入删除旧文件函数:RemoveOldFile") i=date.today().weekday() if i==6 or i==0: logging.info('del '+local+'infoservice_database.*') logging.info('del '+local+'*.bz2') os.system('del '+local+'infoservice_database.*') os.system('del '+local+'*.bz2') return 1 def ExecSQL(command): logging.debug("进入SQL语句执行函数:ExecSQL") logging.info("执行的SQL语句:"+command) cmd=['isql','/U',global_sqlserver_user,'/P',global_sqlserver_password,'/S',global_sqlserver_source,'/d','master','/Q',command] rst=subprocess.call(cmd) if rst==0: return 1 else: return 0 def DisConnectDB(): logging.debug("进入断开数据库连接函数:DisConnectDB") command='Exec DisconnectDB "'+global_sqlserver_db+'","数据库还原","'+global_disconnectdb_delay+'"' print command rst=ExecSQL(command) return rst def doRestoreDB(IsInHost): logging.debug("进入还原主函数:doRestoreDB") RemoveOldFile(global_localtmpdir) CopyFileFromSmbToLocal(global_smb_db_filepath,global_localtmpdir,'backup-%Y%m%d\d{6}\.tar\.bz2') Decompress(global_localtmpdir,'backup-%Y%m%d\d{6}\.tar\.bz2') if not IsInHost: hostLocation='\\\\'+global_sqlserver_source+'\\' hostLocation=hostLocation+global_localtmpdir.replace(':','$') os.system('del '+hostLocation+'infoservice_database.*') os.system('copy '+global_localtmpdir+'infoservice_database.* '+hostLocation) result=DisConnectDB() if result==0: NotifyUser(3,'还原库失败,原因:断开连接失败') return -3 i=date.today().weekday() tmpdate=date.today()-datetime.timedelta(days=i+1) j=tmpdate.weekday() while tmpdate<=date.today(): localdbfile='infoservice_database.'+str(j+1) filefullname=global_localtmpdir+localdbfile if os.path.exists(filefullname): if j+1==7: cmd='restore database '+global_sqlserver_db+' from Disk="'+filefullname+'" with file=1, NORECOVERY' if tmpdate==date.today(): cmd='restore database '+global_sqlserver_db+' from Disk="'+filefullname+'" with RECOVERY' else: cmd='restore database '+global_sqlserver_db+' from Disk="'+filefullname+'" with file=1,NORECOVERY' if tmpdate==date.today(): cmd='restore database '+global_sqlserver_db+' from Disk="'+filefullname+'" with file=1,RECOVERY' rst=ExecSQL(cmd) if rst==0: NotifyUser(3,'还原库失败,原因:执行'+cmd+'失败') return -1 else: NotifyUser(3,'还原库失败,原因:文件'+filefullname+'不存在') return -2 tmpdate=tmpdate+datetime.timedelta(days=1) j=tmpdate.weekday() NotifyUser(1,'还原库'+global_sqlserver_db+'成功') logging.info('还原库'+global_sqlserver_db+'成功') return 1 if __name__ == "__main__": doRestoreDB(3<2) logging.shutdown() 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |