Як вирішити помилки при копіюванні послідовності байтів UTF8 під час відновлення, коли джерельна база даних кодується в UTF8?


17

Мені було надано завдання перемістити базу даних PostgreSQL 8.2.x на інший сервер. Для цього я використовую pgAdmin 1.12.2 (до речі, на Ubuntu 11.04) та використовую резервну копію та відновлення, використовуючи спеціальний / стислий формат (.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, щоб у мене не виникло проблем при виконанні відновлення?

Спасибі заздалегідь.

Відповіді:


8

Копаючись по Інтернету, я бачив, що це досить поширена проблема. Поширене рішення - використовувати дамп простого тексту тексту та подавати його через iconv, щоб виправити кодування.

Ось більше інформації про це.


використовуйте iconv для перетворення в UTF-32, відкидаючи недійсні символи, а потім назад до UTF-8, перетворення UTF-8 в UTF-8 не сприймає всі погані кодові точки. (наприклад, сироти-сироти)
Ясен

7

"Я не знаю, як вони потрапили в першу чергу"

Це могло статися як описано тут, хоча це призводить до помилки 8.4:

Якщо ви створюєте таблицю з будь-яким текстовим типом (наприклад, текстом, варшаром (10) тощо), ви можете вставити невірну послідовність байтів у це поле за допомогою восьмеричних вискоків.

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

=> СТВОРИТИ ТАБЛИЦЮ foo (t ТЕКСТ);

=> ВСТАВИТЬСЯ в foo VALUES (E '\ 377');

Тепер, якщо ви скопіювали таблицю, ви не можете скопіювати отриманий файл назад. Це означає, що ваші резервні копії pg_dump не зможуть відновитись. Єдиний спосіб повернути свої дані - це повторне використання цього значення.

У цьому відмінному блозі є хороший пост про загальні проблеми та деякі способи їх вирішення


1

Ймовірно, кодування за замовчуванням використовується у вашому середовищі Unix / Linux Щоб перевірити, яке кодування зараз є типовим, виконайте наступне:

$ echo $LANG
en_US

У цьому випадку ми можемо чітко бачити, що це не кодування UTF-8, а те, на яке покладається команда копіювання.

Отже, щоб виправити це, ми просто встановимо змінну LANG на прикладі наступного:

$ export LANG=en_US.UTF-8

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

Довідково


1

Я не рекомендую сліпо запускати iconv на простому текстовому дамп, оскільки він може конвертувати дійсні символи (наприклад, китайські символи) до деяких інших символів. Краще знайти недійсний символ UTF8, натиснувши команду нижче.

grep -naxv '.*' plain_text_dump.sql

а потім запустіть iconv на конкретних даних. Перевірте цей документ для детального покрокового пояснення .

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