1

Is it possible to use TFDFBNBackup and TFDFBNRestore for creating and restoring backups from/to a remote server from local files?

I know that this can be done with the local service manager command line tool like gbak also allows this, but I do not want to use these tools in my new Firemonkey application (Windows, OSX, Linux). I want to compile the functionality completely into my application and I only will have access to the server on a Firebird connection basis, no file share.

13
  • 1
    Are you aware TFDFBNBackup is nbackup, which is totally different than gbak? In any case the Embarcadero documentation suggests this is not possible. Firebird itself does support remote nbackup. Commented Dec 9, 2018 at 14:15
  • Yes, I am aware of it. Usually ser service behind gbak also only writes files local to the server but somehow gbak on the client accomplishes it. I also would go with the simpler FBIBBAckup if there was a way to do it without calling the command line utilities. Commented Dec 9, 2018 at 14:17
  • Sorry, I don't know Delphi. I know that Firebird itself supports this, I have no clue if there are Delphi components that support this. Commented Dec 9, 2018 at 14:21
  • Thanks. I also thougth about creating a service on the remote machine that regularily checks for presence of a backup file, compresses it and creates a secondary database witjh a blob field containing the backup. Sounds weird but is pehaps doable. Commented Dec 9, 2018 at 14:23
  • gbak on the client can work by two methods: original method is just issuing standard SQL commands to the server, receiving standard query resultsets on client, and saving them to FBK file. New method introduced in some later subversions of FB 2.5 is allowing gbak service running on server and FBK file streaming into client by Services API - this new feature was announced in FB 2.5.x relnotes. However for nbackup it is different: 1) nbackup does not work on SQL data level, it does not know about SQL, it mirrors pages - blocks of FDB file. It works low-level. 2) there was no news about Commented Dec 10, 2018 at 8:55

1 Answer 1

2

Thanks to Arioch's suggestion I could solve it and it works well. I used gbak service as it compresses the backup file. Should work with the nbackup flavour as well.

Below please find some example code without any error handling as proof of concept. As Backup only makes sense if it is absolutely reliable a sophisticated error detection and handling is neccessary when implementing this concept for production purposes.

Also, one has to modify firebird.conf on the server to allow external file access in the folder where the database(s) reside. I created backups of some databases in Windows and a binary compare of the files transferred to the local machine.

In the example I feed a label and a progress bar. The backup component should be set to verbose to display the progress although this slows down the backup on the server I prefer being able to give feedback to the user.

procedure TForm1.Button1Click(Sender: TObject);
var
  count: int64;
  fs: TFileStream;
  x: integer;

  procedure dropBackupTable;
  begin
    with FDQuery do
    begin
      sql.text := 'execute block as ' + 'begin ' +
        'if (exists(select 1 from rdb$relations where rdb$relation_name=''BACKUP'')) then ' +
        'execute statement ''drop table backup'';' + 'end';
      execute;
    end;
  end;

begin

  lbl.text := 'Online backup on server...';
  dropBackupTable;
  pb.Value := 2;
  pb.Max := 2000;
  with FDIbBackup do
  begin
    host := '192.168.2.14';
    database := 'r:\databases\office.fdb';
    port := 1216;
    UserName := 'SYSDBA';
    Password := '???????';
    BackupFiles.Clear;
    BackupFiles.add('r:\databases\back.fbk');
    Backup;
  end;

  lbl.text := 'Copying backup file...';

  with FDQuery do
  begin
    sql.text := 'create table backup external ''r:\databases\back.fbk'' (x integer)';
    execute;
    sql.text := 'select count(*) from backup';
    open;
    count := fields[0].AsInteger;
    close;
    pb.Max := count div 1024;
    pb.Value := 0;
    sql.text := 'select * from backup';
    open;
    fs := TFileStream.create('d:\temp\local.fbk', fmCreate, (fmShareDenyRead or fmShareDenyNone));
    count := 0;
    while not eof do
    begin
      inc(count);
      x := fields[0].AsInteger;
      fs.write(x, sizeOf(x));
      if count > 1023 then
      begin
        pb.Value := pb.Value + 1;
        application.processmessages;
        count := 0;
      end;
      next;
    end;
    close;
    fs.free;
    pb.Value := 0;
  end;

  dropBackupTable;

  lbl.text := 'Ready.';
end;

procedure TForm1.FBBackProgress(ASender: TFDPhysDriverService; const AMessage: string);
begin
  if pb.Value = pb.Max then
    pb.Value := 2
  else
    pb.Value := pb.Value + 1;
  application.processmessages;
end;
Sign up to request clarification or add additional context in comments.

19 Comments

Now, this is over-engineering :-) gbak (apart of nBackup) can pass you backup data over the network natively via services API. See the Firebird's file I mentioned to Mark. No need for ET workarounds with gbak - you can just use backup service in store data remotely fashion as it is
Also, "As Backup only makes sense if it is absolutely reliable" - there is a specifics for IB/FB thing "unrestorable backup", because flexibility of them allows to change data structures and constraints on the go, potentially producing logically prohibited states. So it is a good practice exactly for gbak to immediately restore the data (though it is along process) - just to check the FBK is usable in practice if need be. Or even to replace the working database file with the newly created one.
` The backup component should be set to verbose to display the progress although this slows down the backup on the server` are you sure? I believe it slows things down on the client due to TMemo (actually, underlying WinGDI object) low performance in many small additions workload. If you cache log into TList<string> and only dump it to memo once every 1/3 seconds and after work over - then it should be still fast I think
Thankls for the comments. The Delphi component seems not to support the remote thing. But I will do some additional research.
For reliability: I package my app with a specific firebird version so I am sure that the backups created with gbak are compatible. Usually I indeed had the backup make a restore to a database copy and so validate the backup file.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.