Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Datenbank duplizieren (https://www.delphipraxis.net/204743-datenbank-duplizieren.html)

erich.wanker 24. Jun 2020 11:03

Datenbank: mysql • Version: 32bit • Zugriff über: ZeosLib

Datenbank duplizieren
 
Hallo,

Ziel:
ich würde gerne ein mysql-Datenbank vom lokalen rechner (mysql InnoDB) auf einen Cluster kopieren (via Delphi Code)

Dazu habe ich 2 ZeosLib-ZConnections erstellt ( ZConnection1 = localhost / ZConnection2 = remote mySQL Cluster)

Plan:
1.) Zuerst mit ZConnection2.ExecuteDirect("CREATE DATABASE IF NOT EXISTS ..") ein Datenbank erstellen

2.) Dann via Befehl "CREATE TABLE newtable LIKE oldtable" die Tabellen erstellen

3.) Dann via "INSERT newtable SELECT * FROM oldtable" die neuen Tabellen füllen

Problem:

Wie soll ich bitte dem SQL beibringen, dass es 2 verschiedene ZConnections verwenden soll:

"CREATE TABLE ZConnection2.newtable LIKE ZConnection1.oldtable"

und wie führe ich das SQL aus?



Geht das überhaupt??

Danke für Infos
Erich

Delphi XE4
ZeosLib 7
MySQL

stifflersmom 24. Jun 2020 11:23

AW: Datenbank duplizieren
 
Ist das eine wiederkehrende Aufgabe, für die sich so ein Projekt überhaupt lohnt?
Oder andersrum gefragt: Warum nicht einmalig auf dem Alt-Server ein mysqldump erstellen und das dann in die neue Datenbank auf dem Clusterserver per Mysql einelsen?

erich.wanker 24. Jun 2020 11:59

AW: Datenbank duplizieren
 
Nur eine Spielerei :-)

Ich bin über den SQL Befehlt "INSERT newtable SELECT * FROM oldtable" gestolpert .. wollte schnell was ausprobieren - und siehe da: Mir fehlt die Logik wie das mit zwei ZConnections überhaupt funktionieren soll/kann?

Jumpy 24. Jun 2020 12:13

AW: Datenbank duplizieren
 
Zitat:

Zitat von erich.wanker (Beitrag 1468163)
Nur eine Spielerei :-)

Ich bin über den SQL Befehlt "INSERT newtable SELECT * FROM oldtable" gestolpert .. wollte schnell was ausprobieren - und siehe da: Mir fehlt die Logik wie das mit zwei ZConnections überhaupt funktionieren soll/kann?

Kann es so erstmal nicht. Du kannst die Daten in deine Anwendung holen mit Connection 1 und in die andere Datenbank schreiben mit Connection 2 aber das geht nicht mal eben mit 2 SQL-Befehlen. Das ginge nur, wenn die Datenbanken miteinander verbunden wären. In Oracle geht das z.B. über Database-Links. Aber dann brauchst du auch nur eine Connection zu einer Datenbank wo du dann durch den Link auf die Zweite durchgreifst. Aber ich weiß nicht, ob das in MYSQL geht und ob das in deinen Szenario: Entwichlungsrechner -> Produktiv-Server überhaupt Sinn macht.

stifflersmom 24. Jun 2020 12:20

AW: Datenbank duplizieren
 
Auf Shellebene ginge das über eine Pipe

Code:
mysqldump datenbank -ubenutzer -ppasswort|mysql -hAdresse -ubenutzer -ppasswort datenbank
Wobei die datenbank auf dem Neuserver schon bestehen muss!

Ghostwalker 24. Jun 2020 12:42

AW: Datenbank duplizieren
 
Mit MySQL geht das so in der Art und Weise nicht, soweit ich weiß.

Wie Jumpy schon sagte, kannst du über die eine Connection lesen und auf die andere Connection speichern, das sollte gehen.
Oder, wenn es eh die komplette Datenbank ist, einfach die Dateien kopieren. :)

himitsu 24. Jun 2020 16:33

AW: Datenbank duplizieren
 
Nja, der "normale" Weg, den Viele gehen:
Zwei Connections, zwei DataSets, in dem Einen das SELECT, mit WHILE to EOF drüberlaufen und dann drüben manuell die INSERTs/UPDATEs... ausführen.


Praktisch ist es, wenn man via SQL eine Verbindung zur anderen Datenbank aufbauen kann.

PS: Postgres kann man ohne Installation lokal starten, darin lassen sich Verbindungen zu MySQL aufbauen.
Das geht sogar als FOREIGN TABLE, also eine Tabelle im PostgreSQL, die intern nach MySQL weiterleitet.
Und dann kann man im Postgres einfach
SQL-Code:
INSERT INTO a SELECT * FROM b
ausführen.
https://www.postgresql.org/docs/curr...eigntable.html
https://www.postgresql.org/docs/curr...tawrapper.html
oder (das ALTE)
https://www.postgresql.org/docs/10/dblink.html




oder
FireDAC > LocalSQL

Da kann man im SQL auf lokale Komponenten zugreifen. Ich glaub auch auf andere DataSets, welche z.B. jeweils mit den MySQL-Datenbanken verbunden sind.

Ghostwalker 24. Jun 2020 17:06

AW: Datenbank duplizieren
 
Zitat:

Zitat von himitsu (Beitrag 1468178)
Nja, der "normale" Weg, den Viele gehen:
Zwei Connections, zwei DataSets, in dem Einen das SELECT, mit WHILE to EOF drüberlaufen und dann drüben manuell die INSERTs/UPDATEs... ausführen.


Praktisch ist es, wenn man via SQL eine Verbindung zur anderen Datenbank aufbauen kann.

Ja..was MySQL (soweit ich das weiß) aber von Haus aus nicht kann :)

Zitat:

Zitat von himitsu (Beitrag 1468178)
PS: Postgres kann man ohne Installation lokal starten, darin lassen sich Verbindungen zu MySQL aufbauen.
Das geht sogar als FOREIGN TABLE, also eine Tabelle im PostgreSQL, die intern nach MySQL weiterleitet.
Und dann kann man im Postgres einfach
SQL-Code:
INSERT INTO a SELECT * FROM b
ausführen.
https://www.postgresql.org/docs/curr...eigntable.html
https://www.postgresql.org/docs/curr...tawrapper.html
oder (das ALTE)
https://www.postgresql.org/docs/10/dblink.html

Joa...kannst dir auch die Oracle Version Installieren und das darüber machen. :roll:



Zitat:

Zitat von himitsu (Beitrag 1468178)
oder
FireDAC > LocalSQL

Da kann man im SQL auf lokale Komponenten zugreifen. Ich glaub auch auf andere DataSets, welche z.B. jeweils mit den MySQL-Datenbanken verbunden sind.

Das würde aber nix daran ändern, das du 2 Connections brauchst. :)
Ob eine andere DB diese Verbindungen hat oder die App selbst dürfte dabei relativ egal sein :)

Mit LocalSQL (wenn das so funktioniert, bin da kein Spezialist) hätte man natürlich den Vorteil, das man innerhalb von SQL das ganze handhaben kann.

Hobbycoder 24. Jun 2020 18:30

AW: Datenbank duplizieren
 
Über einen Dump - Restore wie hier dargestellt.

Dump:
Delphi-Quellcode:
procedure TMain.BackupClick(Sender: TObject);
const
   READ_BYTES = 2048;

var
  command: TProcess;
  s: string;
  output: TStringList;
  BytesRead, n: LongInt;
  m: TMemoryStream;

begin
  if not (ZConnection1.User = 'root') then begin
    ShowMessage('Only root could access.');
    Exit
  end;
  SaveDialog1.Free;
  SaveDialog1 := TSaveDialog.Create(Self);
  SaveDialog1.InitialDir:= GetUserDir + 'My Documents\';
  SaveDialog1.Filter:='Backup Files|*.bfl';
  if SaveDialog1.Execute then begin
    s := SaveDialog1.FileName;
    if not (copy(s,Length(s)-3,Length(s)-1) = '.bfl') then
      s := s + '.bfl';
    command := TProcess.Create(Nil);
    output := TStringList.Create;
    M := TMemoryStream.Create;
    BytesRead := 0;
    command.CommandLine := 'c:\mysqldump -u root -p'+ZConnection1.Password+' -h '+ZConnection1.HostName+' database';
    command.Options := command.Options + [poUsePipes];
    command.Execute;
    while command.Running do begin
      // ensure the space
      M.SetSize(BytesRead + READ_BYTES);
      // we try to read
      n := command.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
      if n > 0 then
        Inc(BytesRead, n)
      else
        // whitout data, wait 100 ms
        Sleep(100);
    end;
    // we read the last part
    repeat
      // ensure the space
      M.SetSize(BytesRead + READ_BYTES);
      // we try to read
      n := command.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
      if n > 0 then
       Inc(BytesRead, n);
    until n <= 0;
    M.SetSize(BytesRead);
    output.LoadFromStream(M);
    output.SaveToFile(s);
    output.Free;
    command.Free;
    M.Free;
    ShowMessage('Backup ready.')
  end else
    ShowMessage('Backup canceled.');
end;
Restore:
Delphi-Quellcode:
procedure TFMain.restoreClick(Sender: TObject);
var
  s: string;
  tfFile: TextFile;
begin
  if not (ZConnection1.User = 'root') then begin
    ShowMessage('Only root could access.');
    Exit
  end;
  OpenDialog1.Free;
  OpenDialog1 := tOpenDialog.Create(Self);
  OpenDialog1.InitialDir:=GetUserDir+'My Documents\';
  OpenDialog1.Filter:='Backup Files|*.bfl';
  if OpenDialog1.Execute then begin
    AssignFile(tfFile, OpenDialog1.FileName);
    if not FileExists(OpenDialog1.FileName) then
      exit;
    reset(tfFile);
    ZQuery1.SQL.Clear;
    readln(tfFile,s);
    While not eof(tfFile) do begin
      Readln(tfFile,s);
      if length(s) > 0 then begin
        s := StringReplace(s, #10, '', [rfReplaceAll]);
        s := StringReplace(s, #13, '', [rfReplaceAll]);
        s := StringReplace(s, #9, ' ', [rfReplaceAll]);
        if not ((s[1]+s[2]) = '--') then begin
          ZQuery1.SQL.Add(s);
          if s[length(s)] = ';' then begin
            ZQuery1.ExecSQL;
            ZQuery1.SQL.Clear
          end
        end
      end
    end;
    CloseFile(tfFile);
    ShowMessage('Restauration done.');
  end else
    ShowMessage('Restauration canceled.');
end;
Hab's nicht getestet. Aber mit ein paar kleinen Anpassungen könnte man den Umweg über eine Datei eliminieren.

jobo 24. Jun 2020 21:54

AW: Datenbank duplizieren
 
Bin mir nicht sicher, aber ich mein mysql kann untereinander auf mehrere DB zugreifen, sie müssen nur "erreichbar" sein.
Erreichbar bedeutet in dem Fall, auf dem gleichen Server. (So ungefähr)
Unter den Voraussetzungen würde dann die Idee von Erich Wanker funktioneren.

DB Tools, Backup+Restore wären aber ein nicht unüblicher Weg, eine Kopie anzulegen.

P.S.: Das müsste es sein
https://stackoverflow.com/questions/...rent-databases


Alle Zeitangaben in WEZ +2. Es ist jetzt 04:32 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf