Como resolver erros de cópia de sequência de bytes inválidos UTF8 em uma restauração, quando o banco de dados de origem é codificado em UTF8?

17

Foi-me dada a tarefa de migrar um banco de dados PostgreSQL 8.2.x para outro servidor. Para fazer isso, estou usando o pgAdmin 1.12.2 (a propósito, no Ubuntu 11.04) e usando o Backup and Restore usando o formato custom / compress (.backup) e a codificação UTF8.

O banco de dados original está em UTF8, assim:

-- Database: favela

-- DROP DATABASE favela;

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

Estou criando esse banco de dados exatamente assim no servidor de destino. Mas quando eu restauro o banco de dados a partir do arquivo .backup usando a opção Restaurar, ele apresenta alguns desses erros:

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

Quando eu checo qual registro acionou esse erro, alguns campos de texto de texto possuem caracteres diacríticos como ç (usado em português, por exemplo, "caça"), e quando eu os removo manualmente do texto nos registros, o erro passa para o próximo registro que os possui - pois quando a cópia apresenta um erro, ela para de inserir dados nesta tabela. E não quero substituí-los manualmente, um por um, para fazer isso.

Mas é meio estranho, porque com o UTF8 não deveria haver esse tipo de problema, certo?

Eu não sei como eles chegaram lá em primeiro lugar. Estou apenas migrando o banco de dados e suponho que, de alguma forma, o banco de dados estivesse no LATIN1 e, em seguida, foi incorretamente alterado para UTF8.

Existe alguma maneira de verificar se uma tabela / banco de dados possui sequências UTF8 inválidas? Ou alguma maneira de impor / reconverter esses caracteres no UFT8, para não ter problemas ao executar a restauração?

Desde já, obrigado.

pedrosanta
fonte

Respostas:

8

Procurando na internet, vi que esse é um problema bastante comum. A solução comum é usar o dump de formato de texto sem formatação e alimentá-lo através do iconv para corrigir a codificação.

Aqui está mais informações sobre isso.

Richard
fonte
use iconv para converter para UTF-32 descartando símbolos inválidos e, em seguida, retornando para UTF-8, uma conversão de UTF-8 para UTF-8 não detectará todos os pontos de código incorretos. (por exemplo, substitutos órfãos)
Jasen 25/05
7

"Eu não sei como eles chegaram lá em primeiro lugar"

Poderia ter acontecido como descrito aqui - embora isso gere um erro na 8.4:

Se você criar uma tabela com qualquer tipo de texto (por exemplo, texto, varchar (10) etc.), poderá inserir uma sequência de bytes inválida nesse campo usando escapes octais.

Por exemplo, se você tiver um banco de dados codificado em UTF8, poderá:

=> CRIAR TABELA foo (t TEXTO);

=> INSERIR EM QUATRO VALORES (E '\ 377');

Agora, se você copiar a tabela, não poderá copiar novamente o arquivo resultante. Isso significa que seus backups do pg_dump não poderão ser restaurados. A única maneira de recuperar seus dados é recuperar esse valor.

Há um bom post neste excelente blog sobre os problemas gerais e algumas maneiras de lidar com eles

Jack Douglas
fonte
1

Provavelmente com a codificação padrão usada no seu ambiente Unix / Linux. Para verificar qual codificação é atualmente a padrão, execute o seguinte:

$ echo $LANG
en_US

Nesse caso, podemos ver claramente que não é uma codificação UTF-8, aquela em que o comando copy se baseia.

Então, para corrigir isso, basta definir a variável LANG no exemplo para o seguinte:

$ export LANG=en_US.UTF-8

Nota: Isso estará disponível apenas para a sessão atual. Adicione-o a ~ / .bashrc ou similar para disponibilizá-lo na inicialização de qualquer futura sessão do shell.

Referência

arulraj.net
fonte
1

Não recomendo executar o iconv às cegas no despejo de texto sem formatação, pois ele pode converter caracteres válidos (por exemplo: caracteres chineses) em outros caracteres. É melhor encontrar o caractere UTF8 inválido executando o comando abaixo.

grep -naxv '.*' plain_text_dump.sql

e, em seguida, execute iconv nos dados específicos. Consulte este documento para obter explicações detalhadas passo a passo .

Nijil
fonte