Ні NULL, але недійсна послідовність байтів для кодування "UTF8": 0x00


12

Я провів останні 8 годин, намагаючись імпортувати вихід 'mysqldump --compatible = postgresql' в PostgreSQL 8.4.9, і я прочитав щонайменше 20 різних ниток тут і інших місць вже про цю конкретну проблему, але не знайшов жодної реальна корисна відповідь, яка працює.

Дані MySQL 5.1.52:

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 як пункт призначення

Завантаження даних з 'psql -U rt_user -f foo' є звітні (багато з них, ось один приклад):

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

Відповідно до цього, у вхідному файлі немає символів NULL (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

Аналогічно, ще одна перевірка за допомогою Perl не показує NULL:

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

Як згадується "Підказка" в помилці, я намагався всіма можливими способами встановити "client_encoding" на "UTF8", і мені це вдалося, але це не впливає на вирішення моєї проблеми.

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#

Ідеально, але:

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

Забороняючи правильну відповідь "За Хойлом", яку було б чудово чути, і знаючи, що мені дуже не важливо зберігати будь-які символи, що не належать до ASCII, для цих рідко посилаються даних, які пропозиції ви маєте?

Оновлення: я отримую ту ж помилку з версією ASCII, призначеною лише для ASCII, того самого файлу дампа під час імпорту. Воістину приголомшливі:

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

Одна з розглянутих таблиць визначається як:

                                        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)

Я не маю права змінювати тип для будь-якої частини схеми БД. Це може призвести до порушення майбутніх оновлень програмного забезпечення тощо.

Ймовірний стовпець проблеми - "вміст" типу "текст" (можливо, і інші в інших таблицях). Як я вже знаю з попередніх досліджень, PostgreSQL не дозволить NULL в "текстових" значеннях. Однак, дивіться вище, де і sed, і Perl не показують символів NULL, а потім далі вниз, де я знімаю всі символи, що не належать до ASCII, з усього дамп-файлу, але він все ще залишається затримкою.


2
Як виглядає рядок 29 вашого дамп-файлу? Щось подібне head -29 foo | tail -1 | cat -vможе бути корисним.
mu занадто короткий

Як визначається таблиця, на яку впливає, і як виглядає рядок порушника?
цчо

Це ~ 1 Мб даних компанії. Я розумію, куди ви, звичайно, керуєте. Ось кінець цієї лінії думок (пробачте про мою французьку в кінці суті / вставки): gist.github.com/1525788
jblaine

tscho: Як зазначено, що приклад рядка помилки є однією з сотень цих помилок.
jblaine

Відповіді:


3

Одне або кілька таких символьних / текстових полів МОЖЕ мати 0x00 для свого вмісту.

Спробуйте наступне:

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

Якщо це повертає будь-який один рядок, то спробуйте оновити ці символьні / текстові поля за допомогою:

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

Після цього спробуйте інший MYSQLDUMP ... (і метод імпорту PostgreSQL).


Це допомогло мені знайти своїх бродячих нульових персонажів, хоча мені потрібно було користуватися colname LIKE concat('%', 0x00, '%'). Знайдено їх у полях, що містять серіалізовані масиви PHP.
cimmanon

5

У мене була така ж проблема з використанням MySQL версії 5.0.51 та Postgres версії 9.3.4.0. Я вирішив проблему "недійсна послідовність байтів для кодування" UTF8 ": 0x00" після того, як побачив коментар Даніеля Верете, що "mysqldump у режимі postgresql скидає нульові байти як \ 0 у рядках, тому ви, ймовірно, хочете шукати цю послідовність символів."

Впевнений, що досить греп нарешті виявив значення NULL.

grep \\\\0 dump.sql

Я замінив символи NULL за допомогою наступної команди

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

Потім Postgres вдалося успішно завантажити dump.sql


4

Ви можете отримати цю помилку без будь-якого байта NULL або будь-якого символу non-ascii у файлі. Приклад у базі даних utf8:

select E'ab\0cd';

дасть:

ПОМИЛКА: недійсна послідовність байтів для кодування "UTF8": 0x00 Підказка: Ця помилка також може статися, якщо послідовність байтів не відповідає кодуванню, очікуваному сервером, який контролюється "client_encoding".

mysqldump в режимі postgresql скидає нульові байти як \ 0 у рядках, тому, ймовірно, ви хочете шукати цю послідовність символів.


0

Я наполовину пам’ятаю подібну проблему. Я думаю, що я закінчив мігрувати схему, потім скидаючи дані у форматі csv та завантажуючи дані з файлу csv. Я пам’ятаю, що потрібно було оновити файл csv (використовуючи інструменти unix, такі як sed або unixtodos), або використовувати calc з відкритим офісом (excell), щоб виправити деякі елементи, які були помилками на етапі імпорту - це може бути таким же простим, як відкриття та відновлення збереження файл.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.