Wie löse ich UTF8-Fehler beim Kopieren ungültiger Bytesequenzen bei einer Wiederherstellung, wenn die Quellendatenbank in UTF8 codiert ist?

17

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

Die ursprüngliche Datenbank ist in UTF8 wie folgt:

-- 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 die Datenbank jedoch mit der Option "Wiederherstellen" aus der Sicherungsdatei 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 vartext-Felder diakritische Zeichen wie ç (in Portugiesisch beispielsweise "caça"), und wenn ich sie manuell aus dem Text in den Datensätzen entferne, wird der Fehler an den nächsten Datensatz weitergegeben Das hat sie - da beim Kopieren ein Fehler auftritt und das Einfügen von Daten in diese Tabelle gestoppt wird. Und ich möchte sie nicht einzeln manuell ersetzen, um dies zu erreichen.

Aber es ist irgendwie seltsam, denn mit UTF8 sollte es keine derartigen Probleme 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 umzuwandeln, damit beim Ausführen der Wiederherstellung keine Probleme auftreten?

Danke im Voraus.

pedrosanta
quelle

Antworten:

8

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

Hier gibt es mehr Informationen dazu.

Richard
quelle
Verwenden Sie iconv, um nach UTF-32 zu konvertieren, und verwerfen Sie ungültige Symbole. Wenn Sie dann nach UTF-8 zurückkehren, werden bei einer Konvertierung von UTF-8 nach UTF-8 nicht alle fehlerhaften Codepunkte erfasst. (zB verwaiste Leihmütter)
Jasen
7

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

Es hätte passieren können, wie hier beschrieben - obwohl dies in 8.4 einen Fehler erzeugt:

Wenn Sie eine Tabelle mit einem beliebigen Texttyp (z. B. Text, Varchar (10) usw.) erstellen, können Sie eine ungültige Byte-Sequenz in dieses Feld einfügen, indem Sie Oktal-Escape-Zeichen verwenden.

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

=> CREATE TABLE foo (t TEXT);

=> INSERT INOO VALUES (E '\ 377');

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

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

Jack Douglas
quelle
1

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

$ echo $LANG
en_US

In diesem Fall sehen wir deutlich, 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 auf Folgendes:

$ 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

arulraj.net
quelle
1

Ich empfehle nicht, iconv blind auf dem Klartext-Dump auszuführen, da dies möglicherweise gültige Zeichen (z. B. chinesische Zeichen) in andere Zeichen umwandelt. 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 anschließend iconv für die jeweiligen Daten aus. In diesem Dokument finden Sie detaillierte schrittweise Erklärungen .

Nijil
quelle