Welcome to php club

PHP FAQ from PHPclub.ru: Mysql41Rus ...

Начало | Каталог | Изменения | НовыеКомментарии | Вам запрещён доступПользователи | Вам запрещён доступРегистрация | Вход:  Пароль:  

My Sql

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

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


У 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 ИСПОЛЬЗУЕТ НЕВЕРНУЮ КОДИРОВКУ
Симптомы:
Русский текст приходит в скрипт как русский, в консольном клиенте тоже все хорошо. Однако не работает сортировка, перевод в верхний/нижний регистр и т.д. Если применить решение из проблемы №1, то либо русский текст становится вопросами, либо mysql_error() возвращает сообщение похожее на «Illegal mix of collations (latin1_general_ci,IMPLICIT) and (cp1251_general_ci,COERCIBLE)...». В тоже время phpMyAdmin русский текст отображает как «крокозябры» (латинские символы с умляутами и т.д.).


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


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


Решение:
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 files\mysql50):

После чего перезапустите 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_USER\Software\Microsoft\Command Processor\AutoRun или HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun написать “chcp 1251 > NUL” (и снова без кавычек). Тогда запуск mysql сведется к запуску cmd и уже в нем — mysql.


1) Помните, что php_mysql.dll всего лишь обертка для libmysql.dll, СЛЕДИТЕ за тем, какая libmysql.dll лежит у вас c:\windows\system32 и в других каталогах доступных через переменную окружения 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:\mysql\share\charsets причем в формате .conf, а не в новомодном .xml и номера чарсетов у My SQL 4.0- клиента отличаются от номеров которые посылает сервер My SQL 4.1 при установлении коннекта. Поэтому если при запуске mysql.exe от My SQL 4.0- вы видите ошибки вида:
File 'c:\mysql\share\charsets\?.conf' not found (Errcode: 22)
Character set '#51' is not a compiled character set and is not specified in the 'c:\mysql\share\charsets\Index' file
значит у вас одновременно на машине My SQL 4.0- и 4.1 и для My SQL 4.1 стоит default_character_set не включенный в c:\mysql\share\charsets\Index. Рецепт простой — идем в MySQL4.1 \share\charsets\Index.xml ищем там id="51", понимаем что это cp1251 родимый, добавляем в c:\mysql\share\charsets\Index строку
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"


 
Много комментариев (5). [Показать комментарии/форму]