È meglio usare il set di caratteri utf8mb4con le regole di confronto utf8mb4_unicode_ci.
Il set di caratteri utf8supporta solo una piccola quantità di punti di codice UTF-8, circa il 6% dei possibili caratteri. utf8supporta solo il piano multilingue di base (BMP). Ci sono altri 16 aerei. Ogni piano contiene 65.536 caratteri. utf8mb4supporta tutti e 17 gli aerei.
MySQL tronca i caratteri UTF-8 a 4 byte con conseguente danneggiamento dei dati.
Il utf8mb4set di caratteri è stato introdotto in MySQL 5.5.3 il 24-03-2010.
Alcune delle modifiche necessarie per utilizzare il nuovo set di caratteri non sono banali:
- Potrebbe essere necessario apportare modifiche nell'adattatore del database dell'applicazione.
- Sarà necessario apportare modifiche a my.cnf, tra cui l'impostazione del set di caratteri, le regole di confronto e il passaggio innodb_file_format su Barracuda
- Le istruzioni SQL CREATE potrebbero dover includere:
ROW_FORMAT=DYNAMIC
- DYNAMIC è richiesto per gli indici su VARCHAR (192) e superiori.
NOTA: il passaggio a Barracudada Antelope, potrebbe richiedere il riavvio del servizio MySQL più di una volta. innodb_file_format_maxnon cambia fino a dopo il servizio MySQL è stato riavviato a: innodb_file_format = barracuda.
MySQL utilizza il vecchio Antelopeformato di file InnoDB. Barracudasupporta formati di riga dinamici, che saranno necessari se non si desidera colpire gli errori SQL per la creazione di indici e chiavi dopo il passaggio al set di caratteri:utf8mb4
- # 1709 - Dimensione della colonna dell'indice troppo grande. La dimensione massima della colonna è 767 byte.
- # 1071 - La chiave specificata era troppo lunga; la lunghezza massima della chiave è 767 byte
Il seguente scenario è stato testato su MySQL 5.6.17: Per impostazione predefinita, MySQL è configurato in questo modo:
SHOW VARIABLES;
innodb_large_prefix = OFF
innodb_file_format = Antelope
Arresta il tuo servizio MySQL e aggiungi le opzioni al tuo my.cnf esistente:
[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
Esempio di istruzione SQL CREATE:
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;
- È possibile visualizzare l'errore # 1709 generato per
INDEX contact_idx (contact)se ROW_FORMAT=DYNAMICviene rimosso dall'istruzione CREATE.
NOTA: la modifica dell'indice per limitare i primi 128 caratteri su contactelimina la necessità di utilizzare Barracuda conROW_FORMAT=DYNAMIC
INDEX contact_idx (contact(128)),
Nota anche: quando dice che la dimensione del campo è VARCHAR(128), non è di 128 byte. È possibile utilizzare 128 caratteri a 4 byte o 128 caratteri a 1 byte.
Questa INSERTaffermazione dovrebbe contenere il carattere 'cacca' a 4 byte nella riga 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💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', '');
Puoi vedere la quantità di spazio utilizzata dalla lastcolonna:
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
+--------------------+---------------------+
Nell'adattatore del database, potresti voler impostare il set di caratteri e le regole di confronto per la tua connessione:
SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'
In PHP, questo sarebbe impostato per: \PDO::MYSQL_ATTR_INIT_COMMAND
Riferimenti: