Nessun NULL, ma sequenza di byte non valida per la codifica "UTF8": 0x00


12

Ho trascorso le ultime 8 ore a cercare di importare l'output di "mysqldump --compatible = postgresql" in PostgreSQL 8.4.9 e ho già letto almeno 20 thread diversi qui e in altre parti su questo problema specifico, ma non ho trovato vera risposta utilizzabile che funziona.

Dati MySQL 5.1.52 scaricati:

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

Server PostgreSQL 8.4.9 come destinazione

Il caricamento dei dati con 'psql -U rt_user -f foo' sta riportando (molti di questi, ecco un esempio):

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".

Secondo quanto segue, non ci sono caratteri NULL (0x00) nel file di input.

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

Allo stesso modo, un altro controllo con Perl non mostra NULL:

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

Come citato "SUGGERIMENTO" nell'errore, ho cercato in tutti i modi di impostare "client_encoding" su "UTF8", ma ci riesco ma non ha alcun effetto nel risolvere il mio problema.

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#

Perfetto, tuttavia:

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".
...

Escludendo la risposta corretta "Secondo Hoyle", che sarebbe fantastico sentirla, e sapendo che non mi interessa davvero conservare alcun carattere non ASCII per questi dati a cui raramente si fa riferimento, quali suggerimenti hai?

Aggiornamento: ottengo lo stesso errore con una versione solo ASCII dello stesso file di dump al momento dell'importazione. Veramente sbalorditivo:

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

Una delle tabelle in questione è definita come:

                                        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)

Non ho la libertà di cambiare il tipo per qualsiasi parte dello schema DB. Ciò potrebbe probabilmente interrompere i futuri aggiornamenti del software , ecc.

La colonna del probabile problema è "contenuto" di tipo "testo" (forse anche altri in altre tabelle). Come già noto da precedenti ricerche, PostgreSQL non consentirà NULL nei valori di "testo". Tuttavia, vedi sopra dove sia sed che Perl non mostrano caratteri NULL, e poi più in basso dove rimuovo tutti i caratteri non ASCII dall'intero file di dump ma continua a non funzionare.


2
Che aspetto ha la riga 29 del tuo file di dump? Qualcosa del genere head -29 foo | tail -1 | cat -vpotrebbe essere utile.
mu è troppo corto il

Qual è la definizione della tabella interessata e come appare la linea offensiva?
Tscho,

Sono ~ 1 MB di dati aziendali. Capisco ovviamente dove sei diretto. Ecco la fine di quella linea di pensiero (scusate il mio francese alla fine del gist / paste): gist.github.com/1525788
jblaine,

tscho: Come indicato, quella riga di errore di esempio è una delle centinaia di questi errori.
jblaine,

Risposte:


3

Uno o più di questi campi di caratteri / testo POSSONO avere 0x00 per il suo contenuto.

Prova quanto segue:

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

Se questo restituisce una singola riga, prova ad aggiornare quei campi carattere / testo con:

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

Successivamente, prova un altro MYSQLDUMP ... (e il metodo di importazione PostgreSQL).


Questo mi ha aiutato a trovare i miei caratteri null vaganti, anche se avevo bisogno di usare colname LIKE concat('%', 0x00, '%'). Li ho trovati in campi contenenti array PHP serializzati.
cimmanon,

5

Ho avuto lo stesso problema usando MySQL versione 5.0.51 e Postgres versione 9.3.4.0. Ho risolto il problema "sequenza di byte non valida per la codifica" UTF8 ": 0x00" dopo aver visto il commento di Daniel Vérité che "mysqldump in modalità postgresql scaricherà byte null come \ 0 nelle stringhe, quindi probabilmente vorrai cercare quella sequenza di caratteri".

Abbastanza sicuro che finalmente un grep ha rivelato i caratteri NULL.

grep \\\\0 dump.sql

Ho sostituito i caratteri NULL usando il seguente comando

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

Postgres è stato quindi in grado di caricare correttamente dump.sql


4

È possibile ottenere questo errore senza byte NULL o caratteri non ASCII nel file. Esempio in un database utf8:

select E'ab\0cd';

produrrà:

ERRORE: sequenza di byte non valida per la codifica "UTF8": 0x00 SUGGERIMENTO: questo errore può verificarsi anche se la sequenza di byte non corrisponde alla codifica prevista dal server, che è controllata da "client_encoding".

mysqldump in modalità postgresql scaricherà byte nulli come \ 0 nelle stringhe, quindi probabilmente vorrai cercare quella sequenza di caratteri.


0

Ricordo a metà un problema come questo. Penso di aver finito per migrare lo schema, quindi scaricare i dati come CSV e caricare i dati dal file CSV. Ricordo di aver dovuto aggiornare il file csv (usando strumenti unix come sed o unixtodos) o usando open office calc (excell) per sistemare alcuni elementi che erano errori nella fase di importazione - potrebbe essere semplice come aprire e salvare nuovamente il file.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.