Najlepiej używać zestawu znaków utf8mb4
z zestawieniem utf8mb4_unicode_ci
.
Zestaw znaków utf8
obsługuje tylko niewielką liczbę punktów kodowych UTF-8, około 6% możliwych znaków. utf8
obsługuje tylko Basic Multilingual Plane (BMP). Jest 16 innych samolotów. Każdy samolot zawiera 65 536 znaków. utf8mb4
obsługuje wszystkie 17 samolotów.
MySQL skróci 4-bajtowe znaki UTF-8, co spowoduje uszkodzenie danych.
Zestaw utf8mb4
znaków został wprowadzony w MySQL 5.5.3 w dniu 24.03.2010.
Niektóre z wymaganych zmian w celu użycia nowego zestawu znaków nie są trywialne:
- Konieczne może być wprowadzenie zmian w adapterze bazy danych aplikacji.
- Konieczne będzie wprowadzenie zmian w pliku my.cnf, w tym ustawienie zestawu znaków, sortowanie i przełączanie pliku format_pliku_wodb na Barracuda
- Instrukcje SQL CREATE mogą wymagać:
ROW_FORMAT=DYNAMIC
- DYNAMIC jest wymagany dla indeksów w VARCHAR (192) i większych.
UWAGA: Przełączenie Barracuda
z Antelope
, może wymagać ponownego uruchomienia usługi MySQL więcej niż raz. innodb_file_format_max
nie zmienia się aż po serwis MySQL została wznowiona do: innodb_file_format = barracuda
.
MySQL używa starego Antelope
formatu pliku InnoDB. Barracuda
obsługuje dynamiczne formaty wierszy, które będą potrzebne, jeśli nie chcesz trafić do błędów SQL podczas tworzenia indeksów i kluczy po przejściu na zestaw znaków:utf8mb4
- # 1709 - Rozmiar kolumny indeksu jest zbyt duży. Maksymalny rozmiar kolumny to 767 bajtów.
- # 1071 - Określony klucz był za długi; maksymalna długość klucza wynosi 767 bajtów
Poniższy scenariusz został przetestowany na MySQL 5.6.17: Domyślnie MySQL jest skonfigurowany w następujący sposób:
SHOW VARIABLES;
innodb_large_prefix = OFF
innodb_file_format = Antelope
Zatrzymaj usługę MySQL i dodaj opcje do istniejącego pliku my.cnf:
[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
Przykładowa instrukcja 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;
- Możesz zobaczyć błąd # 1709 wygenerowany,
INDEX contact_idx (contact)
jeśli ROW_FORMAT=DYNAMIC
został usunięty z instrukcji CREATE.
UWAGA: Zmiana indeksu na ograniczenie do pierwszych 128 znaków contact
eliminuje konieczność używania Barracuda zROW_FORMAT=DYNAMIC
INDEX contact_idx (contact(128)),
Uwaga: gdy mówi VARCHAR(128)
, że pole ma rozmiar , to nie jest 128 bajtów. Możesz użyć 128, 4-bajtowych znaków lub 128, 1-bajtowych znaków.
Ta INSERT
instrukcja powinna zawierać 4-bajtowy znak „poo” w 2 rzędzie:
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💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', '');
Możesz zobaczyć ilość miejsca zajmowanego przez last
kolumnę:
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
+--------------------+---------------------+
W adapterze bazy danych może być konieczne ustawienie zestawu znaków i sortowania dla połączenia:
SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'
W PHP byłoby to ustawione dla: \PDO::MYSQL_ATTR_INIT_COMMAND
Bibliografia: