Keine NULL-Werte, aber ungültige Bytefolge für die Codierung von „UTF8“: 0x00

12

Ich habe die letzten 8 Stunden damit verbracht, die Ausgabe von 'mysqldump --compatible = postgresql' in PostgreSQL 8.4.9 zu importieren, und habe hier und an anderer Stelle bereits mindestens 20 verschiedene Threads zu diesem speziellen Problem gelesen, aber keine gefunden echte brauchbare Antwort, die funktioniert.

MySQL 5.1.52-Daten werden gesichert:

mysqldump -u root -p --compatible=postgresql --no-create-info --no-create-db --default-character-set=utf8 --skip-lock-tables rt3 > foo

PostgreSQL 8.4.9 Server als Ziel

Das Laden der Daten mit 'psql -U rt_user -f foo' meldet (viele davon, hier ein Beispiel):

psql:foo:29: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
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".

Demnach enthält die Eingabedatei keine NULL-Zeichen (0x00).

database-dumps:rcf-temp1# sed 's/\x0/ /g' < foo > nonulls
database-dumps:rcf-temp1# sum foo nonulls
04730 2545610 foo
04730 2545610 nonulls
database-dumps:rcf-temp1# rm nonulls

Ebenso zeigt eine weitere Prüfung mit Perl keine NULL-Werte:

database-dumps:rcf-temp1# perl -ne '/\000/ and print;' foo
database-dumps:rcf-temp1#

Wie der "TIPP" in der Fehlermeldung besagt, habe ich alle Möglichkeiten ausprobiert, um "client_encoding" auf "UTF8" zu setzen, und es ist mir gelungen, aber es hat keine Auswirkung auf die Lösung meines Problems.

database-dumps:rcf-temp1# psql -U rt_user --variable=client_encoding=utf-8 -c "SHOW client_encoding;" rt3
 client_encoding
-----------------
 UTF8
(1 row)

database-dumps:rcf-temp1#

Perfekt, aber:

database-dumps:rcf-temp1# psql -U rt_user -f foo --variable=client_encoding=utf-8 rt3
...
psql:foo:29: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
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".
...

Abgesehen von der richtigen Antwort "Laut Hoyle", die fantastisch zu hören wäre, und dem Wissen, dass es mir wirklich egal ist, Nicht-ASCII-Zeichen für diese selten referenzierten Daten zu erhalten, welche Vorschläge haben Sie?

Update: Ich erhalte den gleichen Fehler bei einer Nur-ASCII-Version der gleichen Speicherauszugsdatei zum Zeitpunkt des Imports. Wirklich umwerfend:

database-dumps:rcf-temp1# # convert any non-ASCII character to a space
database-dumps:rcf-temp1# perl -i.bk -pe 's/[^[:ascii:]]/ /g;' mysql5-dump.sql
database-dumps:rcf-temp1# sum mysql5-dump.sql mysql5-dump.sql.bk
41053 2545611 mysql5-dump.sql
50145 2545611 mysql5-dump.sql.bk
database-dumps:rcf-temp1# cmp mysql5-dump.sql mysql5-dump.sql.bk
mysql5-dump.sql mysql5-dump.sql.bk differ: byte 1304850, line 30
database-dumps:rcf-temp1# # GOOD!
database-dumps:rcf-temp1# psql -U postgres -f mysql5-dump.sql --variable=client_encoding=utf-8 rt3
...
INSERT 0 416
psql:mysql5-dump.sql:30: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 455
INSERT 0 424
INSERT 0 483
INSERT 0 447
INSERT 0 503
psql:mysql5-dump.sql:36: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 502
INSERT 0 507
INSERT 0 318
INSERT 0 284
psql:mysql5-dump.sql:41: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 382
INSERT 0 419
INSERT 0 247
psql:mysql5-dump.sql:45: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 267
INSERT 0 348
^C

Eine der fraglichen Tabellen ist wie folgt definiert:

                                        Table "public.attachments"
     Column      |            Type             |                        Modifie
-----------------+-----------------------------+--------------------------------
 id              | integer                     | not null default nextval('atta)
 transactionid   | integer                     | not null
 parent          | integer                     | not null default 0
 messageid       | character varying(160)      |
 subject         | character varying(255)      |
 filename        | character varying(255)      |
 contenttype     | character varying(80)       |
 contentencoding | character varying(80)       |
 content         | text                        |
 headers         | text                        |
 creator         | integer                     | not null default 0
 created         | timestamp without time zone |
Indexes:
    "attachments_pkey" PRIMARY KEY, btree (id)
    "attachments1" btree (parent)
    "attachments2" btree (transactionid)
    "attachments3" btree (parent, transactionid)

Ich kann den Typ für keinen Teil des DB-Schemas ändern. Andernfalls würden zukünftige Upgrades der Software usw. wahrscheinlich unterbrochen .

Die wahrscheinliche Problemspalte ist "Inhalt" vom Typ "Text" (möglicherweise auch andere in anderen Tabellen). Wie ich bereits aus früheren Untersuchungen weiß, lässt PostgreSQL NULL in 'Text'-Werten nicht zu. Wie auch immer, siehe oben, wo sowohl sed als auch Perl keine NULL-Zeichen anzeigen, und weiter unten, wo ich alle Nicht-ASCII-Zeichen aus der gesamten Dump-Datei entferne, sie aber immer noch als Balken kennzeichnet.

jblaine
quelle
2
Wie sieht Zeile 29 Ihrer Dump-Datei aus? So etwas head -29 foo | tail -1 | cat -vkönnte von Nutzen sein.
mu ist zu kurz
Wie ist die Definition der betroffenen Tabelle und wie sieht die fehlerhafte Zeile aus?
Dienstag,
Es sind ca. 1 MB Unternehmensdaten. Ich verstehe natürlich, wohin du fährst. Hier ist das Ende dieses Gedankens (bitte entschuldigen Sie mein Französisch am Ende der Zusammenfassung / Paste): gist.github.com/1525788
jblaine
tscho: Wie bereits erwähnt, ist diese Beispielfehlerzeile einer von Hunderten dieser Fehler.
Jblaine

Antworten:

3

Eines oder mehrere dieser Zeichen- / Textfelder KÖNNEN 0x00 als Inhalt haben.

Versuche Folgendes:

SELECT * FROM rt3 where some_text_field = 0x00 LIMIT 1;

Wenn dies eine einzelne Zeile zurückgibt, aktualisieren Sie diese Zeichen- / Textfelder mit:

UPDATE rt3 SET some_text_field = '' WHERE some_text_field = 0x00;

Versuchen Sie anschließend ein anderes MYSQLDUMP ... (und eine andere PostgreSQL-Importmethode).

Farley Inglis
quelle
Dies half mir, meine streunenden Nullzeichen zu finden, obwohl ich sie verwenden musste colname LIKE concat('%', 0x00, '%'). Fand sie in Feldern mit serialisierten PHP-Arrays.
Cimmanon
5

Ich hatte das gleiche Problem mit MySQL Version 5.0.51 und Postgres Version 9.3.4.0. Ich habe das Problem "Ungültige Byte-Sequenz für die Codierung von" UTF8 ": 0x00" behoben, nachdem ich Daniel Vérités Kommentar gesehen habe, dass "mysqldump im Postgresql-Modus null Bytes als \ 0 in Strings ausgeben wird. Daher möchten Sie wahrscheinlich nach dieser Folge von Zeichen suchen."

Sicher genug, dass ein Grep endlich die NULL-Zeichen enthüllte.

grep \\\\0 dump.sql

Ich habe die NULL-Zeichen mit dem folgenden Befehl ersetzt

sed -i BAK 's/\\0//g' dump.sql

Postgres konnte dann dump.sql erfolgreich laden

Jadence
quelle
4

Sie können diesen Fehler ohne ein NULL-Byte oder ein Nicht-ASCII-Zeichen in der Datei erhalten. Beispiel in einer utf8 Datenbank:

select E'ab\0cd';

wird ergeben:

FEHLER: Ungültige Bytefolge für die Codierung "UTF8": 0x00 TIPP: Dieser Fehler kann auch auftreten, wenn die Bytefolge nicht mit der vom Server erwarteten Codierung übereinstimmt, die von "client_encoding" gesteuert wird.

Da mysqldump im Postgresql-Modus null Bytes als \ 0 in Strings ausgibt, möchten Sie wahrscheinlich nach dieser Zeichenfolge suchen.

Daniel Vérité
quelle
0

Ich erinnere mich zur Hälfte an ein Problem wie dieses. Ich denke, dass ich am Ende das Schema migriert habe, dann die Daten als CSV abgelegt und die Daten aus der CSV-Datei geladen habe. Ich erinnere mich, dass ich die CSV-Datei aktualisieren musste (mit Unix-Tools wie sed oder unixtodos) oder Open Office Calc (Excell), um einige Elemente zu reparieren, bei denen Fehler beim Import aufgetreten waren Datei.

Adam f
quelle