sql >> Databáze >  >> RDS >> Mysql

Data utf8 vypadají v mysql dobře, ale jsou rozbitá v kolejích

Když klient MySQL komunikuje se serverem:

  1. server přijímá jakýkoli text pouze jako řetězec bajtů; klient mu předem řekl, jak bude takový text zakódován.

  2. 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ší).

  3. 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 jako 0x4a617a7ae280934d616e .

  • 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-8 0x4a617a7ac3a2e282ace2809c4d616e . 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-1252 0x4a617a7ae280934d616e .

  • 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:

  1. Nakonfigurujte svou aplikaci tak, aby správně nastavila svou znakovou sadu připojení k MySQL (např. set encoding: utf8 v config/database.yml pro kolejnice);

  2. 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í.



  1. html ztrojnásobil svou velikost tím, že po dotazu mysql vrátil prázdné značky | jak řešit - laravel

  2. reverzní inženýrství databáze mysql k vytvoření aplikace django

  3. Použití více schémat PostgreSQL s modely Rails

  4. Vyskakovací okna Map Google uvnitř nic nezobrazují