Migrando bases de dados LATIN1 para UTF-8 com o PostgreSQL

6 Fev

Nos dias atuais é um padrão que todos os sites e servidores web rodem ao menos com UTF-8 como encoding default, entretanto pode-se encontrar casos onde ainda se roda LATIN1 ou até mesmo ASCII.

O caso que tratamos hoje é de um servidor Debian, versão 5.0.3 (lenny), que usava o encode LATIN1 quando instalado e configurado o Postgresql, e não me deixava criar uma base de dados UTF-8, gerando o seguinte erro:

debian:~# su postgres -c 'createdb teste3  -E UTF-8'
createdb: database creation failed: ERROR:  encoding UTF8 does not match server's locale en_US
DETAIL:  The server's LC_CTYPE setting requires encoding LATIN1.

Porque??

O Postgresql, quando roda pela primeira vez, cria um cluster usando o encode default do sistema, e após feito isso, não se pode alterar o encode do cluster. O cluster default é o main, em todas as intalações que eu vi.

No caso deste servidor o encode default (locales) era en_US, que para o Debian significa en_US.ISO-8859-1. Por default o Debian Lenny, nas minhas instalações do zero, usa en_US.UTF-8, então o servidor provavelmente deveria ser um antigo Debian Etch atualizado.

A solução

Depois de alguma pesquisa, descobri que, após configurar o encode do servidor para usar UTF-8, poderia criar um novo cluster que suportasse tal encode.

Vamos ao passo a passo da solução do problema.

  • Criando um novo cluster: Para criar um novo cluster no Debian, é bastante simples:
    debian:~# pg_createcluster 8.3 utf8_cluster
    Creating new cluster (configuration: /etc/postgresql/8.3/utf8_cluster, data: /var/lib/postgresql/8.3/utf8_cluster)...
    Moving configuration file /var/lib/postgresql/8.3/utf8_cluster/postgresql.conf to /etc/postgresql/8.3/utf8_cluster...
    Moving configuration file /var/lib/postgresql/8.3/utf8_cluster/pg_hba.conf to /etc/postgresql/8.3/utf8_cluster...
    Moving configuration file /var/lib/postgresql/8.3/utf8_cluster/pg_ident.conf to /etc/postgresql/8.3/utf8_cluster...
    Configuring postgresql.conf to use port 5433...
    
    debian:~# /etc/init.d/postgresql-8.3 restart
    

    O cluster vai rodar na primeira porta livre que achar depois da 5432, a não ser que você especifique. Para ter efeito, reinicia-se o Postgresql.

  • Criando o usuário: Agora crie o usuário da base de dados, recomendo o mesmo nome e senha além de editar sua autenticação para trust no pg_hba.conf do seu cluster:
    debian:~# su postgres -c "createuser -P pyuser -p 5433"
    Enter password for new role:
    Enter it again:
    Shall the new role be a superuser? (y/n) n
    Shall the new role be allowed to create databases? (y/n) n
    Shall the new role be allowed to create more new roles? (y/n) n
    
  • Migrando as bases: Agora você deve migrar as bases de dados. Primeiro crie ela e depois faça um dump seguido de um psql, direto na linha de comando. Siga o exemplo:
    debian:~# su postgres -c "createdb teste3 -e -p 5433 -O pyuser"
    CREATE DATABASE teste3 OWNER pyuser;
    

    Agora liste a base de dados:

    debian:~# su postgres -c "psql -l -p 5433"
            List of databases
       Name    |  Owner   | Encoding
    -----------+----------+----------
     postgres  | postgres | UTF8
     template0 | postgres | UTF8
     template1 | postgres | UTF8	
     teste3    | pyuser   | UTF8
    (4 rows)
    

    Após criar a base de dados, então faremos a população dela, atenção quanto as portas:

    debian:~# pg_dump -U pyuser teste3 | psql -U pyuser -p 5433 teste3
  • Configurando sua aplicação: Esta é a parte mais simples, apenas altere a porta da sua aplicação para a porta do novo cluster.

Repita os passos da criação da base de dados para cada base que precisa ser movida, e pronto, tudo funcionando agora com suporte a UTF-8.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

4 Responses to “Migrando bases de dados LATIN1 para UTF-8 com o PostgreSQL”

  1. Eberson dezembro 20, 2010 at %H:%M 10Mon, 20 Dec 2010 22:52:08 +000008. #

    Cara Muito boa sua dica, testei e cria o cluster 100%, mas o meu caso é assim so estou arrumando um servidor de dados em lenny o programador nao esta aqui portanto nao consiogo mudar a porta da aplicação 🙂 será que nao tem como mudar a configuração default do postgre pra usar a codificação utf8??? Se vc puder dar uma dica agradeceria…

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    • Felipe 'chronos' Prenholato dezembro 21, 2010 at %H:%M 10Tue, 21 Dec 2010 10:22:36 +000036. #

      Oi Eberson, desculpa a demora para responder. Se eu não me engano (não to com um postgres agora para checar, pois mudei de trabalho) cada cluster tem um arquivo postgresql.conf. Você indo nestes arquivos e editando a configuração port, e depois restartando o postgresql, deve resolver o seu problema.

      VA:F [1.9.22_1171]
      Rating: 0.0/5 (0 votes cast)
  2. Marc PC1MH novembro 19, 2010 at %H:%M 01Fri, 19 Nov 2010 13:50:33 +000033. #

    Hi,
    Thanks for the help.
    I had the same problem and solved it in a slightly different way. I’d like to share with you all the following:

    If the database is in LATIN1 and the data is in UTF-8 then:

    createdb: database creation failed: ERROR: encoding UTF8 does not match server’s locale en_US
    DETAIL: The server’s LC_CTYPE setting requires encoding LATIN1.

    – purge postgres (apt-get purge postgres postgres-common)
    – check out /etc/locale.gen and add: en_US.UTF-8 UTF-8
    – Then run as root: locale-gen
    – Reinstall postgres and now all databases are in UTF-8

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
  3. marc março 10, 2010 at %H:%M 07Wed, 10 Mar 2010 07:33:09 +000009. #

    Hello! Your post (Moving PostgreSQL databases from LATIN1 to UTF-8 – Chronosbox) does so well that I would like to translate it into French, publish on my french blog and link to you. You have something against it? Regards

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)

Leave a Reply