Mysql
 sql >> база данни >  >> RDS >> Mysql

utf8 данните изглеждат добре в mysql, но са повредени в релсите

Когато MySQL клиент взаимодейства със сървъра:

  1. сървърът получава всеки текст просто като низ от байтове; клиентът ще му е казал предварително как ще бъде кодиран такъв текст.

  2. ако след това сървърът трябва да съхрани този текст в таблица, той трябва да го прекодира към кодирането на съответната колона (ако е различно).

  3. ако клиентът впоследствие иска да извлече такъв текст, сървърът трябва да го транскодира до очакваното от клиента кодиране.

Ако кодировките, използвани от клиента в стъпки 1 и 3, са едни и същи (което обикновено се случва, особено когато клиентът и в двата случая е едно и също приложение), тогава често остава незабелязано, ако клиентът използва кодиране, различно от това, което е казал, че ще използва. Да предположим например, че клиентът казва на MySQL, че ще използва latin1 , но всъщност изпраща данни в utf8 :

  • Низът 'Jazz–Man' се изпраща до сървъра в UTF-8 като 0x4a617a7ae280934d616e .

  • MySQL, декодирайки тези байтове в Windows-1252, ги разбира като представляващи низа 'Jazz–Man' .

  • За съхраняване в utf8 колона, MySQL прекодира низа към неговото UTF-8 кодиране 0x4a617a7ac3a2e282ace2809c4d616e . Това може да се провери с помощта на SELECT HEX(name) FROM lessons WHERE id=79510 .

  • Когато клиентът извлече стойността, MySQL смята, че я иска на latin1 и така прекодира към Windows-1252 кодиране 0x4a617a7ae280934d616e .

  • Когато клиентът получи тези байтове, той ги декодира като UTF-8 и следователно разбира низа като 'Jazz–Man' .

Заключение :клиентът не осъзнава, че нещо не е наред. Проблеми се откриват само когато е различен клиент (този, който не представя погрешно своята UTF-8 връзка като latin1 ) се опитва да използва таблицата. Във вашия случай това се случи, когато mysqldump получи експортиране на данните; използвайки --default-character-set=latin1 --skip-set-charset опциите ефективно принудиха mysqldump да се държи по същия счупен начин като вашето приложение, така че в крайна сметка се оказа с правилно кодирани данни.

За да коригирате проблема си в бъдеще, трябва:

  1. Конфигурирайте приложението си така, че да задава правилно своя набор от символи за свързване към MySQL (напр. задайте encoding: utf8 в config/database.yml за Rails);

  2. Прекодирайте данните във вашата база данни, напр. UPDATE lessons SET name = BINARY CONVERT(name USING latin1) (обърнете внимание, че това трябва да се направи за всяка неправилно кодирана текстова колона).

Също така имайте предвид, че вероятно ще искате да изпълните тези две действия атомарно, което може да изисква известно обмисляне.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Хибернация, изпращане на извънземни заявки към базата данни

  2. Изключване на единични кавички в PHP при вмъкване в MySQL

  3. MYSQL/PHP намира най-често срещания елемент, свързан с даден елемент

  4. MySQL добавя низ

  5. Как мога да открия излишни редове в таблицата?