Když klient MySQL komunikuje se serverem:
-
server přijímá jakýkoli text pouze jako řetězec bajtů; klient mu předem řekl, jak bude takový text zakódován.
-
pokud pak server musí uložit tento text do tabulky, musí jej překódovat do kódování příslušného sloupce (pokud se liší).
-
pokud chce klient následně takový text načíst, server jej musí překódovat do kódování očekávaného klientem.
Pokud jsou kódování použitá klientem v krocích 1 a 3 stejná (což je obvykle případ, zvláště když klientem je v obou případech stejná aplikace), pak často zůstává bez povšimnutí, pokud klient používá jiné kódování, než jaké uvedl. Předpokládejme například, že klient řekne MySQL, že bude používat latin1
, ale ve skutečnosti odesílá data v utf8
:
-
Řetězec
'Jazz–Man'
je odesláno na server v UTF-8 jako0x4a617a7ae280934d616e
. -
MySQL, které dekóduje tyto bajty ve Windows-1252, je chápe tak, že představují řetězec
'Jazz–Man'
. -
K uložení v
utf8
sloupec, MySQL překóduje řetězec na jeho kódování UTF-80x4a617a7ac3a2e282ace2809c4d616e
. To lze ověřit pomocíSELECT HEX(name) FROM lessons WHERE id=79510
. -
Když klient získá hodnotu, MySQL si myslí, že ji chce v
latin1
a tak překóduje na kódování Windows-12520x4a617a7ae280934d616e
. -
Když klient obdrží tyto bajty, dekóduje je jako UTF-8, a proto chápe řetězec jako
'Jazz–Man'
.
Závěr :klient si neuvědomuje, že je něco špatně. Problémy jsou detekovány pouze v případě, že jiný klient (ten, který neuvádí chybně své připojení UTF-8 jako latin1
) se pokusí použít tabulku. Ve vašem případě k tomu došlo, když mysqldump získal export dat; pomocí --default-character-set=latin1 --skip-set-charset
možnosti účinně donutily mysqldump chovat se stejně nefunkčním způsobem jako vaše aplikace, takže to skončilo se správně zakódovanými daty.
Chcete-li svůj problém v budoucnu vyřešit, musíte:
-
Nakonfigurujte svou aplikaci tak, aby správně nastavila svou znakovou sadu připojení k MySQL (např. set
encoding: utf8
vconfig/database.yml
pro kolejnice); -
Překódujte data ve své databázi, např.
UPDATE lessons SET name = BINARY CONVERT(name USING latin1)
(Všimněte si, že to musí být provedeno pro každý nesprávně kódovaný textový sloupec).
Všimněte si také, že pravděpodobně budete chtít provést tyto dvě akce atomicky, což může vyžadovat trochu přemýšlení.