MySQL e MariaDB utf8 e utf8mb4 encoding

Universalmente o conjunto de caracteres chamado utf8 usa o máximo de três bytes por caractere, limitado apenas a caracteres BMP, ou seja, Basic Multilingual Plane.

A partir do MySQL 5.5.3 e MariaDB 10.1.0, o conjunto de utf8mb4 utiliza no máximo quatro bytes por caractere (um byte a mais na codificação), suportando assim os famosos caracteres suplementares (do nosso idioma), e também:
😇 🤣 😎 😰 🤘🏽 ⚽️ 🎲 🛠 🎈 ☂️ 🔑 🦋 ❤️ ♻️ 🇧🇷 🍿 🚧 🚦 🌠 ⏰ 🍺 💊 💯 ☘️ 💋 e etc…

Então, entende-se utf8mb4 como 4-Byte de Codificação Unicode UTF-8.

  • Para um caractere BMP, utf8 e utf8mb4 possuem características de armazenamento idênticas, tais como: o mesmos valores de código, a mesma codificação e o mesmo comprimento.
  • Para um caractere suplementar, o utf8 não consegue armazenar todos os caracteres, enquanto o utf8mb4 requer exatamente quatro bytes para armazená-lo. Isso porque não pode armazena-los em sua totalidade, agora caso você não utilize caracteres suplementares nas colunas utf8, não precisa se preocupar com a conversão de caracteres ou perda de dados ao atualizar sua base em utf8 a partir de versões legadas do MySQL.

Tecnicamente, o utf8mb4 é um utf8mb4 de utf8, portanto, para uma operação como a seguinte concatenação, o resultado tem o conjunto de utf8mb4 e o agrupamento de utf8mb4_col:

SELECT CONCAT(utf8_col, utf8mb4_col);

Um pouco mais de história

Antigamente as linguagens de programação suportavam apenas a codificação ASCII que define 128 símbolos. Essa codificação é excelente para o inglês, produzindo textos bem compactos onde cada letra utiliza apenas um byte para armazenamento.

Com o crescimento da internet e um mundo cada vez mais globalizado, rapidamente começaram a surgir problemas, como as pessoas do Brasil não poderem usar acentos em suas palavras.

Foi daí que começaram iniciativas para se criar uma codificação que reunisse todos os símbolos usados pelo mundo inteiro.

O ASCII só define 128 símbolos, o que faz com que o primeiro bit de todo byte seja zero nessa codificação. O padrão UTF-8 aproveitou isso e definiu os primeiros 128 símbolos exatamente iguais ao ASCII. Quando um caractere que não está presente nesse padrão é necessário, o UTF-8 coloca o valor do primeiro bit como 1 e define códigos que dizem se o caractere vai ter 1, 2, 3 ou 4 bytes.

Portanto um programa que utilize UTF-8 terá compatibilidade total com qualquer texto em ASCII.

Voltando ao MySQL e MariaDB

O problema é que o MySQL não aderiu completamente ao padrão UTF-8. O time de desenvolvimento implementou apenas símbolos de até 3 bytes, inviabilizando o restante.

E como isso afetou o MariaDB? Simples, o time que desenvolvia e mantinha MySQL é o responsável pelo desenvolvimento do MariaDB.

O que se declara no MySQL/MariaDB como utf8 na verdade não o é, e sim apenas parte dele

Para consertar este erro, a partir da versão MySQL 5.5.+ foi implementado o padrão completo (indo de 1 até 4 bytes) e como a equipe já havia usado o nome utf8, optou-se por chamar a nova implementação de utf8mb4.

Resumindo o utf8 do MySQL não é UTF-8, e, o utf8mb4 sim segue totalmente o padrão UTF-8.

Abraços!
Thiago Pereira Rosa.