it-swarm.com.de

Wie löse ich ungültige UTF8-Fehler beim Kopieren von Byte-Sequenzen bei einer Wiederherstellung, wenn die Quellendatenbank in UTF8 codiert ist?

Ich erhielt die Aufgabe, eine PostgreSQL 8.2.x-Datenbank auf einen anderen Server zu migrieren. Dazu verwende ich pgAdmin 1.12.2 (übrigens unter Ubuntu 11.04) und das Backup and Restore mit dem benutzerdefinierten/compress-Format (.backup) und der UTF8-Codierung.

Die ursprüngliche Datenbank befindet sich wie folgt in UTF8:

-- Database: favela

-- DROP DATABASE favela;

CREATE DATABASE favela
  WITH OWNER = favela
       ENCODING = 'UTF8'
       TABLESPACE = favela
       CONNECTION LIMIT = -1;

Ich erstelle diese Datenbank genau so auf dem Zielserver. Wenn ich jedoch die Datenbank aus der Sicherungsdatei mit der Option "Wiederherstellen" wiederherstelle, werden einige der folgenden Fehler angezeigt:

pg_restore: restoring data for table "arena"
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 2173; 0 35500 TABLE DATA arena favela
pg_restore: [archiver (db)] COPY failed: ERROR:  invalid byte sequence for encoding "UTF8": 0xe3a709
HINT:  This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client_encoding".
CONTEXT:  COPY arena, line 62

Wenn ich überprüfe, welcher Datensatz diesen Fehler ausgelöst hat, haben einige Vartextfelder diakritische Zeichen wie ç (auf Portugiesisch verwendet, z. B. "caça"), und wenn ich sie manuell aus dem Text in den Datensätzen entferne, wird der Fehler an den nächsten Datensatz übergeben das hat sie - denn wenn beim Kopieren ein Fehler auftritt, werden keine Daten mehr in diese Tabelle eingefügt. Und ich möchte sie nicht einzeln manuell ersetzen, um dies zu erreichen.

Aber es ist irgendwie seltsam, denn mit UTF8 sollte es solche Probleme nicht geben, oder?

Ich weiß nicht, wie sie überhaupt dorthin gekommen sind. Ich migriere nur die Datenbank und nehme an, dass die Datenbank irgendwie wie in LATIN1 war und dann nicht ordnungsgemäß in UTF8 geändert wurde.

Gibt es eine Möglichkeit zu überprüfen, ob eine Tabelle/Datenbank ungültige UTF8-Sequenzen enthält? Oder eine Möglichkeit, diese Zeichen in UFT8 zu erzwingen/umzuwandeln, damit beim Ausführen der Wiederherstellung keine Probleme auftreten?

Danke im Voraus.

17
pedrosanta

Beim Stöbern im Internet habe ich gesehen, dass dies ein ziemlich häufiges Problem ist. Die übliche Lösung besteht darin, den Dump im Nur-Text-Format zu verwenden und ihn durch iconv zu führen, um die Codierung zu korrigieren.

hier ist mehr Information darüber.

8
Richard

"Ich weiß nicht, wie sie überhaupt dorthin gekommen sind"

Es könnte wie beschrieben geschehen sein hier - obwohl dies bei 8.4 einen Fehler erzeugt:

Wenn Sie eine Tabelle mit einem beliebigen Texttyp (d. H. Text, varchar (10) usw.) erstellen, können Sie mit oktalen Escapezeichen eine ungültige Bytefolge in dieses Feld einfügen.

Wenn Sie beispielsweise eine UTF8-codierte Datenbank haben, können Sie Folgendes tun:

=> CREATE TABLE foo (t TEXT);

=> INSERT IN foo VALUES (E '\ 377');

Wenn Sie jetzt die Tabelle kopieren, können Sie die resultierende Datei nicht wieder kopieren. Das bedeutet, dass Ihre pg_dump-Backups nicht wiederhergestellt werden können. Die einzige Möglichkeit, Ihre Daten wiederherzustellen, besteht darin, diesen Wert erneut zu umgehen.

Es gibt einen guten Beitrag zu diesem ausgezeichneter Blog über die allgemeinen Probleme und einige Möglichkeiten, mit ihnen umzugehen

Ich empfehle nicht, iconv blind auf dem Nur-Text-Dump auszuführen, da dadurch möglicherweise gültige Zeichen (z. B. chinesische Zeichen) in andere Zeichen konvertiert werden. Es ist besser, das ungültige UTF8-Zeichen zu finden, indem Sie den folgenden Befehl ausführen.

grep -naxv '.*' plain_text_dump.sql

führen Sie dann iconv für die jeweiligen Daten aus. Überprüfen Sie dieses Dokument enthält eine detaillierte schrittweise Erklärung .

1
Nijil

Dies ist wahrscheinlich mit der Standardcodierung, die in Ihrer Unix/Linux-Umgebung verwendet wird. Führen Sie die folgenden Schritte aus, um zu überprüfen, welche Codierung derzeit die Standardcodierung ist:

$ echo $LANG
en_US

In diesem Fall können wir deutlich erkennen, dass es sich nicht um eine UTF-8-Codierung handelt, auf die sich der Kopierbefehl stützt.

Um dies zu beheben, setzen wir die LANG-Variable im Beispiel wie folgt:

$ export LANG=en_US.UTF-8

Hinweis: Dies ist nur für die aktuelle Sitzung verfügbar. Fügen Sie es zu ~/.bashrc oder ähnlichem hinzu, damit es beim Start einer zukünftigen Shell-Sitzung verfügbar ist.

Referenz

1
arulraj.net

Ich habe auf den folgenden Link verwiesen, der mir Hinweise gab, um die Quellcodierung zu bestimmen und sie dann in die gewünschte UTF-8-Codierung umzuwandeln. Linux Check and Change Encoding

$ file -bi cabot.sql
text/plain; charset=utf-16le
$ iconv -f utf-16le -t utf-8 -o converted.sql cabot.sql
$ file -bi converted.sql
text/plain; charset=utf-8
0
Biswajit Barman