Nenhum NULL, mas sequência de bytes inválida para codificação “UTF8”: 0x00

12

Passei as últimas 8 horas tentando importar a saída do 'mysqldump --compatible = postgresql' para o PostgreSQL 8.4.9 e li pelo menos 20 threads diferentes aqui e eles já em algum lugar sobre esse problema específico, mas não encontrei resposta útil real que funciona.

Dados do MySQL 5.1.52 despejados:

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

Servidor PostgreSQL 8.4.9 como destino

O carregamento dos dados com 'psql -U rt_user -f foo' está sendo relatado (muitos deles, aqui está um exemplo):

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

De acordo com o seguinte, não há caracteres NULL (0x00) no arquivo de entrada.

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

Da mesma forma, outra verificação com Perl não mostra NULLs:

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

Como o "HINT" no erro menciona, tentei de todas as formas possíveis definir 'client_encoding' como 'UTF8', e obtive sucesso, mas isso não tem efeito na solução do meu 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#

Perfeito, ainda:

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

Exceto a resposta correta "De acordo com Hoyle", o que seria fantástico de ouvir, e sabendo que realmente não me importo em preservar caracteres não ASCII para esses dados raramente referenciados, que sugestões você tem?

Atualização: Eu recebo o mesmo erro com uma versão somente ASCII do mesmo arquivo de despejo no momento da importação. Verdadeiramente incompreensível:

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

Uma das tabelas em questão é definida como:

                                        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)

Não tenho a liberdade de alterar o tipo de qualquer parte do esquema do banco de dados. Isso provavelmente quebraria futuras atualizações do software etc.

A coluna do problema provável é 'conteúdo' do tipo 'texto' (talvez outros também em outras tabelas). Como eu já sei em pesquisas anteriores, o PostgreSQL não permitirá NULL em valores de 'texto'. No entanto, veja acima, onde sed e Perl não mostram caracteres NULL, e mais abaixo, onde retiro todos os caracteres não ASCII de todo o arquivo de despejo, mas ele ainda vomita.

jblaine
fonte
2
Como é a linha 29 do seu arquivo de despejo? Algo como head -29 foo | tail -1 | cat -vpode ser útil.
mu é muito curto
Qual é a definição da tabela afetada e como é a linha incorreta?
tscho 28/12/11
São aproximadamente 1 MB de dados da empresa. Eu entendo para onde você está indo, é claro. Aqui está o final dessa linha de pensamento (perdoe meu francês no final da essência / pasta): gist.github.com/1525788
jblaine
tscho: Como indicado, esse exemplo de linha de erro é uma das centenas desses erros.
Jblaine

Respostas:

3

Um ou mais desses campos de caracteres / texto PODEM ter 0x00 para o seu conteúdo.

Tente o seguinte:

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

Se isso retornar uma única linha, tente atualizar esses campos de caracteres / texto com:

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

Depois, tente outro MYSQLDUMP ... (e o método de importação do PostgreSQL).

Farley Inglis
fonte
Isso me ajudou a encontrar meus caracteres nulos perdidos, embora eu precisasse usá-lo colname LIKE concat('%', 0x00, '%'). Encontrei-os em campos contendo matrizes PHP serializadas.
Cimmanon
5

Eu tive o mesmo problema usando o MySQL versão 5.0.51 e Postgres versão 9.3.4.0. Resolvi o problema "sequência de bytes inválida para codificação" UTF8 ": 0x00" depois de ver o comentário de Daniel Vérité de que "o mysqldump no modo postgresql despejaria bytes nulos como \ 0 nas strings, então você provavelmente deseja procurar essa sequência de caracteres".

Com certeza, um grep finalmente revelou os caracteres NULL.

grep \\\\0 dump.sql

Substituí os caracteres NULL usando o seguinte comando

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

O Postgres conseguiu carregar com êxito o dump.sql

Jadence
fonte
4

Você pode obter esse erro sem nenhum byte nulo ou nenhum caractere não-ascii no arquivo. Exemplo em um banco de dados utf8:

select E'ab\0cd';

produzirá:

ERRO: sequência de bytes inválida para a codificação "UTF8": 0x00 DICA: Este erro também pode ocorrer se a sequência de bytes não corresponder à codificação esperada pelo servidor, que é controlada por "client_encoding".

O mysqldump no modo postgresql irá despejar bytes nulos como \ 0 em strings, então você provavelmente desejará procurar por essa sequência de caracteres.

Daniel Vérité
fonte
0

Eu meio que me lembro de um problema como este. Acho que acabei migrando o esquema, depois descarregando os dados como csv e carregando os dados do arquivo csv. Lembro-me de ter que atualizar o arquivo csv (usando ferramentas unix como sed ou unixtodos) ou usando o open office calc (excell) para corrigir alguns itens que eram erros na etapa de importação - pode ser tão simples quanto abrir e salvar novamente o arquivo Arquivo.

adam f
fonte