it-swarm.dev

Jak rozwiązać błędy kopiowania nieprawidłowej sekwencji bajtów UTF8 podczas przywracania, gdy źródłowa baza danych jest zakodowana w UTF8?

Dostałem zadanie migracji bazy danych PostgreSQL 8.2.x na inny serwer. Aby to zrobić, używam pgAdmin 1.12.2 (tak na marginesie, na Ubuntu 11.04) i korzystam z Backup and Restore, używając niestandardowego formatu/kompresji (.backup) i kodowania UTF8.

Oryginalna baza danych znajduje się w UTF8, podobnie jak:

-- Database: favela

-- DROP DATABASE favela;

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

Tę bazę danych tworzę dokładnie na serwerze docelowym. Ale kiedy przywracam bazę danych z pliku .backup przy użyciu opcji Przywróć, daje mi to niektóre z następujących błędów:

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

Kiedy sprawdzam, który rekord spowodował ten błąd, w rzeczywistości niektóre pola vartext mają znaki diakrytyczne, takie jak ç (używane w języku portugalskim, na przykład „caça”), a kiedy ręcznie usuwam je z tekstu w rekordach, błąd przechodzi do następnego rekordu to ma je - ponieważ gdy kopia ma błąd, przestaje wstawiać dane do tej tabeli. I nie chcę ich zastępować ręcznie jeden po drugim, aby to osiągnąć.

Ale to trochę dziwne, ponieważ z UTF8 nie powinno być takich problemów, prawda?

Nie wiem, jak się tam dostali. Migruję tylko bazę danych i przypuszczam, że w jakiś sposób baza danych była podobna do LATIN1, a następnie została nieprawidłowo zmieniona na UTF8.

Czy istnieje sposób sprawdzenia, czy tabela/baza danych ma nieprawidłowe sekwencje UTF8? Lub w jakikolwiek sposób wymusić/przekonwertować te znaki na UFT8, aby nie napotkać żadnych problemów podczas przywracania?

Z góry dziękuję.

17
pedrosanta

Przeszukując Internet, zauważyłem, że jest to dość powszechny problem. Typowym rozwiązaniem jest użycie zrzutu zwykłego tekstu i przesłanie go przez iconv, aby poprawić kodowanie.

tutaj to więcej informacji na ten temat.

8
Richard

„Nie wiem, jak się tam dostali”

Może się to zdarzyć zgodnie z opisem tutaj - chociaż generuje to błąd w wersji 8.4:

Jeśli utworzysz tabelę z dowolnym typem tekstu (tj. Tekst, varchar (10) itp.), Możesz wstawić niepoprawną sekwencję bajtów do tego pola, używając ósemkowych znaków ucieczki.

Na przykład, jeśli masz bazę danych zakodowaną w UTF8, możesz:

=> UTWÓRZ TABELĘ foo (t TEKST);

=> WSTAWIĆ WARTOŚCI Foo (E '\ 377');

Teraz, jeśli KOPIUJESZ tabelę, nie możesz ponownie KOPIOWAĆ wynikowego pliku. Oznacza to, że twoje kopie zapasowe pg_dump nie będą mogły przywrócić. Jedynym sposobem na odzyskanie danych jest ponowne użycie tej wartości.

Na tym doskonałym blogu znajduje się dobry post na temat ogólnych problemów i sposobów ich rozwiązywania

Nie polecam ślepego uruchamiania iconv na zrzucie zwykłego tekstu, ponieważ może on konwertować prawidłowe znaki (np .: znaki chińskie) na niektóre inne znaki. Lepiej jest znaleźć niepoprawny znak UTF8, uruchamiając poniżej polecenia.

grep -naxv '.*' plain_text_dump.sql

a następnie uruchom iconv na danych. Sprawdź ten dokument zawiera szczegółowe wyjaśnienia krok po krok .

1
Nijil

Jest to prawdopodobne z domyślnym kodowaniem używanym w środowisku Unix/Linux. Aby sprawdzić, które kodowanie jest obecnie domyślnym, wykonaj następujące czynności:

$ echo $LANG
en_US

W tym przypadku wyraźnie widać, że nie jest to kodowanie UTF-8, na którym opiera się polecenie kopiowania.

Aby to naprawić, po prostu ustawiliśmy zmienną LANG w przykładzie na następującą:

$ export LANG=en_US.UTF-8

Uwaga: będzie dostępna tylko dla bieżącej sesji. Dodaj go do ~/.bashrc lub podobnego, aby był dostępny podczas uruchamiania każdej przyszłej sesji Shell.

odniesienie

1
arulraj.net

Odniosłem się do następującego linku, który dał mi wskazówki do ustalenia kodowania źródłowego, a następnie przekonwertowania go na pożądane kodowanie UTF-8. Linux Check and Change Encoding

$ file -bi cabot.sql
text/plain; charset=utf-16le
$ iconv -f utf-16le -t utf-8 -o converted.sql cabot.sql
$ file -bi converted.sql
text/plain; charset=utf-8
0
Biswajit Barman