IT-Academy Logo
Sign Up Login Help
Home - Programmieren - PHP - MySQL-Datenbank sichern



MySQL-Datenbank sichern

In diesem Artikel erfahren Sie, wie Sie die Struktur und den Inhalt Ihrer MySQL-Datenbanken sichern und somit auf einfachste Weise wiederherstellen können.


Autor: ()
Datum: 07-11-2004, 20:45:29
Referenzen: keine
Schwierigkeit: Profis
Ansichten: 27579x
Rating: 9 (2x bewertet)

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Einleitung

Aufgrund der Komplexibilität des Themas werde ich den Artikel in zwei Parts aufteilen. Zum einen die Theorie und zum anderen die Praxis mit gut kommentiertem Source-Code. Ziel ist es, am Ende eine *.sql Datei zu haben, mit der man den Zustand der Datenbank zum Zeitpunkt des Backups 100%ig wiederherstellen kann.

Theorie

Zuerst sollten wir uns einen Überblick darüber verschaffen, was benötigt wird um eine Datenbank 100%ig wiederherzustellen. Zum einen wäre da ihre Struktur (Tabellen, Eigenschaften der einzelnen Felder und Extras wie "Primary Key" oder "Unique") und zum anderen die in ihr enthaltenen Daten ("Records" in den Tabellen).

Es ist üblich, dass eine Datenbank mehrere Tabellen besitzt. Diese Tabellen sollten nun in ein Array eingelesen werden. Danach wird die folgende Routine von jeder Tabelle durchlaufen. Es soll ja ein Abbild der gesamten Datenbank entstehen.
Was ist also zuerst zu tun in dieser Routine?
Um einen besseren Überblick zu haben sollte man vielleicht über der Struktur und den Daten jeder Tabelle einen Header in Form eines Kommentars mit dem Namen der Tabelle einfügen.
Um die ersten Informationen zu erhalten benutzen wir den MySQL Befehl "DESCRIBE Tabelle". Tabelle muss hier natürlich durch den entsprechenden Namen ersetzt werden. Als Ergebnis bekommen wir eine tabellarische Auswertung. Für jedes Feld der Tabelle sind folgende Informationen verfügbar:
  • Field (Name des Feldes)
  • Type (Typ des Feldes, z.B. "int(1)")
  • Null (Enthält die Option, ob das Feld "null" sein kann)
  • Key (Schlüssel, z.B. "Primary Key")
  • Default (Default Wert des Feldes)
  • Extras (Extras, z.B. "auto_increment")
Alle diese Informationen sind von Nöten, um die Struktur der Tabelle zu beschreiben - bis auf das "Key"-Feld. Diese Information bekommen wir später auf einem anderen Wege.

Nämlich mit dem Befehl "SHOW keys FROM Tabelle". Als Ergebnis gibt es wieder eine tabellarische Auswertung. Jedoch nicht wieder für jedes Feld sondern für die komplette Tabelle. Diese Auswertung gibt Aufschluss darüber, welche Extras auf welches Feld der Tabellen angewendet wurden.
Zum Abschluss des Datenbank-Abbildes müssen noch die in den Tabellen enthaltenen Daten gesichert werden. Das ist eigentlich recht einfach. Man fragt alle Daten aus der Tabelle mittels "SELECT * FROM Tabelle" ab und packt die Ergebnisse formatiert in die Backup-Datei.

Zum Schluss soll dem User selbst überlassen bleiben, ob er die Backup-Datei lieber herunterladen möchte oder lokal auf dem Server speichert will. Für das Herunterladen müssen die Header modifiziert werden, sodass der Browser die Datei, die mittels "echo" ausgegeben wurde, als eine von jenen betrachtet, die es herunterzuladen gilt. Leider gibt es verschiedene Browser, die nur ihre eigene "Syntax" in Header Befehlen verstehen, so dass man zusätzlich noch einen "Fallback" einbauen sollte. Dieser überprüft zuerst welchen Browser der User benutzt und gibt dann die entsprechenden Header aus.
Hiermit ist der theoretische Teil beendet. Falls einige Schritte nicht vollkommen verstanden wurden, gibt es den kommentierten Source-Code, den vielleicht einige besser verstehen als ihre Muttersprache ;).

Praxis

In der Theorie wurde nur der dynamische Teil des Backups beschrieben. Allerdings muss der User zuerst einmal die Datenbank auswählen und sonstige Entscheidungen treffen. Dafür habe ich ein HTML-Formular vorbereitet. Doch auch dieses kommt ohne Verbindung zur MySQL-Datenbank nicht aus, deshalb muss am Anfang jeder Datei eine Verbindung aufgebaut werden. Der Einfachheit halber kann man die Verbindungsdaten in einer separaten Datei ablegen und diese mittels "include()" einbinden.

Verbindungskennung (config.inc.php):
<?php

$host
= "localhost";
$user = "Hans";
$pass = "root";

$server_id = @mysql_connect($host, $user, $pass);

?>


Das HTML Formular sollte folgende Optionen bieten:
  • Auflistung aller Datenbanken
  • Auswahl einer Datenbank für das Backup
  • Auswahl der Backup-Methode (Struktur, Daten oder beides)
  • Auswahl weiterer Optionen (Delete all, Drop table)
  • Auswahl der Speicher-Methode (Herunterladen oder auf dem Server ablegen)
HTML Formular (form.php):
<?php

// Verbindungskennung hinzuladen
include("config.inc.php");

// Alle Datenbanken auflisten
$result = @mysql_list_dbs($server_id);
$num = @mysql_num_rows($result);

?>
<form action="dbsave.php" method="post">
<input name="export" type="hidden" value="true">
Zu exportierende Datenbank:<br>
<br>
<?php

// Auflistung in ein "radio" Input verpacken
for($i=0; $i<$num; $i++) {

$dbname = @mysql_tablename($result, $i);
echo
"<input name=\"dbname\" type=\"radio\" value=\"" . $dbname . "\">" . $dbname . "<br>";

}

?>
<br>
Weitere Optionen:<br>
<br>
<input name="type" type="radio" value="structur"> Nur Struktur der Datenbank<br>
<input name="type" type="radio" value="data"> Nur in der Datenbank enthaltene Daten<br>
<input name="type" type="radio" value="both" checked> Struktur und Daten sichern<br>
<br>
<input name="droptable" type="checkbox" value="true"> DROP TABLE miteinbeziehen<br>
<input name="deleteall" type="checkbox" value="true"> DELETE ALL miteinbeziehen<br>
<br>
Speichern unter:<br>
<br>
<input name="saveto" type="radio" value="server"> Server (gleiches Verzeichnis wie dieses Script)<br>
<input name="saveto" type="radio" value="download"> Download (Speichern auf Client-Rechner)<br>
<br>
<input name="export" type="submit" value="Exportieren">
</form>


Script zum Erstellen des Backups (dbsave.php):
<?php

// Verbindungskennung hinzuladen
include("config.inc.php");

// Wenn das Formular abgeschickt wurde...
if($_POST["export"] == true) {

// Alle nötigen Variabeln vorhanden?
if(isset($_POST["dbname"]) && !empty($_POST["dbname"]) && isset($_POST["saveto"]) && !empty($_POST["saveto"])) {

// Header der Datei erstellen
$datei = "########################################\n";
$datei .= "#\n";
$datei .= "# Backup vom " . date("d.m.Y H:i:s") . "\n";
$datei .= "#\n";
$datei .= "# Datenbank: " . $_POST["dbname"] . "@" . $host . "\n";
$datei .= "#\n";
$datei .= "########################################\n";
$datei .= "\n\n";

// Alle Tabellen der Datenbank in einem Array speichern
$res = mysql_list_tables($_POST["dbname"]);
$num = mysql_num_rows($res);

for(
$i=0; $i<$num; $i++) {

$tables[] = mysql_tablename($res, $i);

}

// Jede Tabelle einzeln durchlaufen
foreach($tables as $tab) {

if(
$_POST["type"] == "both" || $_POST["type"] == "structure") {

$datei .= "########################################\n";
$datei .= "# Tabelle: " . $tab . "\n";
$datei .= "########################################\n";
$datei .= "\n";

// "DROP TABLE miteinbeziehen" ?!
if($_POST["droptable"] == true) {

$datei .= "DROP TABLE IF EXISTS " . $tab . ";\n\n";

}

// Grundlegende Informationen über die Struktur sammeln
$datei .= "CREATE TABLE " . $tab . " (\n";
$query = "DESCRIBE " . $tab;
$sql = mysql_query($query);
$num = mysql_num_rows($sql);
$end = 0;

while(
$info = mysql_fetch_array($sql)) {

$tab_name = $info["Field"];
$tab_type = $info["Type"];
$tab_null = (empty($info["Null"])) ? " NOT NULL" : " NULL";
$tab_default = (empty($info["Default"])) ? "" : " DEFAULT '" . $info["Default"] . "'";
$tab_extra = (empty($info["Extra"])) ? "" : " " . $info["Extra"];

// Ende? Dann keine Kommas mehr setzen.
$end++;
$tab_komma = ($end<$num) ? ",\n" : "";

// Ergebnisse zu $datei hinzufügen
$datei .= " " . $tab_name . " " . $tab_type . $tab_null . $tab_default . $tab_extra . $tab_komma;

}

unset(
$keyarray);

// Weiter Informationen abfragen
$query = "SHOW KEYS FROM " . $tab;
$sql = mysql_query($query);

while(
$info = mysql_fetch_array($sql)) {

$keyname = $info["Key_name"];
$comment = (isset($info["Comment"])) ? $info["Comment"] : "";
$sub_part = (isset($info["Sub_part"])) ? $info["Sub_part"] : "";

if(
$keyname != "PRIMARY" && $info["Non_unique"] == 0) {

$keyname = "UNIQUE|$keyname";

}

if(
$comment == "FULLTEXT") {

$keyname="FULLTEXT|$keyname";

}

if(!isset(
$keyarray[$keyname])) {

$keyarray[$keyname] = array();

}

$keyarray[$keyname][] = ($sub_part > 1) ? $info["Column_name"] . "(" . $sub_part . ")" : $info["Column_name"];

}

// Informationen verarbeiten und in $datei schreiben
if(is_array($keyarray)) {

foreach(
$keyarray as $keyname => $columns) {

$datei .= ",\n";

if(
$keyname == "PRIMARY") {

$datei .= "PRIMARY KEY (";

}
elseif(
substr($keyname, 0, 6) == "UNIQUE") {

$datei .= "UNIQUE " . substr($keyname, 7) . " (";

}
elseif(
substr($keyname, 0, 8) == "FULLTEXT") {

$datei .= "FULLTEXT " . substr($keyname, 9) . " (";

}
else {

$datei .= "KEY " . $keyname . " (";

}

$datei .= implode($columns, ", ") . ")";

}

}

$datei .= ");\n";
$datei .= "\n";

}

// Backup der Datensätze
if($_POST["type"] != "structure") {

if (
$_POST["deleteall"] == true) {

$datei .= "DELETE FROM " . $tab . ";\n\n";

}

// Alle Daten der Tabelle auslesen
$query = "SELECT * FROM " . $tab;
$sql = mysql_query($query);

while(
$info = mysql_fetch_assoc($sql)) {

unset(
$values);
unset(
$fieldnames);

foreach(
$info as $name => $field) {

$fieldnames = ($fieldnames) ? $fieldnames .= "," . $name : $name;
$values = ($values) ? $values .= ",'" . addslashes($field) . "'" : "'" . addslashes($field) . "'";

}

// Formatierten String zu $datei hinzufügen
$datei .= "INSERT INTO " . $tab . " (" . $fieldnames . ") VALUES (" . $values . ");\n";

}

$datei .= "\n\n";

}

}

// Speicher Optionen
if($_POST["saveto"] == "server") {

if(
$fp = fopen("Backup-" . date("d-m-Y-H-i-s") . ".sql", "w")) {

fwrite($fp, $datei);
fclose($fp);

echo
"Datei erfolgreich gespeichert.";

}
else {

echo
"Datei konnte nicht zum Schreiben geöffnet bzw. angelegt werden.";

}

}
else {

// Content Type festlegen
$content_type = (strstr($_SERVER["HTTP_USER_AGENT"], "Opera") || strstr($_ENV["HTTP_USER_AGENT"], "Opera") || strstr($_ENV["HTTP_USER_AGENT"], "IE") || strstr($_SERVER["HTTP_USER_AGENT"], "IE")) ? "application/octetstream" : "application/octet-stream";
header('Content-Type: ' . $content_type);

// Fallback für verschiedene Browser
if(strstr($_ENV["HTTP_USER_AGENT"], "IE") || strstr($_SERVER["HTTP_USER_AGENT"], "IE")) {

header('Content-Disposition: inline; filename="Backup-' . date("d-m-Y-H-i-s") . '.sql"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');

}
else {

header('Content-Disposition: attachment; filename="Backup-' . date("d-m-Y-H-i-s") . '.sql"');
header('Expires: 0');
header('Pragma: no-cache');

}

// $datei zum Herunterladen an den Browser senden
echo $datei;

}

}
else {

echo
"Keine Datenbank zum Exportieren angegeben oder keine Speichermethode gewählt.";

}

}

?>


Für Fragen, Anregungen oder Kritik in Form von Kommentaren stehe ich gerne bereit.


Macavity
Rookie
Beitrag vom:
08-04-2008, 17:34:20

Statt Export werden im IE Daten angezeigt

Das Ganze funktioniert fast perfect. Lediglich beim Export muss ich die Daten umständlich über "speichern unter" mit dem Bowser sichern, da sie nur im Browserfenster angezeigt, aber nicht gespeichert werden. Wie erreiche ich dass die Daten sofort als .sql Datei exportiert werden (wie in PHPMyAdmin)?
Sorry falls die Frage dämlich ist. Aber ich arbeite mich gerade erst in diese Thematik ein.
Mac

-----------------------------------------------------



Senior Member
Beitrag vom:
02-04-2005, 00:25:25

das muss mir entfallen sein - wird bei nächster gelegenheit nachgereicht ;)

-----------------------------------------------------


NOAH
Rookie
Beitrag vom:
28-03-2005, 16:21:26

Leider keine Sicherung der default-Werte!

Das Script gefällt mir ganz gut, nur leider werden keine default-Werte gesichert so das die Datenbank nach der Rücksicherung nicht mehr wie erwartet arbeitet.

-----------------------------------------------------


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06245
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1150
Comments: 0