Proč v MySQL nepoužívat UTF-8

UTF-8 ukládá znaky jako vícebajtové (1-4 bajty), tedy znak může mít klidně 4 bajty. Bohužel, když při komunikaci s MySQL nastavíte kódování na UTF-8, ve skutečnosti se o plnohodnotné UTF-8 nejedná. Článek už mám nějakou dobu v šuplíku, dnešní hrabání se v kódu mě donutilo jej zveřejnit. 

Podle dokumentace je utf-8 alias utf8mb3! To znamená, že interní interpretace UTF-8 má pouze tři bajty. Většinu času asi nenarazíte na problém, protože do utf8mb3 se vejde celá BMP ale narazíte, když uživatel zadá znaky, které v BMP nejsou jako například populární emoji. Při pokusu o uložení řetězce s takovým znakem, dostanete chybu podobnou této:

Warning | 1366 | Incorrect string value: ‘\xF0\x9D\x8C\x86’ for column ‘description’ at row 1

Nemožnost uložit emoji bohužel není jediný problém. Špatně nastavené kódování může útočníkovi zjednodušit práci při pokusu o napadení vaší aplikace – slidy z prezentace.

Nikdy při komunikaci s MySQL nebo pro vytváření tabulek/sloupců nepoužívejte utf-8! Vždy používejte utf8mb4! Utf8mb4 je v MySQL od verze 5.5.3, která vyšla na začátku roku 2010. Se starší verzí se snad už dneska nesetkáte (a rozhodně se ani setkat nechcete).

Převod všech tabulek a sloupců na utf8mb4 resp. utf8mb4_unicoce_ci lze udělat hromadně použitím údajů z tabulky information_schema.columns, kde je uložena informace o všech sloupcích. Po převedení je nejlepší nastavit správné kódování rovnou v konfiguraci MySQL, kde se stále používá jako výchozí utf8 :-(.

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

kde character-set-client-handshake = false znamená, že má ignorovat požadované kódování vyžádané klientem. Asi bych raději nechal na true a po převedení všech tabulek/sloupců teprve nastavil na false (a znovu ověřil jestli se něco nerozbilo).

UPDATE 9.2.2019 Od verze MySQL 8 utf-8 znamená utf8mb4. Hurá!

Zdroje:

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *