Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Dane utf8 wyglądają dobrze w mysql, ale są uszkodzone w szynach

Gdy klient MySQL wchodzi w interakcję z serwerem:

  1. serwer odbiera dowolny tekst jedynie jako ciąg bajtów; klient wcześniej powiedział mu, jak taki tekst będzie zakodowany.

  2. jeśli serwer musi następnie przechowywać ten tekst w tabeli, musi go transkodować do kodowania odpowiedniej kolumny (jeśli jest inna).

  3. jeśli klient chce później pobrać taki tekst, serwer musi go transkodować do kodowania oczekiwanego przez klienta.

Jeśli kodowania używane przez klienta w krokach 1 i 3 są takie same (co zwykle ma miejsce, zwłaszcza gdy klient w obu przypadkach jest tą samą aplikacją), często pozostaje niezauważone, jeśli klient używa kodowania innego niż to, o którym mówi. Załóżmy na przykład, że klient mówi MySQL, że użyje latin1 , ale faktycznie wysyła dane w utf8 :

  • Ciąg 'Jazz–Man' jest wysyłany na serwer w UTF-8 jako 0x4a617a7ae280934d616e .

  • MySQL, dekodując te bajty w Windows-1252, rozumie, że reprezentują one ciąg 'Jazz–Man' .

  • Aby przechowywać w utf8 kolumna, MySQL transkoduje ciąg do jego kodowania UTF-8 0x4a617a7ac3a2e282ace2809c4d616e . Można to zweryfikować za pomocą SELECT HEX(name) FROM lessons WHERE id=79510 .

  • Kiedy klient pobiera wartość, MySQL myśli, że chce ją w latin1 a więc transkoduje do kodowania Windows-1252 0x4a617a7ae280934d616e .

  • Gdy klient otrzymuje te bajty, dekoduje je jako UTF-8 i dlatego rozumie, że ciąg to 'Jazz–Man' .

Wniosek :klient nie zdaje sobie sprawy, że coś jest nie tak. Problemy są wykrywane tylko wtedy, gdy inny klient (taki, który nie podaje błędnie swojego połączenia UTF-8 jako latin1 ) próbuje użyć tabeli. W Twoim przypadku miało to miejsce, gdy mysqldump uzyskał eksport danych; używając --default-character-set=latin1 --skip-set-charset opcje skutecznie zmusiły mysqldump do zachowywania się w ten sam sposób, co Twoja aplikacja, więc w efekcie uzyskano poprawnie zakodowane dane.

Aby rozwiązać problem w przyszłości, musisz:

  1. Skonfiguruj swoją aplikację tak, aby poprawnie ustawiała zestaw znaków połączenia MySQL (np. ustaw encoding: utf8 w config/database.yml dla szyn);

  2. Przekoduj dane w Twojej bazie, np. UPDATE lessons SET name = BINARY CONVERT(name USING latin1) (zauważ, że należy to zrobić dla każdej błędnie zakodowanej kolumny tekstu).

Pamiętaj też, że prawdopodobnie będziesz chciał wykonać te dwie czynności atomowo, co może wymagać trochę przemyślenia.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. przenoszenie bazy kodeignitera do innej tabeli

  2. Foreach MySQL/PHP nadal wyświetla się tylko jako pierwszy w bazie danych

  3. Uciekanie ciągów za pomocą pythona mysql.connector

  4. Mysql, przekształć dane z długich / wysokich na szerokie

  5. Dynamiczny link MySQL do pobrania właściwego wiersza