Rails, MySQL, Unicode data и таблицы latin1 - Куда пойти отсюда? - PullRequest
8 голосов
/ 03 октября 2010

Я не уверен на 100% в деталях, поэтому я бы хотел, чтобы кто-то меня поправил, но я продвинусь вперед в том, что, как мне кажется, происходит ...

Когда я впервые настроил свою базу данных, я использовал систему кодировки символов по умолчанию, даже не задумываясь, и это была латиница 1. Я никогда даже не думал о i18n / l10n. Это просто не пришло мне в голову. Я просто принял значения по умолчанию и пошел с ним.

В любом случае, я использую базу данных исключительно для приложения Rails, и теперь у нас есть несколько ГБ данных, 100 000 строк и много международных пользователей. Я заметил, что многие из наших иностранных пользователей вставляют данные, которые выглядят как Unicode / non-latin1. Вот пример:

А как насчет сумасшедших вещей в Юникоде? 100 ☠ ☭

database.yml

Вот наш файл database.yml.

development:
  adapter: mysql
  database: XXX
  username: YYY
  password: ZZZ
  host: localhost
  encoding: utf8

Как видите, мы устанавливаем нашу кодировку символов в utf8. Однако все наши таблицы имеют набор символов по умолчанию latin1. Я в этом уверен.

Обновление После тщательного изучения нашего производственного файла database.yml не указывается кодировка, в то время как в моей локальной копии указывается utf8. Это вызывало проблемы, когда я сбрасывал производственную базу данных и импортировал ее локально. Теперь кажется, что импорт работал нормально, но Rails читал его неправильно.

mysql CLI tool

Когда я просматриваю данные с помощью инструмента CLI mysql, он правильно отображает все символы Юникода. Тем не менее, оператор 'show create table' ясно показывает, что таблицы являются кодировкой по умолчанию latin1. Это наводит меня на мысль, что MySQL достаточно умен, чтобы хранить нелатинские данные.

HTTP-заголовок

Наш HTTP-заголовок Content-Type установлен в utf-8, например:

Content-Type: text/html; charset=utf-8

Попытки преобразования

Я немного поиграл с преобразованием наших таблиц в кодировку utf-8, но все безуспешно. В основном я пытался создать дамп базы данных, запустить iconv для преобразования, а затем выполнить повторный импорт с таблицами, установленными в utf-8. В MySQL не было ошибок, но все данные Unicode были искажены.

Что делать?

Я как бы застрял в том, что делать (если что-нибудь). Я твердо верю в то, чтобы не починить то, что не сломано, но вся эта ситуация беспокоит меня. Мы никогда не жаловались на то, что пользователи не могут хранить свои данные, и, похоже, все работает нормально. Я просто хотел бы знать, что именно происходит, кто / что делает преобразование (MySQL? Ruby? Rails? MySQL соединение?), И любые советы о том, как продолжить.

Ответы [ 2 ]

3 голосов
/ 03 октября 2010

Скорее всего, данные, хранящиеся в ваших таблицах, являются допустимыми UTF-8, но MySQL считает, что это Latin-1 (потому что это тип данных, с которым был объявлен столбец).Конечно, это также допустимое значение Latin-1, поскольку в AFAIK допустима любая произвольная последовательность байтов Latin-1.

Что происходит при преобразовании в UTF-8, так это то, что MySQL видит действительные данные в кодировке Latin-1 ипреобразует это в эквивалентный действительный UTF-8.Это означает, что вы получаете данные с двойным UTF-8-кодированием, поэтому они искажаются.

Способ обойти это - преобразовать столбец в двоичную строку, а затем в UTF-8 изтам.MySQL не преобразует строку, когда вы делаете это (потому что вы конвертируете ее в формате, который просто говорит: «трактуйте эту строку как последовательность из 0 и 1»).

ALTER TABLE MyTable
    MODIFY MyColumn CHAR(100) CHARACTER SET binary,
    MODIFY MyColumn CHAR(100) CHARACTER SET utf8
0 голосов
/ 28 мая 2012

Для меня (и других) было полезно использовать адаптер mysql2 .

В вашем Gemfile :

gem "mysql2"

В config / database.yml :

adapter: mysql2

И вы также должны помнить, что для набора символов в вашей базе данных необходимо задать UTF-8, но, как я понимаю, вы тоже это сделали: -)

Надеюсь, это поможет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...