My SQL 4.1+ и любые проблемы с русскими буквами


Распространенные проблемы с русскими буквами и методы их решения



У 
tp://phpclub.ru/faq/wakka.php?wakka=MySql&v=mrb”>My SQL
версии 4.1 и выше (далее 4.1+) с русскими буквами бывают несколько проблем – рассмотрим их по отдельности.



1. PHP ИСПОЛЬЗУЕТ НЕВЕРНУЮ КОДИРОВКУ В КАЧЕСТВЕ КЛИЕНТСКОЙ
Симптомы:
– Через phpMyAdmin (здесь и далее подразумевается версия умеющая работать с кодировками, т.е. >= 2.6.0) все по-русски, а в скрипт приходят вопросительные знаки.
– Скрипт, заносящий данные в базу, видит русский нормально, а после вставки, как в правильном скрипте, так и в phpMyAdmin-е – знаки вопросов.



Тестирование:
Попробуйте в начале вашего скрипта, но после соединения выполнить SQL-запрос “SET NAMES кодировка, где кодировка, та кодировка, в которой у вас (по вашему мнению) данные. Например, для русской виндовой кодировки (windows-1251) это будет cp1251, для KOI8-R – koi8r, для UTF-8 – utf8 и так далее. В дальнейшем она будет упоминаться как “кодировка“.



Результат тестирования:
Если буквы (но необязательно слова) стали русскими, значит данные в базе лежат в правильной кодировке, сама база эту самую кодировку и использует.
Если буквы стали русскими, а слова нет (“бнопня”), значит скрипт ожидает данные в другой русской кодировке – пробуйте другие, пока не получится русских слов.



Решение:
1) Оставить запрос “SET NAMES кодировка в начале скрипта, если скриптов много – см. вариант 2.
2) Заставить My SQL автоматом выполнять этот запрос при каждом коннекте к нему.
Для этого нужно в файле my.cnf/my.ini (где их искать – в документацию) в раздел [server] добавить следующую строку:
init-connect=”SET NAMES кодировка
Однако, следует заметить, что это НЕ будет работать, если пользователь, которым вы подключаетесь к базе имеет привилегию SUPER (а стандартный пользователь root к таким относится, так же как и все созданные через “GRANT ALL PRIVILEGES ON *.* TO …”). Это сделано для того, чтобы в случае ошибки в этом запросе (а его можно изменить во время работы), хоть кто-то мог подключиться к базе и исправить его.
Внимание! Функция mysqli_client_encoding() и сотоварищи, отображает кодировку клиента на момент соединения и не меняют возвращаемое значение в процессе работы. Поэтому не стоит кричать, что кодировка не меняется. Просто делайте что говорят и смотрите результат работы скрипта. Получить нужное значение можно SQL-запросом “SHOW VARIABLES LIKE ‘character_set_client'”.
3) Начиная с версий 4.1.15 и 5.0.13 добавить в секцию [mysqld] или [server] файла my.cnf/my.ini параметр skip-character-set-client-handshake. Этот параметр заставляет сервер игнорировать кодироку, посылаемую клиентом, и использовать указанную серверу. В примере конфигурации ниже этот параметр уже есть.



2. My SQL ИСПОЛЬЗУЕТ НЕВЕРНУЮ КОДИРОВКУ
Симптомы:
Русский текст приходит в скрипт как русский, в консольном клиенте тоже все хорошо. Однако не работает сортировка, перевод в верхний/нижний регистр и т.д. Если применить решение из проблемы N1, то либо русский текст становится вопросами, либо mysql_error() возвращает сообщение похожее на “Illegal mix of collations (latin1_general_ci,IMPLICIT) and (cp1251_general_ci,COERCIBLE)…”. В тоже время phpMyAdmin русский текст отображает как “крокозябры” (латинские символы с умляутами и т.д.).



Тестирование:
Попробуйте в phpMyAdmin-е выполнить запрос вида “SELECT CONVERT(CONVERT(поле USING binary) USING кодировка) FROM таблица, где таблица и поле соответствующая таблица и поле с русским текстом, а кодировка – кодировка из проблемы N1.



Результат тестирования:
Если буквы (но необязательно слова) стали русскими, значит текст в базе лежал не в правильной кодировке и его нужно сконвертировать.
Если буквы стали русскими, а слова нет (“бнопня”), значит неверно выбрана одна из русских кодировок – пробуйте другие, пока не получится русских слов.



Решение:
1) Установить для My SQL нужную кодировку по умолчанию.
Внимание! Это решение сработает сработает, только если кодировки не переопределены для базы, таблицы или столбца.
Для этого нужно в файл my.cnf/my.ini в раздел [server] добавить следующую строку:
default-character-set=cp1251
2) Сконвертировать таблицы в нужную кодировку.
Про то как конвертировать таблицы с неверными кодировками хорошо написано в мануале. Повторять здесь то же самое не к чему.


Компилирование My SQL 4.1+ из исходников


Самостоятельная компиляция My SQL 4.1+ из исходников
1) Отконфигурировать (./configure) My SQL как минимум со следующими параметрами:
–with-charset=cp1251 – задает кодировку по умолчанию для сервера и клиента (для портов Free BSD – параметр для make WITH_CHARSET)
–with-collation=cp1251_general_ci – задает collation по умолчанию (для Free BSD – WITH_COLLATION)
–with-extra-charset=all – включает поддеркжу всех поддерживаемых My SQL кодировок (для Free BSD – WITH_XCHARSET)
Внимание! Для портов Free BSD нужно с такими параметрами собрать, как сервер, так и клиента. Тоже самое замечание относится и к случаю, когда клиент и сервер находятся физически на разных машинах. Т.е. нужно понимать, что и сервер, и клиент должны быть собраны с привильной кодировкой по умолчанию, иначе полного результата не будет.
2) Cкомпилировать и установить My SQL :).
3) Скомпилировать PHP с только что установленной библиотекой-клиентом My SQL (т.е. указав –with-mysql=/path/to/mysql).


Установка My SQL 4.1+ под Windows


Установка
Устанавливать My SQL, во избежании проблем в дальнейщем, желательно в каталог c:mysql. Однако это не обязательно. Других рекоммендаций относительно установки нет – устанавливайте как обычно.



Настройка
Создайте файл c:my.cnf следующего содержания (здесь и далее предполагается, что My SQL была установлена в c:web filesmysql50):

После чего перезапустите My SQL и наслаждайтесь результатом :).


Перенос данных между My SQL версии 4.0 и младше (далее 4.0-) и 4.1+


Перенос данных из My SQL 4.0- в My SQL 4.1+
Внимание! При правильно скомпилированном My SQL это не нужно, однако на Windows, где скомплировать затруднительно, крайне рекоммендуется использовать приведенный метод для предотвращения преобразования кодировки текста в latin1.
1) Сохранить базы с помощью mysqldump.
2) Обновить My SQL.
3) Залить базы с помощью “mysql -u user -p –default-character-set=cp1251 < dump.sql” (или установить default-character-set=cp1251 для mysql в my.cnf/my.ini, см. “установку” выше).



Перенос данных из My SQL 4.1+ в My SQL 4.0-
По умолчанию mysqldump пишет в кодировке UTF8 и использует “SET NAMES …” для указания этого. Т.к. My SQL 4.0- не поддерживает UTF8, нужно дампить базы с помощью “mysqldump –default-character-set=cp1251”. Однако, не думайте, что это единственная проблема на данном пути, но этот faq их не рассматривает, т.к. посвящен только проблемам с русским текстом. Смотрите документацию к mysqldump-у на предмет параметра –compat.


Некоторые замечания для Win 32? платформы


0) Помните, что стандартная виндовая консоль имеет кодировку cp866 и как результат русские символы в cp1251 выводятся черт знает как. Есть два возможных решения этой проблемы:
– Выполнить запрос “SET NAMES cp866” после запуска mysql. Однако это сработает только при правильно настроенном сервере/базе/таблице – в противном случае будут вопросительные знаки. В общем не рекоммендуется.
– Открыть новую виндовую конслоль (например пойти в Start->Run (Пуск->Выполнить), набрать в поле ввода “cmd” (без кавычек) и нажать OK), в которой выполнить комманду “chcp 1251” (опять же без кавычек) и сменить шрифт консоли (Щелчок правой кнопкой на заголовок окна->Properties (Свойства), закладка Font (Шрифт)) на “Lucuda Console” и поставить галочку “Bold fonts” (как это по русски – без понятия :)). Нажать “OK”. В появившемся окне диалога выбрать “Save properties for future windows with same title” (как по русски – опять же хз :)) и нажать “OK”. После этого можно в этой консоли запускать mysql и работать в нем. Чтобы не писать каждый раз “chcp 1251” можно в ключе строкового типа HKEY_CURRENT_USERSoftwareMicrosoftCommand ProcessorAutoRun или HKEY_LOCAL_MACHINESoftwareMicrosoftCommand ProcessorAutoRun написать “chcp 1251 > NUL” (и снова без кавычек). Тогда запуск mysql сведется к запуску cmd и уже в нем – mysql.



1) Помните, что php_mysql.dll всего лишь обертка для libmysql.dll, СЛЕДИТЕ за тем, какая libmysql.dll лежит у вас c:windowssystem32 и в других каталогах доступных через переменную окружения PATH.



2) Следите за тем, с каким my.ini/my.cnf запускается ваш клиент и сервер и какие там настройки default-character-set и character-sets-dir. Лучше всего иметь один такой файлик – с:my.cnf – и его копию в каталоге где установлен My SQL. Последнее удобно, когда установлено несколько My SQL, и для переключения между ними можо просто скопировать нужный из каталога его установки в с:. С My SQL 5.0 все еще проще, он читает файл настроек из каталога, куда установлен. Т.е. с ним таковой в c: оказывается не нужен.



3) Учитывайте, что в PHP4 php_mysql.dll (до определенных версий, может в 4.3.11 уже поправили) собирается для 4.0.x и 3.23.x libmysql.dll, и пытается выхватить настройки из c:my.cnf. Кроме того, постоянно проскакивает глючок, когда php как клиент при коннекте ищет charset’ы в папке c:mysqlsharecharsets причем в формате .conf, а не в новомодном .xml и номера чарсетов у My SQL 4.0- клиента отличаются от номеров которые посылает сервер My SQL 4.1+ при установлении коннекта. Поэтому если при запуске mysql.exe от My SQL 4.0- вы видите ошибки вида:
File ‘c:mysqlsharecharsets?.conf’ not found (Errcode: 22)
Character set ‘#51’ is not a compiled character set and is not specified in the ‘c:mysqlsharecharsetsIndex’ file
значит у вас одновременно на машине My SQL 4.0- и 4.1+ и для My SQL 4.1+ стоит default_character_set не включенный в c:mysqlsharecharsetsIndex. Рецепт простой – идем в MySQL4.1+sharecharsetsIndex.xml ищем там id=”51″, понимаем что это cp1251 родимый, добавляем в c:mysqlsharecharsetsIndex строку
cp1251 51
и проверяем.
(Не может ли кто-нить проверить, как сейчас с этим обстоят дела? У меня уже нигде нет ни PHP4 ни My SQL 4.0-. /Profic/)



4) Всегда помните, php_mysql.dll собирается по умолчанию как клиент с кодировкой latin1, этот чарсет устанавливается при вызове mysql_connect и вы ничего с этим поделать не можете, кроме вызова “SET NAMES кодировка, из решения выше. Грубые хаки в виде правки Hex Edit?-ом dll-ки – не решение.



5) Важно понимать, что выполнение “SET NAMES кодировка НИКАК не влияет на default_character_set который используется при СОЗДАНИИ таблиц по “CREATE TABLE” без указания charset и collation, они берутся из default-character-set my.ini/my.cnf. Чтобы это поправить нужно нормально настроить сервер (см. “установку” выше) или использовать комбинацию


SET NAMES кодировка;
SET character_set_database=кодировка;
SET character_set_server=кодировка;



6) Можно запускать mysqld-nt.exe с указанием альтернативного файла, из которого читать настройки, вместо стандартного, через параметр –defaults-file=путь/до/вашего/my.ini/my.cnf. Однако, если в таком файле указаны опции для клиента, то параметр –default-file нужно указывать руками при вызове каждого отдельно взятого клиента. Установить так сервис можно коммандой: “mysqld-nt.exe –install mysql50 –defaults-file=с:\web files\mysql50\my-config.cnf”




By Ruslan Novikov

Интернет-предприниматель. Фулстек разработчик. Маркетолог. Наставник.