No hay NULL, pero la secuencia de bytes no es válida para codificar "UTF8": 0x00

12

Pasé las últimas 8 horas tratando de importar la salida de 'mysqldump --compatible = postgresql' en PostgreSQL 8.4.9, y he leído al menos 20 hilos diferentes aquí y en otros sitios sobre este problema específico, pero no encontré ningún respuesta utilizable real que funciona.

Datos de MySQL 5.1.52 volcados:

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

Se está cargando la información con 'psql -U rt_user -f foo' (muchos de estos, aquí hay un ejemplo):

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

Según lo siguiente, no hay caracteres NULL (0x00) en el archivo 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

Del mismo modo, otra verificación con Perl no muestra NULL:

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

Como se menciona en la "SUGERENCIA" en el error, he intentado todas las formas posibles de establecer 'client_encoding' en 'UTF8', y tengo éxito, pero no tiene ningún efecto para resolver mi 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#

Perfecto, sin embargo:

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

Salvo la respuesta correcta "Según Hoyle", que sería fantástico escuchar, y sabiendo que realmente no me importa preservar ningún carácter no ASCII para estos datos raramente referenciados, ¿qué sugerencias tiene?

Actualización: obtengo el mismo error con una versión solo ASCII del mismo archivo de volcado en el momento de la importación. Realmente alucinante:

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 de las tablas en cuestión se define 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)

No tengo la libertad de cambiar el tipo de ninguna parte del esquema DB. Hacerlo probablemente rompería futuras actualizaciones del software , etc.

La columna del problema probable es 'contenido' del tipo 'texto' (quizás otros en otras tablas también). Como ya sé por investigaciones anteriores, PostgreSQL no permitirá NULL en valores de 'texto'. Sin embargo, vea arriba donde tanto sed como Perl no muestran caracteres NULOS, y luego más abajo donde elimino todos los caracteres que no son ASCII del archivo de volcado completo, pero aún se barfs.

jblaine
fuente
2
¿Cómo se ve la línea 29 de su archivo de volcado? Algo así head -29 foo | tail -1 | cat -vpodría ser útil.
mu es demasiado corto el
¿Cuál es la definición de la tabla afectada y cómo se ve la línea ofensiva?
tscho
Son ~ 1 MB de datos de la compañía. Sin embargo, entiendo a dónde te diriges. Aquí está el final de esa línea de pensamiento (disculpe mi francés al final de la esencia / pasta): gist.github.com/1525788
jblaine
tscho: Como se indicó, esa línea de error de ejemplo es uno de los cientos de estos errores.
jblaine

Respuestas:

3

Uno o más de esos campos de caracteres / texto PUEDEN tener 0x00 para su contenido.

Intenta lo siguiente:

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

Si esto devuelve una sola fila, intente actualizar esos campos de caracteres / texto con:

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

Luego, intente con otro MYSQLDUMP ... (y el método de importación PostgreSQL).

Farley Inglis
fuente
Esto me ayudó a encontrar mis personajes nulos perdidos, aunque necesitaba usarlos colname LIKE concat('%', 0x00, '%'). Los encontré en campos que contienen matrices PHP serializadas.
cimmanon
5

Tuve el mismo problema usando MySQL versión 5.0.51 y Postgres versión 9.3.4.0. Resolví el problema de "secuencia de bytes no válida para codificar" UTF8 ": 0x00" después de ver el comentario de Daniel Vérité de que "mysqldump en modo postgresql volcará bytes nulos como \ 0 en cadenas, por lo que probablemente desee buscar esa secuencia de caracteres".

Efectivamente, un grep finalmente reveló los caracteres NULL.

grep \\\\0 dump.sql

Reemplacé los caracteres NULL usando el siguiente comando

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

Postgres pudo cargar con éxito dump.sql

Jadence
fuente
4

Puede obtener este error sin ningún byte NULL o ningún carácter no ascii en el archivo. Ejemplo en una base de datos utf8:

select E'ab\0cd';

rendirá:

ERROR: secuencia de bytes no válida para la codificación "UTF8": 0x00 SUGERENCIA: Este error también puede ocurrir si la secuencia de bytes no coincide con la codificación esperada por el servidor, que está controlado por "client_encoding".

mysqldump en el modo postgresql volcará bytes nulos como \ 0 en cadenas, por lo que probablemente desee buscar esa secuencia de caracteres.

Daniel Vérité
fuente
0

Medio recuerdo un problema como este. Creo que terminé migrando el esquema y luego volcando los datos como csv y cargando los datos del archivo csv. Recuerdo tener que actualizar el archivo csv (usando herramientas de Unix como sed o unixtodos) o usando Open Office calc (excell) para arreglar algunos elementos que eran errores en el paso de importación; podría ser tan simple como abrir y volver a guardar el archivo.

adam f
fuente