É melhor usar o conjunto de caracteres utf8mb4
com o agrupamento utf8mb4_unicode_ci
.
O conjunto de caracteres, utf8
suporta apenas uma pequena quantidade de pontos de código UTF-8, cerca de 6% dos caracteres possíveis. utf8
suporta apenas o plano multilíngue básico (BMP). Existem outros 16 aviões. Cada plano contém 65.536 caracteres. utf8mb4
suporta todos os 17 aviões.
O MySQL truncará caracteres UTF-8 de 4 bytes, resultando em dados corrompidos.
O utf8mb4
conjunto de caracteres foi introduzido no MySQL 5.5.3 em 24-03-2010.
Algumas das alterações necessárias para usar o novo conjunto de caracteres não são triviais:
- Podem ser necessárias alterações no adaptador do banco de dados do aplicativo.
- Alterações precisarão ser feitas no my.cnf, incluindo a configuração do conjunto de caracteres, o agrupamento e a alternância de innodb_file_format para Barracuda
- As instruções SQL CREATE podem precisar incluir:
ROW_FORMAT=DYNAMIC
- DINÂMICO é necessário para índices em VARCHAR (192) e maiores.
NOTA: Mudar para Barracuda
de Antelope
, pode exigir a reinicialização do serviço MySQL mais de uma vez. innodb_file_format_max
não muda até que o serviço MySQL foi reiniciado para: innodb_file_format = barracuda
.
O MySQL usa o antigo Antelope
formato de arquivo InnoDB. Barracuda
suporta formatos de linha dinâmicos, que você precisará se não desejar obter os erros do SQL para criar índices e chaves após mudar para o conjunto de caracteres:utf8mb4
- # 1709 - Tamanho da coluna de índice muito grande. O tamanho máximo da coluna é 767 bytes.
- # 1071 - A chave especificada era muito longa; o comprimento máximo da chave é 767 bytes
O cenário a seguir foi testado no MySQL 5.6.17: Por padrão, o MySQL está configurado assim:
SHOW VARIABLES;
innodb_large_prefix = OFF
innodb_file_format = Antelope
Pare o serviço MySQL e adicione as opções ao my.cnf existente:
[client]
default-character-set= utf8mb4
[mysqld]
explicit_defaults_for_timestamp = true
innodb_large_prefix = true
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_per_table = true
# Character collation
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
Instrução SQL CREATE de exemplo:
CREATE TABLE Contacts (
id INT AUTO_INCREMENT NOT NULL,
ownerId INT DEFAULT NULL,
created timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
contact VARCHAR(640) NOT NULL,
prefix VARCHAR(128) NOT NULL,
first VARCHAR(128) NOT NULL,
middle VARCHAR(128) NOT NULL,
last VARCHAR(128) NOT NULL,
suffix VARCHAR(128) NOT NULL,
notes MEDIUMTEXT NOT NULL,
INDEX IDX_CA367725E05EFD25 (ownerId),
INDEX created (created),
INDEX modified_idx (modified),
INDEX contact_idx (contact),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT=DYNAMIC;
- Você pode ver o erro # 1709 gerado para
INDEX contact_idx (contact)
se ROW_FORMAT=DYNAMIC
for removido da instrução CREATE.
NOTA: Alterar o índice para limitar os primeiros 128 caracteres contact
elimina o requisito de usar o Barracuda comROW_FORMAT=DYNAMIC
INDEX contact_idx (contact(128)),
Observe também: quando diz que o tamanho do campo é VARCHAR(128)
, isso não é 128 bytes. Você pode usar caracteres de 128, 4 bytes ou 128, caracteres de 1 byte.
Esta INSERT
declaração deve conter o caractere 'poo' de 4 bytes na linha 2:
INSERT INTO `Contacts` (`id`, `ownerId`, `created`, `modified`, `contact`, `prefix`, `first`, `middle`, `last`, `suffix`, `notes`) VALUES
(1, NULL, '0000-00-00 00:00:00', '2014-08-25 03:00:36', '1234567890', '12345678901234567890', '1234567890123456789012345678901234567890', '1234567890123456789012345678901234567890', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678', '', ''),
(2, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', ''),
(3, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '123💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', '');
Você pode ver a quantidade de espaço usada pela last
coluna:
mysql> SELECT BIT_LENGTH(`last`), CHAR_LENGTH(`last`) FROM `Contacts`;
+--------------------+---------------------+
| BIT_LENGTH(`last`) | CHAR_LENGTH(`last`) |
+--------------------+---------------------+
| 1024 | 128 | -- All characters are ASCII
| 4096 | 128 | -- All characters are 4 bytes
| 4024 | 128 | -- 3 characters are ASCII, 125 are 4 bytes
+--------------------+---------------------+
No seu adaptador de banco de dados, convém definir o conjunto de caracteres e agrupamento para sua conexão:
SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'
No PHP, isso seria definido para: \PDO::MYSQL_ATTR_INIT_COMMAND
Referências: