it-swarm.it

Come risolvere gli errori di copia della sequenza di byte non validi UTF8 su un ripristino, quando il database di origine è codificato in UTF8?

Mi è stato affidato il compito di migrare un database PostgreSQL 8.2.x su un altro server. Per fare ciò sto usando pgAdmin 1.12.2 (su Ubuntu 11.04 a proposito) e usando il Backup e il Ripristino usando il formato personalizzato/comprimere (.backup) e la codifica UTF8.

Il database originale è in UTF8, in questo modo:

-- Database: favela

-- DROP DATABASE favela;

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

Sto creando questo database esattamente come questo sul server di destinazione. Ma quando ripristino il database dal file .backup usando l'opzione Ripristina mi dà alcuni di questi errori:

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

Quando controllo quale record ha innescato questo errore, in effetti alcuni campi vartext hanno caratteri diacritici come ç (usato in portoghese, ad esempio "caça"), e quando li rimuovo manualmente dal testo nei record l'errore passa al record successivo che li ha - poiché quando la copia ha un errore smette di inserire dati in questa tabella. E non voglio sostituirli manualmente uno per uno per ottenere questo risultato.

Ma è un po 'strano perché con UTF8 non dovrebbe esserci questo tipo di problemi, giusto?

Non so come ci siano arrivati ​​in primo luogo. Sto solo migrando il database e suppongo che in qualche modo il database fosse come in LATIN1 e quindi sia stato erroneamente cambiato in UTF8.

Esiste un modo per verificare se una tabella/database ha sequenze UTF8 non valide? O un modo per imporre/riconvertire questi caratteri in UFT8 in modo da non incorrere in alcun problema quando eseguo il ripristino?

Grazie in anticipo.

17
pedrosanta

Scavando su Internet, ho visto che questo è un problema piuttosto comune. La soluzione comune è quella di utilizzare il dump in formato testo normale e inviarlo tramite iconv per correggere la codifica.

Qui sono maggiori informazioni a riguardo.

8
Richard

"In primo luogo non so come ci siano arrivati"

Potrebbe essere successo come descritto qui - sebbene ciò generi un errore su 8.4:

Se si crea una tabella con qualsiasi tipo di testo (ad esempio, text, varchar (10), ecc.), È possibile inserire una sequenza di byte non valida in quel campo utilizzando gli escape ottali.

Ad esempio, se si dispone di un database con codifica UTF8, è possibile eseguire:

=> CREA TABELLA foo (t TEXT);

=> INSERISCI IN VALORI (E '\ 377');

Ora, se si COPIA la tabella, non è possibile COPIARE nuovamente il file risultante. Ciò significa che i backup di pg_dump non saranno in grado di ripristinare. L'unico modo per recuperare i tuoi dati è ripristinare il valore.

C'è un buon post su questo blog eccellente sulle questioni generali e alcuni modi per affrontarle

Non consiglio di eseguire ciecamente iconv sul dump del testo normale perché potrebbe convertire caratteri validi (ad esempio: caratteri cinesi) in altri caratteri. È meglio trovare il carattere UTF8 non valido eseguendo il comando seguente.

grep -naxv '.*' plain_text_dump.sql

e quindi eseguire iconv sui dati particolari. Controlla questo documento per una spiegazione dettagliata dettagliata .

1
Nijil

È probabile con la codifica predefinita utilizzata nel tuo ambiente Unix/Linux. Per verificare quale codifica è attualmente quella predefinita, eseguire quanto segue:

$ echo $LANG
en_US

In questo caso, possiamo vedere chiaramente che non è una codifica UTF-8, quella su cui si basa il comando di copia.

Quindi per risolvere questo problema, abbiamo semplicemente impostato la variabile LANG nell'esempio come segue:

$ export LANG=en_US.UTF-8

Nota: questo sarà disponibile solo per la sessione corrente. Aggiungilo a ~/.bashrc o simile per renderlo disponibile all'avvio di qualsiasi sessione Shell futura.

riferimento

1
arulraj.net

Ho fatto riferimento al seguente link che mi ha dato indizi per determinare la codifica sorgente e quindi convertirla nella codifica UTF-8 desiderata. 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