
Ich habe eine riesige MySQL-Sicherungsdatei (von mysqldump) mit den Tabellen in alphabetischer Reihenfolge. Meine Wiederherstellung ist fehlgeschlagen und ich möchte dort weitermachen, wo ich aufgehört habe, mit der nächsten Tabelle in der Sicherungsdatei. (Ich habe das Problem behoben, dies ist nicht wirklich eine Frage zu MySQL-Wiederherstellungen usw.)
Ich möchte beispielsweise meine Sicherungsdatei nehmen backup.sql
und den Anfang der Datei abschneiden, bis ich diese Zeile sehe:
-- Table structure for `mytable`
Alles weitere landet dann beispielsweise in meiner Ergebnisdatei backup-secondhalf.sql
. Dies wird etwas dadurch erschwert, dass die Datei bzip2-komprimiert ist, aber das sollte kein allzu großes Problem sein.
Ich denke, ich kann es so machen:
$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Table structure for table `mytable`' -m 1
Dadurch erhalte ich den Byte-Offset in der Datei, den ich kürzen möchtebis zu. Dann:
$ bunzip2 -c backup.sql.bz2 | dd skip=[number from above] | bzip2 -c > backup-secondhalf.sql.bz2
Leider muss ich hierfür bunzip2 zweimal auf der Datei ausführen und alle Bytes zweimal durchlesen.
Gibt es eine Möglichkeit, dies alles auf einmal zu tun?
Ich bin nicht sicher, ob mein Sed-Fu stark genug ist, um einen Ausdruck vom Typ „Alle Zeilen bis zum regulären Ausdruck löschen, dann den Rest der Datei durchlassen“ auszuführen.
Dies läuft auf Debian Linux, daher stehen mir GNU-Tools zur Verfügung.
Antwort1
bunzip2 -c backup.sql.bz2 | \
sed -n '/-- Table structure for `mytable`/,$p'
Erläuterung:
-n suppress automatic printing of pattern space
Adressbereichsaufbau: Beginnen Sie mit regulären Ausdrücken
/-- Table structure for `mytable`/
Ende mit
$ Match the last line.
Befehl
p Print the current pattern space.
Bearbeiten: Abhängig davon, wie Sie die Datenbank gesichert haben, haben Sie möglicherweisesehrlange Zeilen. GNU sed kann sie im Rahmen der verfügbaren Speichermenge verarbeiten.
Antwort2
HINWEIS: Keine tatsächliche Antwort
Da ich motiviert war, dieses Problem zu lösenJetzt, ich habe es versucht und verwendet, grep
um den Offset in der gewünschten Datei zu finden. Es hat wunderbar funktioniert.
Zum Ausführen dd
ist leider ein Set erforderlich, ibs=1
was im Grunde bedeutet, dass kein Puffer vorhanden ist und die Leistung schrecklich ist. Während ich darauf wartete, dass dd fertig wird, habe ich Zeit damit verbracht, mein eigenes benutzerdefiniertes C-Programm zu schreiben, um die Bytes zu überspringen. Nachdem ich das getan hatte, sah ich, dass tail
es genauso einfach für mich hätte erledigt werden können:
$ bunzip2 -c restore.sql.bz2 | tail -c +[offset] | bzip2 -c > restore-trimmed.sql.bz2
Ich sage „das beantwortet meine Frage nicht“, weil trotzdem zwei Durchgänge durch die Datei erforderlich sind: einer, um den Offset des gesuchten Objekts zu finden, und ein weiterer, um die Datei zuzuschneiden.
Wenn ich zu meinem benutzerdefinierten Programm zurückkehren würde, könnte ich Folgendes implementieren:KMPwährend der „Nur-Lesen“-Phase des Programms und wechseln Sie danach zu „Alles lesen+schreiben“.
Antwort3
Ich frage mich, ob so etwas funktionieren würde:
use strict;
use warnings;
use feature 'say';
use IO::Uncompress::Bunzip2 '$Bunzip2Error';
my $file = $ARGV[0] // die "need a file";
my $zh = IO::Uncompress::Bunzip2->new( $file, {
AutoClose => 1,
Transparent => 1,
} ) or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";
my $trigger = undef;
while ( <$zh> ) {
chomp;
$trigger = 1 if $_ eq '-- Dumping data for table `experiments`';
say if $trigger;
}
Es beginnt also grundsätzlich mit dem Drucken des Materials gemäß dem Muster. Man kann es auch direkt an bzip2/gzip weiterleiten, wie es unter Debian perl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2
erforderlich wäre .libio-compress-perl