开发了一个数据备份服务,希望每天自动执行数据备份。
思路:做了个死循环,判断日期是否大于9999-12-31。
子循环判断每天是否做过备份,做过了就不执行。
里面还有子个循环判断是否到备份时间,如果是则开始备份,否在不备份。
服务开发完了,竟在服务启动的时候判断时间做备份,第二天却并没用自动备份。
如果手动重启服务,又会做备份。会是哪的问题啊?
我把代码用程序断点执行,会一直死循环。我在服务创建时创建了个线程,线程执行备份操作。
按道理讲服务没停止,线程应该一直执行,即第二天也应该自动备份啊。
即使电脑重启,服务是自动启动的,也不应该会造成不备份的情况啊。
求指点!!!
思路:做了个死循环,判断日期是否大于9999-12-31。
子循环判断每天是否做过备份,做过了就不执行。
里面还有子个循环判断是否到备份时间,如果是则开始备份,否在不备份。
服务开发完了,竟在服务启动的时候判断时间做备份,第二天却并没用自动备份。
如果手动重启服务,又会做备份。会是哪的问题啊?
我把代码用程序断点执行,会一直死循环。我在服务创建时创建了个线程,线程执行备份操作。
按道理讲服务没停止,线程应该一直执行,即第二天也应该自动备份啊。
即使电脑重启,服务是自动启动的,也不应该会造成不备份的情况啊。
求指点!!!
MYSQL也可以通过设置自动备份的时间来实现。至于从数据库自动备份出来后,如果想再做个异机备份,那么写个bat批处理,通过XP的任务计划即可很方便的实现。
我就是不想用批处理,应为批处理要在DOS界面里显示数据库密码不安全。
而且一旦有修改发布很麻烦,我有100多台服务器需要自动备份,未来会有超过300台。
所以想设计个服务自动备份,而且程序是调用的存储过程执行备份,如果有变动,
我直接修改下存储过程就下发下可以了。现在的问题就是服务仅在启动的时候执行,
而没有在第二天合适的时间执行,把服务重新启动又可以了,会是哪写错了?
SYBASE管理器没有备份功能,只有备份命令可以使用。
考虑到实际情况,每个服务器的备份路径、时间、方式都可能不同。
我现在备份方式采用数据表管理,方便个性化管理。备份用存储过程执行,
期间从表中读取备份方式,所有没采用批处理。
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
DB, CTMemDataSet, CTDataSet, CTQuery,DateUtils, CTLibDatabase,
CTStoredProc,WinSock,StrUtils;type
Tdbbak = class(TService)
CTLibDatabase1: TCTLibDatabase;
CTQuery1: TCTQuery;
CTStoredProc1: TCTStoredProc;
procedure ServiceStart(Sender: TService; var Started: Boolean);
procedure ServiceStop(Sender: TService; var Stopped: Boolean);
procedure ServicePause(Sender: TService; var Paused: Boolean);
procedure ServiceContinue(Sender: TService; var Continued: Boolean);
private
{ Private declarations }
public
function GetServiceController: TServiceController; override;
{ Public declarations }
end;
NetThread = class(TThread)
protected
procedure Execute; override;
end;
var
dbbak: Tdbbak;implementation
var
NetThread1 : NetThread;{$R *.DFM}procedure ServiceController(CtrlCode: DWord); stdcall;
begin
dbbak.Controller(CtrlCode);
end;function Tdbbak.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;function ComputerName:string;
var
FStr:PChar;
FSize:Cardinal;
begin
FSize:=255;
GetMem(FStr,FSize);
Windows.GetComputerName(FStr,FSize);
Result:=FStr;
FreeMem(FStr);end;
procedure Tdbbak.ServiceStart(Sender: TService; var Started: Boolean);
begin
NetThread1 := NetThread.Create(false);
Started:=True;
end;procedure NetThread.Execute;
var
oldtime,subtime,H,M,i,backupsum,backupsumnow:integer;
closedtime,dobacktime:string;
sr: TSearchRec; //定义 TSearchRec 结构变量
Attr: Integer; //文件属性
s: string; //要搜索的内容
ListName,ListTime: TStringList; //存放搜索结果
FileName: string;
ti: Integer;
dt: TDateTime;
j:integer;
FileTimeMin:Double;
MinL:integer;//最小日期序号
begin
dbbak.CTLibDatabase1.ServerName:= ComputerName;
dbbak.CTLibDatabase1.DbName:='SCS';
dbbak.CTLibDatabase1.UserName:='sa';
dbbak.CTLibDatabase1.Password:='sk30673';
dbbak.CTLibDatabase1.Connected:=false;
dbbak.CTLibDatabase1.Connected:=true;
while (now()-strtodatetime('9999-12-31'))<0 do
begin
//判断今日是否备份
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select BKEndTime from DBBackupLog where BKEndTime = (select max(BKEndTime) from DBBackupLog where BKStatus = '''+'2'+''') ');
dbbak.CTQuery1.Open;
if formatdatetime('yyyy-mm-dd',dbbak.CTQuery1.fieldbyname('BKEndTime').AsDateTime) <> formatdatetime('yyyy-mm-dd',now) then
i:=0
else
i:=1;
dbbak.CTLibDatabase1.Connected:=false; if i=0 then //i=0时今日未备份执行
begin
dbbak.CTLibDatabase1.Connected:=false;
dbbak.CTLibDatabase1.Connected:=true;
//取出历时最长备份时间
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select RegValue from Registry_SKYL where RegName = '''+'BackupMAXTime'+''' ');
dbbak.CTQuery1.Open;
oldtime:=strtoint(dbbak.CTQuery1.fieldbyname('RegValue').AsString);
//取出备份时间提前量
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select RegValue from Registry_SKYL where RegName = '''+'BackupAdvanceTime'+''' ');
dbbak.CTQuery1.Open;
subtime:=strtoint(dbbak.CTQuery1.fieldbyname('RegValue').AsString);
//取得关店时间
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select RegValue from Registry_SKYL where RegName = '''+'StoreClosedTime'+''' ');
dbbak.CTQuery1.Open;
closedtime:=trim(dbbak.CTQuery1.fieldbyname('RegValue').AsString);
//算出备份时间点 。关店时间-历时最长备份时间-备份时间提前量
dbbak.CTLibDatabase1.Connected:=false;
H:=(strtoint(LeftStr(closedtime,2))*60+strtoint(copy(closedtime,4,2))-oldtime-subtime) div 60; //算出备份小时
M:=(strtoint(LeftStr(closedtime,2))*60+strtoint(copy(closedtime,4,2))-oldtime-subtime) mod 60; //算出备份分钟
dobacktime:=datetimetostr(dateof(now()))+' '+inttostr(h)+':'+inttostr(m)+':'+'00'; //查询现有备份数量
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select RegValue from Registry_SKYL where RegName = '''+'BackupSumNow'+''' ');
dbbak.CTQuery1.Open;
backupsumnow:=strtoint(trim(dbbak.CTQuery1.fieldbyname('RegValue').AsString)); //查询最大备份数量
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select RegValue from Registry_SKYL where RegName = '''+'BackupSum'+''' ');
dbbak.CTQuery1.Open;
backupsum:=strtoint(trim(dbbak.CTQuery1.fieldbyname('RegValue').AsString)); dbbak.CTLibDatabase1.Connected:=false; //当系统时间到开始执行备份
while (now()-strtodatetime(dobacktime))>0 do
begin
dbbak.CTLibDatabase1.Connected:=false;
dbbak.CTLibDatabase1.Connected:=true;
dbbak.CTStoredProc1.ExecProc;
dbbak.CTLibDatabase1.Connected:=false;
if backupsumnow = backupsum then //当现有备份数量等于最大备份数量
begin
//查询备份路径
dbbak.CTLibDatabase1.Connected:=false;
dbbak.CTLibDatabase1.Connected:=true;
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('select RegValue from Registry_SKYL where RegName = '''+'BackupPath'+''' ');
dbbak.CTQuery1.Open;
s:=trim(dbbak.CTQuery1.fieldbyname('RegValue').AsString)+'SCS*.dmp'; Attr := faAnyFile; //文件属性值faAnyFile表示是所有文件
ListName := TStringList.Create; //文件名称List建立
ListTime := TStringList.Create; //文件修改时间 List建立
if FindFirst(s,Attr,sr)=0 then //开始搜索,并给 sr 赋予信息, 返回0表示找到第一个
begin
repeat //如果有第一个就继续找 FileName:=trim(dbbak.CTQuery1.fieldbyname('RegValue').AsString)+sr.Name;
ListName.Add(FileName); //用ListName记下结果
ti := FileAge(FileName);
dt := FileDateToDateTime(ti); //转换
ListTime.Add(DateTimeToStr(dt)); //用ListTime记下结果
until(FindNext(sr)<>0); //因为sr已经有了搜索信息, FindNext只要这一个参数, 返回0表示找到
end;
FindClose(sr); //需要结束搜索, 搜索是内含句柄的
FileTimeMin:=strtodatetime('9999-12-31');
MinL:=0;
for j:=0 to (ListTime.Count-1) do
begin
if (strtodatetime(ListTime.Strings[j])-FileTimeMin)<0 then
begin
FileTimeMin:=strtodatetime(ListTime.Strings[j]);
MinL:=j;
end;
end;
//删除最旧备份SCS
if FileExists(ListName.Strings[MinL]) then
DeleteFile(ListName.Strings[MinL]);
//删除最旧备份master
if FileExists(StringReplace(ListName.Strings[MinL],'SCS','master',[rfReplaceAll])) then //替换文件名SCS为master
DeleteFile(StringReplace(ListName.Strings[MinL],'SCS','master',[rfReplaceAll]));
//释放内存
ListTime.Free;
ListName.Free;
break;
end
else
begin
// 更新现有备份数量统计
backupsumnow:=backupsumnow+1;
dbbak.CTQuery1.Close;
dbbak.CTQuery1.ClearSQL;
dbbak.CTQuery1.SQL.Add('update Registry_SKYL set RegValue = '''+inttostr(backupsumnow)+''' where RegName = '''+'BackupSumNow'+''' ');
dbbak.CTQuery1.ExecSQL;
break;
end;
end;
end;
end;
end;procedure Tdbbak.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
NetThread1.Terminate;
Stopped:=True;
end;procedure Tdbbak.ServicePause(Sender: TService; var Paused: Boolean);
begin
NetThread1.Suspend;
Paused:=True;
end;procedure Tdbbak.ServiceContinue(Sender: TService; var Continued: Boolean);
begin
NetThread1.Resume;
Continued := True;
end;end.
procedure Tdbbak.ServiceExecute(Sender:TService);
begin
while not Terminated do begin
Sleep(10);
ServiceThread.ProcessRequests(false);
end;
end;
一般是这样:
while True do
begin
if 当前时间=定义的时间 then
执行备份
end;建议楼主先做个测试:
例:通过服务在指定的时间去复制某个目录下的文件,成功后,再加入数据库中的内容。
只是你上面的代码如果运行不是一直sleep一直不响应???
因为我没有关闭服务啊
while (now()-strtodatetime('9999-12-31'))<0 do
......
while (now()-strtodatetime(dobacktime))>0 do
......你可以在这两个循环中做个调试,输出到Tmemo或 日志中去,看看是不是某个控制没有考虑周到
例如dobacktime是否每次都能正确地取到
测试代码如下:
procedure TService1.ServiceExecute(Sender: TService);
begin
while not Terminated do
begin
if strtoint(rightstr(floattostr(now),5)) mod 2 = 0 then
begin
CTLibDatabase1.Connected:=false;
CTLibDatabase1.Connected:=true;
CTQuery1.Close;
CTQuery1.ClearSQL;
CTQuery1.AddSQL('insert into test2011 (demo) values ('''+'1'+''') ');
CTQuery1.ExecSQL;
end;
ServiceThread.ProcessRequests(false);
end;
end;服务大概运行了4分钟自动停止了,这是什么原因造成的?我需要服务一直运行啊~!!!
逐步调试,看看问题出在哪一个环节。上面两个循环,分别输出调试内容,看在哪个循环中出现了中断服务的情况。直接输出到Tmemo中,不用数据库,比较直观和 容易一些。
CTLibDatabase1.Connected:=false;
CTLibDatabase1.Connected:=true;
也不可能是出现异常的原因之一。再说,即使用了数据库,也只是在满足条件时,才去连接数据库,用完了断开,而不是在循环中一直去尝试连接。毕竟一天中,只有一个时间是满足你去执行备份的,其他时间都不要去与数据库打交道。
不连数据库没问题,连数据库的话在执行一段时间后会报下面的错误Service failed on execute: CTLibDatabase1: Message : 84083972
Severity : 5
ct_connect(): network packet layer: internal net library error: Net-Lib protocol driver call to connect two endpoints failed
Failed to connect to the server - Error is 0 操作成功完成。数据库连接失败。之前成功写入3984次后面就不行了,数据库连接不稳定???