Ketika klien MySQL berinteraksi dengan server:
-
server menerima teks apa pun hanya sebagai string byte; klien sebelumnya akan memberitahunya bagaimana teks tersebut akan dikodekan.
-
jika server kemudian harus menyimpan teks itu dalam sebuah tabel, itu harus mentranskodekannya ke pengkodean kolom yang relevan (jika berbeda).
-
jika klien kemudian ingin mengambil teks tersebut, server harus mentranskodekannya ke pengkodean yang diharapkan oleh klien.
Jika penyandian yang digunakan oleh klien pada langkah 1 dan 3 sama (yang biasanya terjadi, terutama ketika klien dalam kedua kasus adalah aplikasi yang sama), maka sering kali tidak diperhatikan jika klien menggunakan pengkodean selain yang dikatakannya. Misalnya, klien memberi tahu MySQL bahwa ia akan menggunakan latin1
, tetapi sebenarnya mengirimkan data dalam utf8
:
-
String
'Jazz–Man'
dikirim ke server dalam UTF-8 sebagai0x4a617a7ae280934d616e
. -
MySQL, mendekode byte tersebut di Windows-1252, memahaminya untuk mewakili string
'Jazz–Man'
. -
Untuk menyimpan dalam
utf8
kolom, MySQL mentranskode string ke penyandian UTF-80x4a617a7ac3a2e282ace2809c4d616e
. Ini dapat diverifikasi dengan menggunakanSELECT HEX(name) FROM lessons WHERE id=79510
. -
Ketika klien mengambil nilainya, MySQL berpikir bahwa ia menginginkannya dalam
latin1
dan transcode ke Windows-1252 encoding0x4a617a7ae280934d616e
. -
Saat klien menerima byte tersebut, ia mendekodekannya sebagai UTF-8 dan oleh karena itu memahami string tersebut sebagai
'Jazz–Man'
.
Kesimpulan :klien tidak menyadari ada yang salah. Masalah hanya terdeteksi saat klien berbeda (klien yang tidak salah menyatakan koneksi UTF-8 sebagai latin1
) mencoba menggunakan tabel. Dalam kasus Anda, ini terjadi ketika mysqldump memperoleh ekspor data; menggunakan --default-character-set=latin1 --skip-set-charset
options secara efektif memaksa mysqldump untuk berperilaku dengan cara yang sama seperti aplikasi Anda, sehingga berakhir dengan data yang dikodekan dengan benar.
Untuk memperbaiki masalah Anda di masa mendatang, Anda harus:
-
Konfigurasikan aplikasi Anda sehingga set karakter koneksi MySQL dengan benar (mis. set
encoding: utf8
diconfig/database.yml
untuk Rel); -
Kode ulang data dalam database Anda, mis.
UPDATE lessons SET name = BINARY CONVERT(name USING latin1)
(perhatikan bahwa ini harus dilakukan untuk setiap kolom teks yang salah kodenya).
Perhatikan juga bahwa Anda mungkin ingin melakukan dua tindakan ini secara atom, yang mungkin memerlukan pemikiran.