È meglio usare il set di caratteri utf8mb4
con le regole di confronto utf8mb4_unicode_ci
.
Il set di caratteri utf8
supporta solo una piccola quantità di punti di codice UTF-8, circa il 6% dei possibili caratteri. utf8
supporta solo il piano multilingue di base (BMP). Ci sono altri 16 aerei. Ogni piano contiene 65.536 caratteri. utf8mb4
supporta tutti e 17 gli aerei.
MySQL tronca i caratteri UTF-8 a 4 byte con conseguente danneggiamento dei dati.
Il utf8mb4
set 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 Barracuda
da Antelope
, potrebbe richiedere il riavvio del servizio MySQL più di una volta. innodb_file_format_max
non cambia fino a dopo il servizio MySQL è stato riavviato a: innodb_file_format = barracuda
.
MySQL utilizza il vecchio Antelope
formato di file InnoDB. Barracuda
supporta 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=DYNAMIC
viene rimosso dall'istruzione CREATE.
NOTA: la modifica dell'indice per limitare i primi 128 caratteri su contact
elimina 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 INSERT
affermazione 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 last
colonna:
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: