MySQL, PHP и кодировки. Ultimate guide.

Всё что вы когда-либо хотели знать про mysql, php и кодировки, но боялись спросить! Почему кириллица на сайте отображается вопросами? Как правильно настроить сервер mysql для работы с кириллицей? Как поменять кодировку в mysql? Как изменить кодировку в скриптах php? Какую выбрать кодировку? Как сконвертировать базу данных из одной кодировки в другую? Эти и многие подобные вопросы с завидным упорством снова и снова поднимаются на различных форумах уже который год. В этом посте я постарался рассказать что нужно делать чтобы такие проблемы не возникали и дать наиболее эффективные советы на тот случай если они все-таки возникнут. Если вы не найдете ответ на свой вопрос здесь – напишите мне и я обязательно дополню этот текст с учетом вашего случая ;)

Mysql, php и кодировки. Источник проблем.

Проблемы с кодировками в Mysql обусловлены историей создания этой программы. Так как разрабатывали mysql – европейцы – для них было естественно выбрать в качестве основной кодировки более удобную для себя latin1. Странно, но и по сей день большинство инсталляций Mysql по умолчанию работают с этой кодировкой что и создает для пользователей кириллицы проблемы с добавлением в базу данных строк на русском и украинском языках – в latin1 эти символы просто отсутствуют.

Поэтому первое что нужно сделать при возникновении проблем с кодировками в mysql – нужно проверить какая кодировка является для данной инсталляции mysql основной. Проверить это можно несколькими способами.

Настройка сервера mysql для нужной кодировки.

  • Если вы админ сервера или вы самостоятельно настраиваете собственную mysql на рабочей машине.
    Откройте файл конфигурации mysql.ini (/etc/mysql.cnf для os linux) и найдите такие строки.

    [mysqld]
    default-character-set=название_кодировки
    character-set-server=название_кодировки
    init-connect="SET NAMES название_кодировки"
    skip-character-set-client-handshake

    Вместо “название_кодировки” нужно подставить название той кодировки, которую вы будете использовать. Для текстов на русском и украинском языках можно использовать utf8 или cp1251 (обратите внимание – названия кодировок в mysql пишутся без обычного дефиса!!!). Но я советовал бы использовать только utf8 – так вы себе сэкономите в будущем немало нервов.

    Если такие строки в файле конфигурации отсутствуют, то это означает что база данных использует по умолчанию ту кодировку, которая была задана при компиляции. Добавьте в конфиг нужные вам настройки кодировок (примеры ниже) и перезапустите mysql.

  • Если у вас возникли проблемы с кодировкой на хостинге, где вы не имеете прав администратора, то проверить настройки кодировки для mysql вы сможете другим способом: установите соединение с mysql (при помощи консольной команды mysql или phpmyadmin – как вам удобнее) и выполните такой sql-запрос: show variables like ‘char%’. Этот запрос покажет вам значения переменных mysql, которые имеют отношение к кодировкам. Скорее всего, вы увидите что-то вроде такого

    character_set_client latin1
    character_set_connection latin1
    character_set_database cp1251
    character_set_filesystem binary
    character_set_results latin1
    character_set_server latin1
    character_set_system utf8
    character_sets_dir /usr/share/mysql/charsets/

    Я специально привел выше пример НЕПРАВИЛЬНО НАСТРОЕННОГО СЕРВЕРА!!! Обратите внимание – в нем используются в разных случаях три(!) разные кодировки. Начинающему веб-программисту в такой ситуации будет сложно добиться корректной работы скрипта. Старайтесь чтобы все переменные были настроены на работу с одной и той же кодировкой. Тогда 99% проблем которые обсуждаются на форумах у вас просто не возникнут. Тут даже не столь важно какую именно кодировку вы выберете – главное чтобы она была везде одинаковой. Но все-таки старайтесь указывать в настройках ту кодировку, которую действительно будете использовать для хранения данных.

    Итак, удачный вариант – это если команда show variables like ‘char%’ из абзаца выше покажет вам список одинаковых кодировок для каждой из переменных и еще лучше будет если эта кодировка совпадет с той которую используете вы.

    Если же кодировка mysql отличается от вашей – не спешите расстраиваться. Изменить любую из этих переменных вы можете либо глобально, для всех правкой конфигов (если вы администратор сервера), либо только для себя – sql-запросом set character_set_database=utf8 (если вы пользователь). Такой запрос должен будет выполняться из вашего php скрипта сразу после установки соединения с сервером mysql. Ниже пример для установки кодировки utf8 из php скрипта.

    mysql_query('SET character_set_database = utf8');
    mysql_query('SET NAMES utf8');

    Настройки для cp1251 выставляются аналогично.

    mysql_query('SET character_set_database = cp1251');
    mysql_query('SET NAMES cp1251');

    Что касается character_set_database – постарайтесь сразу создать базу данных в нужной кодировке (как вариант – отправьте такую просьбу в техподдержку хостинга), тогда вы избежите по крайней мере одного лишнего запроса к mysql во время работы скрипта. Если удастся,то строчку с ‘character_set_database’ из приведенного выше кода можно будет удалить.

Примеры настроек сервера mysql для правильной работы с кодировками.

При правильно настроенном сервере делать запросы из скрипта для установки правильной кодировки уже будет не нужно.

Настройки для utf8

[mysqld]
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci
init-connect="SET NAMES utf8"
skip-character-set-client-handshake
 
[mysqldump]
default-character-set=utf8
 
[client]
default-character-set = utf8

Настройки для cp1251

[mysqld]
default-character-set=cp1251
character-set-server=cp1251
collation-server=cp1251_general_ci
init-connect="SET NAMES cp1251"
skip-character-set-client-handshake
 
[mysqldump]
default-character-set=cp1251
 
[client]
default-character-set = cp1251

Проверка реальной кодировки в которой хранятся базы данных mysql.

В случае если вы все (и сервер, и php скрипт) настроили правильно, по инструкции выше, но русские буквы все равно не отображаются – проверьте действительно ли ваши строки сохранены в той кодировке, которую вы указали в настройках!!!

Простой способ проверки – сделайте дамп базы данных в sql-формате и откройте его в текстовом редакторе. Sql-формат – это обычный текст. Если ваша база данных mysql в кодировке cp1251 – открывайте в Блокноте. Если utf8 – в любом редакторе с поддержкой Юникода. Пролистайте файл и убедитесь что все надписи с кириллицей нормально читаются и что sql-команды create table и create database, которые встречаются в дампе содержат правильные названия кодировки mysql (той кодировки, которая вами была указана в настройках сервера или в запросах из php-скриптов.

Если кодировка не подходит – сделайте бекап базы на всякий случай, перекодируйте sql-дамп в любом текстовом перекодировщике, замените названия кодировок в файле на правильные и заливайте полученный файл на сервер mysql. Теперь с кодировками все должно быть в порядке :)

Если вам понравился этот сайт, вы можете подписаться на rss

Отзывы: 33 комментария

  • Дмитрий
    11 Март 2009 в 23:38

    Спасибо! Помогли мне решить проблему, которая уже тянется на протяжении месяца!

  • Ivan
    04 Апр 2009 в 23:42

    Дай Бог тебе здоровья, человек!!!!
    Огромное спасибо!!!!!!!!!!!!!!!!
    Я, с Вашего позволения, выложу эту статью у себя на сайте.
    Ссылка на первоисточник в обязательном порядке будет

  • admin
    09 Апр 2009 в 23:34

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

  • Zay4enka
    16 Апр 2009 в 23:18

    Спасибище ОГРОМЕННОЕ!!!!!!!!!!!!!!
    Наконецто все работает как положено :)

  • Shuhrat
    21 Апр 2009 в 12:26

    Проблема на MySQL кодировка. У меня текст татарского и узбекского. Я использаваль utf8 кодировка но не работал, если у вас какой небуд правиль вариант пишите(с примером).

  • admin
    21 Апр 2009 в 17:08

    А какой алфавит вы используете? Если латиницу, то у вас пробем не будет даже с настройками mysql по умолчанию (узбекский ведь, если я не ошибаюсь, даже диакритические знаки не использует?). Если кириллицу то настраивать нужно utf8 – примеры есть в статье выше.

  • Сергей
    26 Апр 2009 в 19:51

    УРАААААААААААААААААААААААААААА! Заработало!!!!!!!!!
    СПАСИБО УВ. АДМИН!!!!!! ВСЕ ЧЕТКО И ЯСНО!! НАВЕРНОЕ САМАЯ
    ЛУЧШАЯ СТАТЬЯ В СЕТИ ИНТЕРНЕТ!!!!!!!!!!!!!!!!!!!!

  • Сергей
    26 Апр 2009 в 20:42

    И если можно вопрос. Я настроил кодировки так как было выше расказано, и всетаки осталась еще одна маленькая проблема, я когда
    в своем интернет магазине на локальной машине выбираю не русский, а английский интерфейс то все английские символы в виде “Äîáàâèòü òîâàð”, а когда выбираю русский интерфейс все ОК! что это может быть!
    P.S. На сервере хостера все ок!

  • admin
    28 Апр 2009 в 12:25

    *Английские* символы правильно отображаются в любой кодировке – от UTF8 и latin1 до windows-1251. У вас в английской версии на страницы выводятся все-таки русские символы, причем в неправильной кодировке…

  • Сергей
    28 Апр 2009 в 14:31

    ОК, спасибо за разъяснение, буду разбираться.

  • имя
    16 Май 2009 в 18:13

    Спасибо большое за статью!

  • Лена
    30 Май 2009 в 17:01

    Подскажите пожалуйста, я сделала поиск по сайту и на локальной машине он работает без учета регистра символов, а когда перенесла на хостинг он начинает учитывать регистр (тип полей одинаковый TEXT) это может быть связано с кодировкой?

  • admin
    02 Июнь 2009 в 12:30

    Если поиск все же работает с учетом регистра, то похоже что проблема не в кодировке. Проверьте может быть у вас указан флаг BINARY в описании поля? Если этот флаг включен, то MySQL начинает учитывать регистр при сравнении.

  • Vikusik
    25 Авг 2009 в 2:28

    Большое спасибо!
    Помогло при переезде на новый хостинг :)

  • Александр
    04 Сен 2009 в 23:13

    БОЛЬШОЕ СПАСИБО! Удалось быстро решить проблему.

  • leonder
    11 Сен 2009 в 10:09

    Присоединяюсь к благодарностям, дай вам бог здоровья и счастья!

  • mark1
    23 Сен 2009 в 23:03

    Спа-си-бо! Целый день борьбы с кодировками закончился с прочтением сей статьи. По подсказке, я порылся в дампе БД, и к своей радости обнаружил причину граблей (в поле для ввода, к-рое генерится модулем Adsmanager 2.5RC2 под Joomla, сохранялась лишь латиница). Так вот причина была простая. Привожу кусок кода, может пригодится.
    `ad_age` text CHARACTER SET latin1 NOT NULL,
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
    ——————
    Как видно, php код модуля ЗАЧЕМ-ТО принудительно ставит полю ad_age кодировку latin1, несмотря на дефолтную utf8. За день я переконвертил 10 раз всю базу в utf8, и настроил my.ini. Но в дамп лезть перепроверить и в мыслях не было. СПС ЗА ИДЕЮ! ;-)

  • hunter
    02 Окт 2009 в 10:37

    спасибо огромное!

  • Alex
    04 Окт 2009 в 18:45

    Использовать для базы данных кодировку UTF-8 (по умолчанию) – далеко не всегда удобно, так как это приводит к увеличению ее размера в более чем два раза (по сравнению с кодировкой ср1251).
    Например, если база в кодировке ср1251 занимает 500 МБайт, то в кодировке UTF-8 – те же данные займут уже более 1ГБайта на диске, что, в свою очередь, повлечет снижение скорость доступа к данным.

  • Alex Berkovich
    15 Окт 2009 в 17:03

    Руслан, огромное человеческое спасибо за статью!!!! Лучшая статья во всем рунете!

  • Майк
    27 Окт 2009 в 14:14

    Спасиб Огромное. Наконец избавился от єтих вопросов.

  • BapBapa
    12 Ноя 2009 в 21:40

    utf-8 самая лучшая кодировка на сегодняшний день, думаю в скором все будут на ней сидеть.

  • Александр
    16 Ноя 2009 в 14:48

    Здравствуйте! Спасибо большое за статью. У меня тоже есть проблема перевода базы из Latin1 в UTF8. Какие перекодировщики дампа Вы посоветуете? В phpmyadmin нет подходящих инструментов для этой задачи? Во всяком случае я пытался в phpmyadmin, но не получилось.

    С уважением, Александр

  • igor
    19 Ноя 2009 в 13:09

    Спасибо Ваша стаття помогла=)

  • Руслан
    25 Ноя 2009 в 3:03

    2Александр. Дамп – обычный текстовый файл. Подойдет практически любой перекодировщик… на стороне линуксового сервера можно использовать команды iconv или recode

    2igor Пожалуйста :)

  • Александр
    25 Ноя 2009 в 7:02

    Есть много кодировщиков, которые разные кодировки, в том числе utf8 преобразуют в русский язык. А мне нужно наоборот. Чтобы русский тескт перекодировали в utf8. Пока не нашел такого перекодировщика:( . Latin1 имеет свои преимущества, в дампе виден русский язык, но не все языки поддерживает. Если на сайте знакомств с базой latin1 вместо пароля введут какие-то экзотические символы, он не сможет пойти потом на сайт, так как база эти символы не поддерживает:)

  • Серг
    12 Дек 2009 в 5:13

    Огромное спасибо)) Очень полезная статья!

  • Валик
    23 Янв 2010 в 0:07

    УВ. Админ! Хорошая статья, тока появилась другая проблема, когда я выставляю таким образом:
    character_set_client utf8
    character_set_connection utf8
    character_set_database utf8
    character_set_filesystem binary
    character_set_results utf8
    character_set_server utf8
    character_set_system utf8
    character_sets_dir /usr/share/mysql/charsets/

    MySQL не воспринимает русские буквы в самом клиенте MySQL :( ((
    3-й день уже мучаюсь с кодировкой ((( Помогите плиз!!! Сил моих больше нет.

  • Александр
    09 Фев 2010 в 16:27

    character set database latin1 как это можно изменить если у меня нет прав администратора?

  • humito
    18 Фев 2010 в 2:58

    Руслан, тоже хочу тебя поблагодарить.
    3 дня и 3 ночи ковырялся и пытался пользоваться другими подсказками по этой теме.
    Всё решилось, когда наткнулся на твой мануал.

  • kostya_2d
    26 Фев 2010 в 13:33

    Огромная просьба автора связаться со мной по данной теме.
    У меня похожая проблема с кодировкой, только не сайта, а программы

  • dimion
    07 Март 2010 в 0:52

    Вот это действительно четко и конкретно расписано большое спасибо очень полезная статья !

  • Катя
    15 Март 2010 в 2:06

    Доброй ночи. Вот и я только что решала эту проблему со знаками вопроса. Они исчезли (спасибо огромное), но украинский текст все равно отображается не корректно. Выглядит так: “левЪнві – літн”. Буду очень благодарна если сможете помочь. Спасибо.

Ваш отзыв

Имя (*)

E-mail (*)

Сайт

Сообщение