Extrahieren spezifischer Tabellen aus riesigen SQL-Dumps mit PHP
Mussten Sie schon einmal nur eine einzige Datenbank oder eine bestimmte Tabelle aus einem mehrere Gigabyte großen (z. B. 5 GB) MySQL-Dump wiederherstellen? Das Öffnen einer Datei dieser Größe in Standard-Texteditoren wie VS Code oder Notepad++ führt meistens zu extremen Verzögerungen oder sogar zum Absturz des Programms.
Anstatt sich mit Desktop-Software oder komplexen Kommandozeilen-Tools wie awk oder sed herumzuschlagen, können wir ein einfaches, speichereffizientes PHP-Skript verwenden, um genau den Teil zu extrahieren, den wir benötigen.
Die Lösung: Stream-Verarbeitung
Der Trick bei der Verarbeitung riesiger Dateien in PHP besteht darin, nicht die gesamte Datei auf einmal in den Arbeitsspeicher zu laden (was Funktionen wie file_get_contents() tun). Durch die Verwendung der PHP-Funktion fgets() können wir die Datei streamen und Zeile für Zeile verarbeiten.
Das untenstehende Skript sucht nach den Standard-mysqldump-Kommentaren, die den Beginn unserer Zieldatenbank oder -tabelle anzeigen (z. B. -- Current Database: db). Wenn es unser Ziel findet, aktiviert es ein Flag, um diese Zeilen in eine neue Datei zu schreiben. Sobald es auf den Anfang einer anderen Datenbank oder Tabelle stößt, wird das Flag wieder deaktiviert.
Hier ist das vollständige Skript:
PHP
<?php
ini_set('memory_limit', '2G');
$inputFile = 'dump_5GB.sql';
$outputFile = 'db_fragment.sql';
$targetName = 'db';
$in = fopen($inputFile, 'r');
$out = fopen($outputFile, 'w');
$isExtracting = false;
while (($line = fgets($in)) !== false) {
if (strpos($line, '-- Current Database: `' . $targetName . '`') === 0 ||
strpos($line, 'USE `' . $targetName . '`;') === 0) {
$isExtracting = true;
} elseif (strpos($line, '-- Current Database: `') === 0 ||
strpos($line, 'USE `') === 0) {
$isExtracting = false;
}
if (!$isExtracting) {
if (strpos($line, '-- Table structure for table `' . $targetName . '`') === 0 ||
strpos($line, '-- Table structure for table `' . $targetName . '_') === 0) {
$isExtracting = true;
} elseif (strpos($line, '-- Table structure for table `') === 0) {
$isExtracting = false;
}
}
if ($isExtracting) {
fwrite($out, $line);
}
}
fclose($in);
fclose($out);
Diese Methode hält den Speicherverbrauch extrem niedrig – deutlich unter ein paar Megabyte – und verarbeitet Gigabytes an SQL-Daten in nur wenigen Sekunden.