Как устранить ошибки копирования недопустимой последовательности байтов UTF8 при восстановлении, когда исходная база данных закодирована в UTF8?

17

Мне было поручено перенести базу данных PostgreSQL 8.2.x на другой сервер. Для этого я использую pgAdmin 1.12.2 (кстати, в Ubuntu 11.04), а также использую резервное копирование и восстановление, используя формат custom / compress (.backup) и кодировку UTF8.

Исходная база данных находится в UTF8, вот так:

-- Database: favela

-- DROP DATABASE favela;

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

Я создаю эту базу данных точно так же, как это на целевом сервере. Но когда я восстанавливаю базу данных из файла .backup, используя опцию Восстановить, это дает мне некоторые из этих ошибок:

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

Когда я проверяю, какая запись вызвала эту ошибку, на самом деле в некоторых полях из текстового поля есть диакритические символы, такие как ç (используется на португальском языке, например, «caça»), и когда я вручную удаляю их из текста в записях, ошибка переходит к следующей записи. у них есть - поскольку при копировании возникает ошибка, он прекращает вставку данных в эту таблицу. И я не хочу заменять их вручную один за другим для достижения этой цели.

Но это немного странно, потому что с UTF8 не должно быть таких проблем, верно?

Я не знаю, как они туда попали. Я только перемещаю базу данных, и я полагаю, что база данных каким-то образом была похожа на LATIN1, а затем была неправильно изменена на UTF8.

Есть ли способ проверить, есть ли в таблице / базе данных недопустимые последовательности UTF8? Или какой-нибудь способ принудительно / преобразовать эти символы в UFT8, чтобы у меня не возникало проблем при выполнении восстановления?

Заранее спасибо.

pedrosanta
источник

Ответы:

8

Покопавшись в интернете, я увидел, что это довольно распространенная проблема. Распространенным решением является использование дампа в формате простого текста и подача его через iconv для исправления кодировки.

Вот больше информации об этом.

Ричард
источник
используйте iconv для преобразования в UTF-32, отбрасывая недопустимые символы, а затем обратно в UTF-8, преобразование UTF-8 в UTF-8 не уловит все плохие кодовые точки. (например, суррогаты-сироты)
Джейсен
7

«Я не знаю, как они туда попали»

Это могло произойти, как описано здесь - хотя это приводит к ошибке на 8.4:

Если вы создаете таблицу с любым типом текста (например, text, varchar (10) и т. Д.), То вы можете вставить недопустимую последовательность байтов в это поле, используя восьмеричные экранированные символы.

Например, если у вас есть база данных в кодировке UTF8, вы можете сделать:

=> CREATE TABLE foo (t TEXT);

=> ВСТАВИТЬ В ЦЕННОСТИ foo (E '\ 377');

Теперь, если вы скопируете таблицу, вы не сможете скопировать полученный файл обратно. Это означает, что ваши резервные копии pg_dump не смогут восстановить. Единственный способ вернуть ваши данные - это повторно экранировать это значение.

В этом отличном блоге есть хороший пост об общих проблемах и некоторых способах их решения.

Джек Дуглас
источник
1

Вероятно, с кодировкой по умолчанию, используемой в вашей среде Unix / Linux. Чтобы проверить, какая кодировка в настоящее время является кодировкой по умолчанию, выполните следующее:

$ echo $LANG
en_US

В этом случае мы можем ясно видеть, что это не кодировка UTF-8, а та, на которую опирается команда копирования.

Поэтому, чтобы исправить это, мы просто устанавливаем переменную LANG в следующем примере:

$ export LANG=en_US.UTF-8

Примечание. Это будет доступно только для текущего сеанса. Добавьте его в ~ / .bashrc или аналогичный, чтобы он был доступен при запуске любого будущего сеанса оболочки.

Ссылка

arulraj.net
источник
1

Я не рекомендую слепо запускать iconv в дампе простого текста, поскольку он может преобразовывать действительные символы (например, китайские символы) в некоторые другие символы. Лучше найти недопустимый символ UTF8, выполнив команду ниже.

grep -naxv '.*' plain_text_dump.sql

и затем запустите iconv для определенных данных. Проверьте этот документ для подробного пошагового объяснения .

Nijil
источник