andreas: Dump-Schema von MySQL DB wie in phpMyAdmin

Hallo!
Ich würde gerne meine Datenbank täglich selber sichern, und wenn möglich per Mail an einen anderen Server senden.
Ich dachte mir Ich schreibe genau so eine Dump-Schema, so wie phpMyAdmin es erzeugen kann - "Struktur und Daten" - in eine Datei wie 'Sicherung_DB12345_20020220.txt'.
Dann würde ich jede Nacht einen Cronjob laufen lassen, der dieses Script ausführt, evtl auch automatisch alle Dateien älter als eine Woche löscht und mir die Datei zusätzlich noch als attachment per Mail zusendet. Im Prinzip weiß ich _dass_ das geht, nur weiß ich nicht genau wie ich dieses Schema genau so schön wie phpMyAdmin in die .txt Datei schreiben kann, wohl gemerkt genau so, dass ich mit dieser Datei die kpl DB dieses Tages wiederherstellen könnte.
Die DB ist auch nicht ganz so groß, also kein Problem wegen des Speichers.
1. Frage: Was haltet Ihr davon? Ist das vernünftig oder gibt es bessere Möglichkeiten die DB automatisch und regelmäßig zu sichern?
2. Frage: LOAD DATA INFILE hab ich schon gefunden und mir auch mal die entsprechende phpMyAdmin Datei näher angeschaut, nur ist die aufgrund der Einstellmöglichkeiten recht kompliziert, aber als Grundlage ganz in Ordnung denke ich.

Problem an diesem Script, es soll automatisch, nicht manuell ausgeführt werden. Durch [LOCAL] gebe ich ja einen Speicherplatz auf meinem 'lokalen' PC an, nicht auf dem Server, oder? Und da beginnen die Probleme, kann ich [LOCAL] einfach weglassen und einen direkten Pfad auf dem Server angeben? Z.B. '/www/daten/datei.txt'? Wie sieht das dann aus mit file-privileges, hat das was mit CHERMOD zu tun oder ist das ein MySQL Recht? Wenn letzteres, woher weiß ich ob ich es habe?
Bekomme ich wenn das so funktioniert auch die "Create Table" und "Insert Into" Anweisungen, genau wie in phpmyadmin?

Naja, das wars fürs erste, hab mal das entsprechende phpMyAdmin-Script eingefügt!

Würde mich freuen wenn jemand mir den ein oder anderen Tipp dazu geben könnte!

Grüße
  Andreas

<?php
/* $Id: ldi_check.php,v 1.11 2001/11/23 01:03:20 loic1 Exp $ */

/**
 * This file checks and builds the sql-string for
 * LOAD DATA INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE table_name
 *    [FIELDS
 *        [TERMINATED BY '\t']
 *        [OPTIONALLY] ENCLOSED BY "]
 *        [ESCAPED BY '\' ]]
 *    [LINES TERMINATED BY '\n']
 *    [(column_name,...)]
 */

/**
 * Gets some core scripts
 */
require('./libraries/grab_globals.lib.php');
require('./libraries/common.lib.php');

/**
 * The form used to define the query has been submitted -> do the work
 */
if (isset($btnLDI) && ($textfile != 'none')) {
    if (!isset($replace)) {
        $replace = '';
    }

// Formats the data posted to this script
    $textfile             = PMA_sqlAddslashes($textfile);
    if (get_magic_quotes_gpc()) {
        $field_terminater = stripslashes($field_terminater);
        $enclosed         = PMA_sqlAddslashes(stripslashes($enclosed));
        $escaped          = PMA_sqlAddslashes(stripslashes($escaped));
        $line_terminator  = stripslashes($line_terminator);
        $column_name      = PMA_sqlAddslashes(stripslashes($column_name));
    } else {
        $enclosed         = PMA_sqlAddslashes($enclosed);
        $escaped          = PMA_sqlAddslashes($escaped);
        $column_name      = PMA_sqlAddslashes($column_name);
    }

// Builds the query
    $query     = 'LOAD DATA LOCAL INFILE '' . $textfile . ''';
    if (!empty($replace)) {
        $query .= ' ' . $replace;
    }
    $query     .= ' INTO TABLE ' . PMA_backquote($into_table);
    if (isset($field_terminater)) {
        $query .= ' FIELDS TERMINATED BY '' . $field_terminater . ''';
    }
    if (isset($enclose_option) && strlen($enclose_option) > 0) {
        $query .= ' OPTIONALLY';
    }
    if (strlen($enclosed) > 0) {
        $query .= ' ENCLOSED BY '' . $enclosed . ''';
    }
    if (strlen($escaped) > 0) {
        $query .= ' ESCAPED BY '' . $escaped . ''';
    }
    if (strlen($line_terminator) > 0){
        $query .= ' LINES TERMINATED BY '' . $line_terminator . ''';
    }
    if (strlen($column_name) > 0) {
        if (PMA_MYSQL_INT_VERSION >= 32306) {
            $query .= ' (';
            $tmp   = split(',( ?)', $column_name);
            for ($i = 0; $i < count($tmp); $i++) {
                if ($i > 0) {
                    $query .= ', ';
                }
                $query     .= PMA_backquote(trim($tmp[$i]));
            } // end for
            $query .= ')';
        } else {
            $query .= ' (' . $column_name . ')';
        }
    }

// Executes the query
    // sql.php will stripslash the query if 'magic_quotes_gpc' is set to on
    if (get_magic_quotes_gpc()) {
        $sql_query = addslashes($query);
    } else {
        $sql_query = $query;
    }
    include('./sql.php');
}

/**
 * The form used to define the query hasn't been yet submitted -> loads it
 */
else {
    include('./ldi_table.php');
}
?>

  1. Moin

    man mysqldump

    --
    Henryk Plötz
    Grüße aus Berlin

    1. Hi!
       - nicht LOAD DATA INFILE?????

      Also ich hab mich mal auf die Suche gemacht und hab jetzt mal folgendes probiert(auf win32):

      <?
      system("system("c:\mysql\bin\mysqldump -u root -p  -h 127.0.0.1 TestDB > c:\datei.sql ", $fp);

      if ($fp==0) echo "Daten auf lokalen PC exportiert"; else echo "Es ist ein Fehler aufgetreten";
      ?>

      Ich habe einen User in MySQL mit
      Username: root
      kein Passwort
      Und DB ist auf meinem PC, also 127.0.0.1

      Wegen Windows habe ich das von /user/bin/mysqldump wie oben abgeändert.

      Im Verzeichnis c:\mysql\bin\ befindet sich die Datei: mysqldump.exe

      Abeer ich bekomme einen Parse Error in Zeile 2. Was mache ich falsch?

      Grüße
        Andreas

      1. Huhu Andreas

        system("system("c:\mysql\bin\mysqldump -u root -p  -h 127.0.0.1 TestDB > c:\datei.sql ", $fp);

        Diese Zeile sieht etwas 'gestottert' aus.  system("system("

        Abeer ich bekomme einen Parse Error in Zeile 2. Was mache ich falsch?

        Viele Grüße

        lulu

        1. Hallo!
          Vielen Dank Euch beiden, vor allem Henryk für den Tipp mit mysqldump, hätte bestimmt 100 Zeilen Code geschrieben, jetzt ist alle in einer kleinen Zeile - trotz PHP(auch wenn mir das nicht mehr alles nach PHP aussieht, aber ich sag lieber nichts mehr:)! Vielen Dank dafür!

          Grüße
            Andreas

      2. Moin,

        • nicht LOAD DATA INFILE?????

        Nein, du wolltest doch einen Dump haben genauso wie ihn phpMyAdmin erzeugt.

        system("system("c:\mysql\bin\mysqldump -u root -p  -h 127.0.0.1 TestDB > c:\datei.sql ", $fp);

        a) Zähl mal die Anführungszeichen :)
        b) Wenn der User kein Passwort hat, dann darfst du -p nicht angeben, sonst fragt er dich nach einem Passwort. -p ohne Parameter sorgt für eine Passwortabfrage, -phaha sorgt dafür dass "haha" (ohne Anführungszeichen) als Passwort verwendet wird. Beachte das zwischen -p und das Passwort _kein_ Leerzeichen stehen darf !

        --
        Henryk Plötz
        Grüße aus Berlin

        1. Hi!
          Danke, aber wie folgt kommt der gleiche Fehler(habt Recht, nicht gerade aussagekräftig:)

          <?
          system(system("c:\mysql\bin\mysqldump -uroot -h127.0.0.1 TestDB > c:\datei.sql ", $fp);

          if ($fp==0) echo "Daten auf lokalen PC exportiert"; else echo "Es ist ein Fehler aufgetreten";
          ?>

          Nun? Ich weiß nicht was ich falsch mache, aber was ist daran so anders als an meiner Vorlage, oder ist die auch falsch?:

          http://www.php-mysql.de/faqs/dump/index.php3

          Grüße
            Andreas

          1. Moin,

            <?
            system(system("c:\mysql\bin\mysqldump -uroot -h127.0.0.1 TestDB > c:\datei.sql ", $fp);
            if ($fp==0) echo "Daten auf lokalen PC exportiert"; else echo "Es ist ein Fehler aufgetreten";
            ?>

            Na dann zähl jetzt eben mal Klammern :) ... und "system" solltest du auch mal zählen.
            Hint: system("...."); würde reichen

            PS: Nicht alles gedankenlos aus irgendwelchen FAQs abschreiben. Ein bisschen selfdenken hat noch nie geschadet.

            --
            Henryk Plötz
            Grüße aus Berlin

            1. Hi!
              Nachdem das jetzt so super klappt würde ich noch gerne wissen, ob es die Möglichkeit gibt, die erzeugte Datei direkt zu komprimieren, denn die ist nicht grade klein!
              Wie kann man das da noch einbauen?
              Grüße
                Andreas

              1. Moin

                Nachdem das jetzt so super klappt würde ich noch gerne wissen, ob es die Möglichkeit gibt, die erzeugte Datei direkt zu komprimieren, denn die ist nicht grade klein!
                Wie kann man das da noch einbauen?

                mysqldump schreibt die Daten auf die Standardausgabe raus. gzip bzw. bzip2 (letzteres komprimiert oft ein bisschen besser, braucht dafür aber auch länger) nimmt die zu komprimierenden Daten auf der Standardeingabe entgegen und schreibt das komprimierte Zeugs auf die Standardausgabe. Mit einer Pipe (das ist das |-Dings) kannst du die Standardausgabe eines Programms an die Standardeingabe eines anderen Programmes hängen. Muß ich noch mehr sagen?

                --
                Henryk Plötz
                Grüße aus Berlin

                1. Hi!

                  Muß ich noch mehr sagen?

                  JA, BITTE:-)

                  mysqldump schreibt die Daten auf die Standardausgabe raus.

                  soll das heißen normal ohne Komrimierung, richtig? Da Du Dich damit ja gut auszukennen scheinst, weißt Du bestimmt auch, welchen mime-typ mysqldump erzeugt oder vielleicht kennst Du einen anderen Grund warum sich die frisch erzeugt dump-datei nicht als attachment versenden läßt, siehe http://forum.de.selfhtml.org/?m=28781&t=5121(ich probiere das jetzt ca. 3-4 Stunden!!!)

                  gzip bzw. bzip2 (letzteres komprimiert oft ein bisschen besser, braucht dafür aber auch länger) nimmt die zu komprimierenden Daten auf der Standardeingabe entgegen und schreibt das komprimierte Zeugs auf die Standardausgabe. Mit einer Pipe (das ist das |-Dings) kannst du die Standardausgabe eines Programms an die Standardeingabe eines anderen Programmes hängen. Muß ich noch mehr sagen?

                  Das ist zu hoch für mich, ich bin froh das ich gerade mit ein paar PHP-Funktionen klar komme, ich versuche das zu verstehen, kommt aber nicht so viel bei rum. Wie sähe das denn praktisch aus und wie komme ich dann an den erzeugten Dateinamen als Variable?
                  Bei mir siehts bis jetzt so aus:

                  $dateiname=$db."_".date("Y-m-d").".sql";
                  system ("/usr/bin/mysqldump -u".$user." -p".$pass." -h".$host." ".$db." > /www/daten/sicherung/".$dateiname, $fp);

                  weiter unten verwende ich $dateiname dann für:
                   $attachment = fread(fopen("www/daten/sicherung/".$dateiname, "r"), filesize($dateiname));

                  was aber wie gesagt mit allen Dateien funktioniert, nur nicht mit den erzeugten Dump-Dateien.

                  Zur Komprimierung hatte ich auch mal folgendes probiert:

                  $data = "www/daten/sicherung/".$dateiname;
                  $gzdata = gzencode($data, 9);
                  $fp = fopen("/www/daten/sicherung/".$dateiname.".gz", "w");
                  fwrite($fp, $gzdata);
                  fclose($fp);

                  Aber auch die so erzeugte Datei ist leer.

                  Nur wenn ich die mysqldump erzeugte Datei direkt runterlade kann ich sie mit einem Editor öffnen.

                  Höchst seltsam ist das alles für mich, ich habe keinen blassen Schimmer woran das jetzt noch liegen kann.

                  Naja, vieleicht weißt Du ja noch Rat!

                  Vielen Dank im voraus!

                  Grüße
                    Andreas

                  1. Moin

                    JA, BITTE:-)

                    Ich spar mir an dieser Stelle mal die Einführung in die Ausgabeumleitung bei Shellaufrufen und verweise auf http://aktuell.de.selfhtml.org/artikel/server/linux/index.htm (auch wenn da "Linux" drübersteht ist das meiste wohl auf allen unixoiden Systemen gültig, das hierfür benötigte geht sogar unter Windows)

                    Nur soviel wie momentan unmittelbar nötig ist:
                    echo "bla" gibt   bla   auf der Standardausgabe aus.

                    leitet die Standardausgabe eines Programms in eine Datei um.

                    | leitet die Standardausgabe des Programms vor dem | (Pipe-Symbol) in die Standardeingabe des Programms hinter den | um.
                    echo "bla" | gzip > trallala.gz   gibt also bla aus, gzipt es und schreibt es in eine Datei namens trallala.gz.
                    Preisfrage: Wie sieht der Aufruf aus, wenn du die Standardausgabe von mysqldump gzippen und in eine Datei leiten möchtest? :)

                    soll das heißen normal ohne Komrimierung, richtig? Da Du Dich damit ja gut auszukennen scheinst, weißt Du bestimmt auch, welchen mime-typ mysqldump erzeugt oder vielleicht kennst Du einen anderen Grund warum sich die frisch erzeugt dump-datei nicht als attachment versenden läßt, siehe http://forum.de.selfhtml.org/?m=28781&t=5121(ich probiere das jetzt ca. 3-4 Stunden!!!)

                    Einen Mimetyp erzeugt es gar nicht, der kommt erst ins Spiel wenn du die Datei in einer MIME-formatierten Mail verschicken (oder direkt vom Webserver ausliefern lassen) willst. Da mysqldump aber reinen Text erstellt, wird text/plain schon ok sein. Wenn die Datei gezippt wurde, ist der richtige Typ application/x-gzip.

                    Das ist zu hoch für mich, ich bin froh das ich gerade mit ein paar PHP-Funktionen klar komme, ich versuche das zu verstehen, kommt aber nicht so viel bei rum. Wie sähe das denn praktisch aus und wie komme ich dann an den erzeugten Dateinamen als Variable?

                    Häh? Du leitest die Ausgabe in eine Datei deiner Wahl um, da wird kein Name erzeugt.

                    weiter unten verwende ich $dateiname dann für:
                    $attachment = fread(fopen("www/daten/sicherung/".$dateiname, "r"), filesize($dateiname));

                    ich würde mal schwer tippen dass der Pfad auch zwischen filesize( und $dateiname gehört. Sonst weiss die Funktion doch gar nicht welche Dateigröße sie eigentlich zurückgeben soll.

                    $data = "www/daten/sicherung/".$dateiname;
                    $gzdata = gzencode($data, 9);

                    Das komprimiert den Datei_namen_, ist vielleicht nicht ganz genau dass was du willst :)

                    $fp = fopen("/www/daten/sicherung/".$dateiname.".gz", "w");
                    fwrite($fp, $gzdata);
                    fclose($fp);

                    Hint: Bitte bei jedem Dateisystemaufruf eine Fehlerabfrage machen. Es kann sonst sein dass irgendwo vorher was nicht geklappt hat, der Fehler aber erst viel weiter hinten offensichtlich wird. Nach solchen Fehlern könnte man sich stundenlang tot suchen.

                    --
                    Henryk Plötz
                    Grüße aus Berlin

                    1. Hi!

                      Ich spar mir an dieser Stelle mal die Einführung in die Ausgabeumleitung bei Shellaufrufen und verweise auf http://aktuell.de.selfhtml.org/artikel/server/linux/index.htm (auch wenn da "Linux" drübersteht ist das meiste wohl auf allen unixoiden Systemen gültig, das hierfür benötigte geht sogar unter Windows)

                      Danke für den link, da kenne ich mich noch GAR NICHT aus! Aber irgendwamm fängt mal halt an!

                      Nur soviel wie momentan unmittelbar nötig ist:
                      echo "bla" gibt   bla   auf der Standardausgabe aus.

                      leitet die Standardausgabe eines Programms in eine Datei um.
                      | leitet die Standardausgabe des Programms vor dem | (Pipe-Symbol) in die Standardeingabe des Programms hinter den | um.
                      echo "bla" | gzip > trallala.gz   gibt also bla aus, gzipt es und schreibt es in eine Datei namens trallala.gz.
                      Preisfrage: Wie sieht der Aufruf aus, wenn du die Standardausgabe von mysqldump gzippen und in eine Datei leiten möchtest? :)

                      Klappt wunderbar, reduziert die größe mal eben um 80%! Das lohnt sich!

                      Einen Mimetyp erzeugt es gar nicht, der kommt erst ins Spiel wenn du die Datei in einer MIME-formatierten Mail verschicken (oder direkt vom Webserver ausliefern lassen) willst. Da mysqldump aber reinen Text erstellt, wird text/plain schon ok sein. Wenn die Datei gezippt wurde, ist der richtige Typ application/x-gzip.

                      War auch nur eine Vermutung meinerseits.

                      Häh? Du leitest die Ausgabe in eine Datei deiner Wahl um, da wird kein Name erzeugt.

                      Sorry, ist am Anfang nicht ganz so einfach zu verstehen wenn man nur mei teinfachen PHP-Funktionen zu tun hat und die oft nichtmal versteht!

                      ich würde mal schwer tippen dass der Pfad auch zwischen filesize( und $dateiname gehört. Sonst weiss die Funktion doch gar nicht welche Dateigröße sie eigentlich zurückgeben soll.

                      War richtig getippt, bin kurz bevor ich das gelesen habe selbst drauf gekommen, als ich das alles nochmal von vorne gemacht habe!

                      Das komprimiert den Datei_namen_, ist vielleicht nicht ganz genau dass was du willst :)

                      :))

                      Hint: Bitte bei jedem Dateisystemaufruf eine Fehlerabfrage machen. Es kann sonst sein dass irgendwo vorher was nicht geklappt hat, der Fehler aber erst viel weiter hinten offensichtlich wird. Nach solchen Fehlern könnte man sich stundenlang tot suchen.

                      OK, nur bevor das nicht funktioniert mache ich mir darum keine Sorgen, aber mit dem Totsuchen habe Heute den ganzen Tag betrieben!

                      Dir nochmal vielen Dank für Deine Hilfe, jetzt klappt es super! Leider merke ich immer öfter was mir an Wissen noch alles fehlt, z.B. Fopen habe ich irgendwann mal in Zusammenhang mit einem Counter gefunden, seitdem verwende ich es ohne mir darüber Gedanken zu machen und ohne es zu verstehen. Daher auch das Probkem welches mich alleine grob geschätzt 4 Stunden gekostet hat. Jetzt weiß ich wie es geht!
                      Vielen Dank nochmal hierfür!

                      Grüße
                        Andreas