Desenvolvimento e bases de dados

MySQL 8, mudança da codificação de carateres de latin1 para utf8mb4

Revisto a 3 min de leitura codificação MySQL

Os valores predefinidos do fabricante passaram de latin1 no MySQL 5.7 para utf8mb4 no MySQL 8. A configuração de um servidor pode ser diferente. Atualizar o MySQL não converte automaticamente todas as tabelas existentes; também conta o conjunto de carateres que a aplicação negoceia ao ligar-se.

Esta mudança não costuma causar problemas, uma vez que as aplicações definem o charset a utilizar na camada de ligação ao MySQL. No entanto, em aplicações muito antigas ou desenvolvimentos próprios isso pode não acontecer e, por isso, depois da mudança os dados podem aparecer no ecrã com carateres "estranhos".

Antes de alterar seja o que for, verifique a codificação real das tabelas e a configuração que a aplicação espera. Forçar latin1 só é correto quando o projeto e os seus dados continuam a utilizar esse conjunto de carateres; não serve para reparar dados já convertidos ou guardados com uma codificação incorreta.

Verificar onde aparece o problema

Reveja uma amostra conhecida de texto na base de dados e no site, sem a voltar a guardar por enquanto. Se o phpMyAdmin a mostra corretamente e a sua aplicação não, verifique a ligação e a codificação da resposta HTML. Se já estiver mal guardada, alterar a ligação não a vai reparar. Trabalhe sobre uma cópia antes de tentar converter dados.

A partir da mesma ligação que a aplicação utiliza, pode consultar:

SELECT @@character_set_client, @@character_set_connection,
       @@character_set_results, @@collation_connection;

Executá-lo a partir do phpMyAdmin mostra a sessão do phpMyAdmin, não a da sua aplicação. Reveja também o conjunto de carateres das colunas afetadas; pode ser diferente do predefinido da tabela.

Manter temporariamente uma aplicação em latin1

Configure o conjunto de carateres no próprio conector. Com MySQLi:

mysqli_set_charset($connection, 'latin1');

Com PDO, inclua-o no DSN ao criar a ligação:

$dsn = 'mysql:host=localhost;dbname=BASE_DE_DATOS;charset=latin1';
$connection = new PDO($dsn, $user, $password);

Não utilize mysql_select_db() nem mysql_query(): pertencem à antiga extensão mysql, removida do PHP desde a versão 7. Também não é recomendável enviar SET NAMES manualmente com MySQLi, porque mysqli_set_charset() mantém sincronizado o conjunto de carateres que o cliente utiliza ao escapar cadeias.

Preparar a atualização

Se o projeto suportar Unicode completo, planeie a conversão para utf8mb4 com um clone, uma cópia recuperável e testes de leitura e escrita. Não mude para latin1 uma aplicação que já utiliza corretamente utf8mb4.

Também lhe pode ser útil

Algo não bate certo ou mudou? Diga-nos e revemos.