Character set system как изменить

Сейчас появляется все больше предложений хостинга с самыми последними версиями MySQL-серверов, хостеры обновляют у себя версии софта "до последних имеющихся". Часто это приносит проблемы пользователям, в частности большое количество жалоб связано с нарушением работы "Joomla! LE". Вернее так: сам движок встает и работает без вопросов, а любой вновь устанавливаемый компонент, модуль или другая "крутая прибабаха" после установки упорно выдает вместо кириллицы в контенте или знаки вопросиков "???? ??????? ?????? ?????????????? ???????" или вообще что-то непотребное "Сейчас появляется РІСЃРµ больС?Рµ предложе".

Сейчас появляется все больше предложений хостинга с самыми последними версиями MySQL-серверов, хостеры обновляют у себя версии софта «до последних имеющихся».

Часто это приносит проблемы пользователям, в частности большое количество жалоб связано с нарушением работы «Joomla! LE». Вернее так: сам движок встает и работает без вопросов, а любой вновь устанавливаемый компонент, модуль или другая «крутая прибабаха» после установки упорно выдает вместо кириллицы в контенте или знаки вопросиков «???? ??????? ?????? ?????????????? ???????» или вообще что-то непотребное «РЎРµР№С‡Р°СЃ появляется РІСЃРµ больС?Рµ предложе».

Как в таком случае исправить ситуацию и запустить необходимый компонент на «LE»?

Для начала давайте рассмотрим отличия в структуре БД и таблиц разных версий MySQL-серверов.

Я делю версии MySQL-серверов на:

  • нижние версии — все версии, до версии 4.1
  • высшие версии — все версии, начиная с 4.1 включительно и выше

Они имеют следующие отличия:

  • нижние версии — выдают результат в той кодировке, на какую настроен сам сервер. Если он настроен на работу с кириллицей, то никаких проблем обычно не возникает, это в 99.9 % случаев так. Поставил — забыл.
  • высшие версии — имеют внутренне представление идентификаторов всегда в utf8-кодировке, т.е. независимо от того, в какой кодировке выдаются и обрабатываются данные, внутренне их представление всегда в utf8. Кроме того, у сервера имеется несколько настраиваемых параметров, с помощью которых он может проводить промежуточные перекодировки в зависимости от требований пользователя, причем они еще делятся на две группы — GLOBAL и SESSION.
  • GLOBAL — Глобальные, относятся к самому серверу. т.е. настройки «по умолчанию». Если в SQL-запросе не передаются какие-то требуемые параметры, то применяются параметры «по умолчанию», которые в свою очередь берутся именно отсюда. Могут устанавливаться в файле конфигурации (my.cnf , my.ini), передаваться как параметры командной строки при запуске сервера, динамически меняться в зависимости от поступивших команд для динамической перенастройки сервера и его параметров «на лету». В последнем случае требуется наличие таковых прав у пользователя, который посылает серверу такую команду, как правило — это привилегия пользователя ROOT.
  • SESSION — Настройки текущего соединения в БД- текущей сессии. Как только соединение с БД разорвано, сессия считается завершенной и настройки «пропадают». Они более безопасны (для хостера :)), т.к. нигде не сохраняются и и не могут повлиять на работу и настройки самого сервера. Выдача этих команд и их результаты являются заботой самого пользователя.

Все эти параметры (а мы сейчас рассматриваем только те, которые влияют на работу с кириллицей) существуют в системе MySQL-сервера в виде переменных, соответственно — глобальных (global) и локальных (session) и для перенастройки параметров MySQL-сервера достаточно их изменить следующими SQL-операторами:

SET GLOBAL variable_name = new_valie
SET SESSION variable_name = new_valie

Для просмотра текущих значений нужной переменной используйте следующие операторы:

select @@global.variable_name
select @@session.variable_name

Пример:

set session collation_server = cp1251_general_ci;
select @@session.collation_server;

… вот 1251

set session collation_server=latin1_swedish_ci;
select @@session.collation_server;

… а здесь уже latin1

Посмотреть их можно и иным способом — через phpMyAdmin:

… вот они:

Можно посмотреть стразу все переменные сервера:

SHOW VARIABLES

Давайте рассмотрим эти переменные:

Имя переменной Описание Зона десйтвия
character_set Кодировка по умолчанию. С версии 4.1.1 удалена. НЕ ИСПОЛЬЗОВАТЬ! GLOBAL | SESSION
character_set_client Кодировка для операторов, поступающих со стороны клиента GLOBAL | SESSION
character_set_connection Кодировка, используемая для литералов, не имеющих устройства для ввода символов, (у некотрых функций) и для преобразования числового кода в строковый. GLOBAL | SESSION
character_set_database Кодировка, используемая БД по умолчанию. Сервер устанавливает эту переменную каждый раз, когда изменяется БД по умолчанию. Если БД по умолчанию отсутствует, переменная будет иметь то же значение, что и character_set_server. GLOBAL | SESSION
character_set_server Кодировка по умолчанию для всего сервера. GLOBAL | SESSION
character_set_results Кодировка, используемая для возвращению клиенту результатов запроса. GLOBAL | SESSION
character_set_system Кодировка, используемая сервером для хранения идентификаторов. Всегда имеет значение = UTF8 GLOBAL | SESSION
collation_connection Сопоставление кодировки соединения. GLOBAL | SESSION
collation_database Сопоставление кодировки БД. переменная устанавливается всякий раз, когда изменяется БД по умолчанию. Если БД по умолчанию отсутствует, переменная будет иметь тот же значение, что и collation_server GLOBAL | SESSION
collation_server Сопоставление по умолчанию GLOBAL | SESSION

Теперь давайте рассмотрим случай «ненормального» MySQL-сервера, который установлен хостером с параметрами «по умолчанию и хай стоить…». Дело в том, что «по умолчанию MySQL-сервер устанавливается в кодировке latin1 , что нас ну никак не устраивает, поскольку именно эта настройка и является основным нашим врагом и «производителем» знаков вопросиков «?????? ???????? ??????????».

И так мы имеем установленные MySQL-сервер с параметрами кодировки по умолчанию latin1.

При подаче последовательности SQL-команд на создание новой БД и таблицы в ней:

# создание БД
CREATE DATABASE `TEST` ; 

# создание таблицы с одним текстовым полем
CREATE TABLE `TEST` (
`title` TEXT 
) ENGINE = MYISAM ;

… мы получим:

  • БД с кодировкой latin1
  • Таблицу «TEST» с кодировкой latin1

  • Текстовое поле ‘title’ с кодировкой latin1

Для нормальной работы с кириллицей создание БД, таблицы и полей на сервере с latin1 должно выглядеть так:

# создание БД
CREATE DATABASE `TEST` COLLATE cp1251_general_ci; 

# создание таблицы с одним текстовым полем
CREATE TABLE `TEST` (
`title` TEXT CHARACTER SET cp1251 COLLATE cp1251_general_ci
) ENGINE = MYISAM COLLATE cp1251_general_ci;

… только тогда мы получим:

  • БД с кодировкой 1251
  • Таблицу «TEST» с кодировкой 1251

  • Текстовое поле ‘title’ с кодировкой 1251

Но:

  • во первых, как правило у пользователя нет прав на создание БД собственным SQL-скриптом, БД создается или панелью управления хостинга, которая оставляет кодировку по умолчанию, что и приводит к дальнейшему распространению действия latin1 на вложенные объекты — таблицы и поля;
  • во вторых, в Joomla! при установке компонентов, как правило, в 99.9 % случаев, SQL-команды создания объектов и работы с ними, не содержат этик команд тоже.

Выход?

  • первое: переписывать SQL-скрипты (на что не каждый пользователь способен, да и «на фиг надо»);
  • второе: перевести все вложенные объекты БД в кодировку 1251

В последнем случае мы избавимся от головной боли с переписыванием SQL-скриптов, с неработоспособностью нужных компонентов и т.п.

Для начала требуется составить список БД, таблиц и полей в таблицах. которые имеют кодировку, вызывающую потерю кириллицы, в нашем случае это любая кодировка, отличная от cp1251_general_ci , после чего потребуется составить SQL-скрипт и выполнить его на MySQL-сервере. Вот параметры этого скрипта:

Смена кодировки БД ALTER DATABASE `db_name` COLLATE cp1251_general_ci
Смена кодировки у таблицы ALTER TABLE `table_name` COLLATE cp1251_general_ci
Смена кодировки у поля ALTER TABLE `table_name`
CHANGE `current_field_name` `new_field_name` VARCHAR( 100 ) CHARACTER SET cp1251
COLLATE cp1251_general_ci

Последнюю команду рассмотрим поподробнее:

Изменить в таблице… ALTER TABLE
… в какой таблице.. `test
…сменить… CHANGE
..меняем это поле… `test`
…новое его имя (то же) … `test`
… новые параметры поля (те же) … VARCHAR( 100 )
…новая кодировка поля… CHARACTER SET cp1251
… новое сопоставление. COLLATE cp1251_general_ci

Кодировку отдельных объектов можно сменить прямо в phpMyAdmin:

После смены кодировки полей, даже старые компоненты, которые были написаны еще до выхода этих версий MySQL, начинают работать нормально, только данные, которые уже находятся в БД «вопросиками», можно считать потерянными, их придется вводить заново уже после того, как БД, таблицы и поля таблиц будут переведены в кодировку 1251.

Для хостеров: (и не говорите, что не читали…)

Для перенастройках самого MySQД-сервера на кириллицу 1251 следует внести изменения в MY.CNF (желательно в каталоге /etc для *nix) или MY.INI:

character-sets-dir=/путь_к_папке_с_чарсетами # если запросит...
default-character-set=cp1251

Выглядеть это должно так:

[mysql]
default-character-set=cp1251

[mysqld]
default-character-set=cp1251

… после чего перезагрузить MySQL-сервер. В результате должно получиться:

… особенно важно Глобальное значение, т.к. от него «пляшут» все по умолчанию.

Как правило, этого вполне достаточно для перевода всей системы MySQL-сервера в 1251 кодировку, т.к. все остальные объекты MySQL-сервера будут воспринимать установку по умолчанию. БД установится в 1251 потому, что сервер в 1251, таблицы будут создаваться в 1251, потому что БД и 1251. Поля будут в 1251, потому что таблица в 1251 и т.п.

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

  • переменная пишется с разделением слов знаком подчеркивания: default_character_set
  • написание параметра в конфиг-файле вместо знака подчеркивания знак «тире»: default-character-set
  • параметром командной строки при запуске сервера знаком подчеркивания:
shell>  mysqld --variable1_name=Variable1Value 
--variable2_name=Variable2Value 
--variable3_name=Variable3Value

Для установки глобальных параметров MySQL-сервера (равнозначные команды):

mysql> SET GLOBAL collation_server=cp1251_general_ci;
mysql> SET @@global.collation_server=cp1251_general_ci;

Полный список переменных смотри:

SHOW VARIABLES


January 5, 2013


Posted by:

gaHcep


Category:

MySQL, Unicode

Сегодня речь пойдет о MySQL и о настройке UTF8 кодировки по-умолчанию.
Тема заезжена, но как я убедился за прошедшую неделю, мало кто в состоянии нормально пояснить какие параметры и куда надо прописать для полноценной работы с UTF8 в MySQL. К сожалению, ситуация на тематических блогах оставляет желать лучшего. Основной тип ответа — приведение соедржимого конфигурационного файла с комментарием типа “попробуй, у меня это работает”.

Основная цель данного поста — выяснить, какие параметры и с какими значениями следует прописать в конфигурационный файл my.cnf (my.ini) для дальнейшей беспроблемной работы с Юникодом.

Рабочее окружение

UTF8 на данный момент у меня успешно работает в Мастер-Слейв конфигурации:

  • MySQL версии 5.1.66
  • Два сервера CentOS версии 6.3
  • Репликация между серверами Master-Slave на базе SSL

Любой внешний клиент в состоянии корректно работать с UTF8 базой (проверено на EMS Manager for MySQL c Windows 8 x64).

Все опции и настройки я привожу для версии сервера 5.1.x, однако с минимальными (а то и вовсе без оных) изменениями все это будет работать и на версиях 5.5.x и 5.6.x.

Параметры кодировок MySQL

Довольно часто приходится видеть в ответах на вопросы о настройке UTF8 следующее:

[mysqld]
init_connect='SET collation_connection = utf8_general_ci'
init_connect='SET NAMES utf8'
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci
skip-character-set-client-handshake 

Предполагается, что после вставки всего этого добра (тут кстати есть противоречащие друг другу опции) в конфигурационный файл my.cnf (my.ini) магический Юникод начнет работать.

Но давайте забудем о списке и попытаемся разбираться со всеми опциями сами и начнем с самого начала. То есть с документации. Потому как все это прекрасно описано в документации MySQL на официальном сайте. Я лишь постараюсь последовательно рассказать о параметрах сервера и прояснить неясные моменты.

Главный раздел по описанию кодировок (character sets) и их представлений (collations — используется например при сортировке) в контексте сервера, базы, таблиц — это секция 10.1.3. Specifying Character Sets and Collations.

Символьная кодировка может быть задана для:

  1. сервера,
  2. базы данных,
  3. таблицы и
  4. колонок в таблице.

Сделано это для гибкой настройки баз данных и доступа клиентов с разными кодировками. Однако, последнее не входит в область рассмотрения данного поста, поэтому будем рассматривать вариант с кодировкой UTF8 настроенной для всего по-умолчанию.

Все параметры могут быть переданы серверу тремя разными способами:

  1. через командную строку mysqld
  2. через конфигурационный файл my.cnf (my.ini)
  3. через опции компиляции.

Второй и третий варианты рассматриваться не будут. Тут уместно будет просто прочитать официальные доки — в каждом разделе приведены примеры конфигурации с использованием всех трех способов. Я же буду использовать первый вариант.

Кодировка (character set) и представление (collation) сервера

Секция 10.1.3.1. Server Character Set and Collation

Кодировка (characher set) — набор используемых символов.
Представление (collation) — набор правил для сравнения символов в наборе.

Тут есть несколько фундаментальных вещей которые надо понимать.

Основные параметры используемые в контексте сервера — это character_set_server и collation_server. Оба параметра влияют на определение кодировки и отображения сервера MySQL.

Можно задать оба параметра либо только один из них. При этом важно знать как задача того или иного влияет на определение отсутствующего:

  • Не заданы — используются значения по умолчанию (дефолтные),

  • Заданы оба — используются указанные кодировка и ее представление,

  • Задана только кодировка — ее представление выставляется по умолчанию для данного типа кодировки. Что это значит? Для каждого типа кодировки есть ее дефолтное представление, например, дефолтная кодировка сервера — latin1, а дефолтное отображение для нее — latin1_swedish_ci.
    Посмотреть соответствие кодировки и ее дефолтного представления можно используя команду:

    SHOW COLLATION LIKE ‘your_character_set_name’;

    Пример:

    mysql> SHOW COLLATION LIKE ‘latin1%’;

     +-------------------+---------+----+---------+----------+---------+
     | Collation         | Charset | Id | Default | Compiled | Sortlen |
     +-------------------+---------+----+---------+----------+---------+
     | latin1_german1_ci | latin1  |  5 |         | Yes      |       1 |
     | latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       1 |
     | latin1_danish_ci  | latin1  | 15 |         | Yes      |       1 |
     | latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
     | latin1_bin        | latin1  | 47 |         | Yes      |       1 |
     | latin1_general_ci | latin1  | 48 |         | Yes      |       1 |
     | latin1_general_cs | latin1  | 49 |         | Yes      |       1 |
     | latin1_spanish_ci | latin1  | 94 |         | Yes      |       1 |
     +-------------------+---------+----+---------+----------+---------+
    

Поле Default дает ответ о представлении выбранной кодировки.

В нашем случае, при настройке дефолтной кодировки в UTF8, параметры должны быть определены, так как могут быть использованы при определении кодировки или представления базы данных:

Наши команды:
my.cnf (my.ini)

[mysqld]
character-set-server = utf8
collation-server = utf8_unicode_ci

Дефолтное представление для utf8 — utf8_general_ci, так что если бы мы его использовали вместо utf8_unicode_ci, то параметр collation_server можно было бы вообще опустить.

Кодировка (character set) и представление (collation) базы данных

Секция 10.1.3.2. Database Character Set and Collation
Секция 10.1.4. Connection Character Sets and Collations

Тут есть два варианта определения кодировки и представления:

  • явно — при выполнении запроса на создание базы данных:

    CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_swedish_ci;

  • неявно через переменные character_set_database и collation_database.
    Однако, эти переменные нельзя задать явно ни в командной строке ни в конфигурационном файле. Как они инициализируются — чуть ниже.

Вообще при работе с базой данных огромную роль помимо серверных настроек играют настройки клиент-серверного соединения (connection). На этом этапе вступают в игру следующие специфичные для соединения параметры:

  • character_set_client — кодировка в которой посылается запрос от клиента
  • character_set_connection — кодировка используемая для конвертации пришедшего запроса (statement’а)
  • character_set_results — кодировку, в которую сервер должен перевести результат перед его отправкой клиенту

Есть еще представление кодировки соединения (colation_connection). Для чего нужен этот параметр думаю пояснять не надо.

Озадачиваться проблемой инициализации всех этих переменных не стоит (хотя в нашем случае присвоить им значения необходимо).
Есть способ проще: существует два типа запросов (statements) которые задают настройки соединения клиента с сервером группой:

Запрос SET NAMES ‘charset_name’ [COLLATE ‘collation_name’]

Параметр определяет в какой кодировке теперь будут приходить сообщения для сервера от клиента. Прелесть в том, что запрос SET NAMES x эквивалентен следующей группе:

SET character_set_client = x;
SET character_set_results = x;
SET character_set_connection = x;

Для определении представления кодировки соединения (colation_connection) отличного от дефолтного, следует дополнить запрос:

SET NAMES x COLLATE y

А так как у нас utf8 и ее дефолтное представление utf8_general_ci, то нам нужно выпонить полный запрос:

SET NAMES utf8 COLLATE utf8_unicode_ci

Таким образом, используя только этот запрос, можно добиться корректной UTF8 инициализации соединения.

Однако, тут есть один нюанс:

SET NAMES x, как понятно из определения, определяет настройку клиента при коннекте к серверу. Но что делать, если клиент — сам mysql.exe и нам хочется установить collation_connection по-умолчанию, не выполняя каждый раз SET NAMES x при коннекте?
Для этих целей, существует еще один параметр — default_character_set.
Он эквивалентен запросу SET NAMES utf8. В случае его использования задать collation_connection отличный от дефолтного уже не получится, поэтому придется заюзать еще одну команду init_connect (так как напрямую collation_connection нельзя прописать в конфигурационном файле):

init_connect=‘SET collation_connection = utf8_unicode_ci’

Но и тут есть еще одно но: init_connect команда не выполняется для SUPER пользователей — пользователей, обладающих привилегией SUPER. root входит в этот перечень, поэтому при коннекте root’ом команду SET collation_connection = utf8_unicode_ci все же придется выполнить вручную.

Запрос SET CHARACTER SET charset_name

Запрос групповой и он также эквивалентен следующей группе:

SET character_set_client = x;
SET character_set_results = x;
SET collation_connection = @@collation_database;

Согласно документации, разница между двумя запросами в том, что параметры character_set_connection и collation_connection будут установлены на @@character_set_database и @@collation_database соответственно (выше я про них упоминал).

За более детальной информацией отсылаю по двум источникам — собственно к официальной документации и прекрасно оформленному ответу на stackoverflow.com.
Для нашей задачи вполне хватает первого параметра вместе с дополнительной командой.

Подытожим: различные сценарии и что юзается на каждом из них — относительно к настройкам соединения:

  • Если к базе коннектится mysql.exe клиент с пользователем с привилегией SUPER:
    • срабатывает опция в конфигурационном файле default_character_set = utf8
    • надо выполнить вручную команду init_connect='SET collation_connection = utf8_unicode_ci'
  • Если к базе коннектится mysql.exe клиент с пользователем без привилегии SUPER:
    • срабатывает опция в конфигурационном файле default_character_set = utf8
    • срабатывает команда в конфигурационном файле init_connect='SET collation_connection = utf8_unicode_ci'
  • Если к базе коннектится внешний клиент:
    • надо выполнить вручную команду SET NAMES utf8 COLLATE utf8_unicode_ci

Наши команды:
my.cnf (my.ini)

[client]
default_character_set = utf8

[mysqld]
init_connect=‘SET collation_connection = utf8_unicode_ci’

Кодировка (character set) и представление (collation) таблиц

Секция 10.1.3.3. Table Character Set and Collation

Тут все довольно просто. Задать кодировку и ее представление можно через команды:

CREATE TABLE t1 ( … )
CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Тут главное иметь в виду, что если эти настройки не заданы, то берутся настройки базы данных (см. пред. раздел). Нам эти настройки не интересны.

Кодировка (character set) и представление (collation) колонок в таблице

Секция 10.1.3.4. Column Character Set and Collation

Тут по аналогии с пред. секцией. Если параметры кодировок не указаны, берутся те, что указывались для таблицы.

Прежде чем перейти к след. разделу, должен сказать, что все команды и запросы относятся к указанной версии MySQL и в случае возникновения каких-либо проблем советую обратиться к соответствующей версии документации.

skip-character-set-client-handshake

Помимо освещенных параметров, есть еще один довольно часто фигурирующий в разного рода источниках — skip-character-set-client-handshake. Установка этого параметра позволит проигнорировать информацию клиента о кодировке. Я данный параметр не использовал.

Верификация настроек

Итак, вот финальный snapshot наших изменений в файле my.cnf (my.ini):

[mysqld]
init_connect=‘SET collation_connection = utf8_unicode_ci’
character-set-server = utf8
collation-server = utf8_unicode_ci

[client]
default-character-set = utf8

После применения всех опций и рестарта сервера mysql для проверки настроек можно воспользоваться командами SHOW VARIABLES LIKE 'char%' и SHOW VARIABLES LIKE 'collation%';

Состояние среды до изменений:

mysql> SHOW VARIABLES LIKE'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

Состояние среды после изменений (в случае, если вы приконнектились не SUPER пользователем):

mysql> SHOW VARIABLES LIKE 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| 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> SHOW VARIABLES LIKE 'collation%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | utf8_unicode_ci |
| collation_database   | utf8_unicode_ci |
| collation_server     | utf8_unicode_ci |
+----------------------+-----------------+

Для примера, вот отличие при соединении через mysql.exe пользователем с и без привилегии SUPER:

с привилегией:

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | **utf8_general_ci** |
| collation_database   | utf8_unicode_ci |
| collation_server     | utf8_unicode_ci |
+----------------------+-----------------+

с привилегией и выполненной вручную командой ‘SET collation_connection = utf8_unicode_ci’:

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | utf8_unicode_ci |
| collation_database   | utf8_unicode_ci |
| collation_server     | utf8_unicode_ci |
+----------------------+-----------------+

без привилегии:

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | utf8_unicode_ci |
| collation_database   | utf8_unicode_ci |
| collation_server     | utf8_unicode_ci |
+----------------------+-----------------+

Поздравляю, теперь ваши база, таблицы и все в таблицах по-умолчанию в кодировке UTF8.


Ссылки

  1. Официальное руководство MySQL версии 5.1
  2. Отличие utf8_unicode_ci от utf8_general_ci
  3. “MySQL Character Set Support” на informit.com позволит вам больше узнать о том что есть characher set и collation.

« Previous Blog Post | Back to top | Next Blog Post »


comments powered by Disqus

This question already has a lot of answers, but Mathias Bynens mentioned that ‘utf8mb4’ should be used instead of ‘utf8’ in order to have better UTF-8 support (‘utf8’ does not support 4 byte characters, fields are truncated on insert). I consider this to be an important difference. So here is yet another answer on how to set the default character set and collation. One that’ll allow you to insert a pile of poo (💩).

This works on MySQL 5.5.35.

Note, that some of the settings may be optional. As I’m not entirely sure that I haven’t forgotten anything, I’ll make this answer a community wiki.

Old Settings

mysql> SHOW VARIABLES LIKE 'char%'; SHOW VARIABLES LIKE 'collation%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)

Config

# 💩 𝌆
# UTF-8 should be used instead of Latin1. Obviously.
# NOTE "utf8" in MySQL is NOT full UTF-8: http://mathiasbynens.be/notes/mysql-utf8mb4

[client]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

[mysql]
default-character-set = utf8mb4

New Settings

mysql> SHOW VARIABLES LIKE 'char%'; SHOW VARIABLES LIKE 'collation%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_general_ci |
| collation_database   | utf8mb4_unicode_ci |
| collation_server     | utf8mb4_unicode_ci |
+----------------------+--------------------+
3 rows in set (0.00 sec)

character_set_system is always utf8.

This won’t affect existing tables, it’s just the default setting (used for new tables).
The following ALTER code can be used to convert an existing table (without the dump-restore workaround):

ALTER DATABASE databasename CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Edit:

On a MySQL 5.0 server: character_set_client, character_set_connection, character_set_results, collation_connection remain at latin1. Issuing SET NAMES utf8 (utf8mb4 not available in that version) sets those to utf8 as well.


Caveat:
If you had a utf8 table with an index column of type VARCHAR(255), it can’t be converted in some cases, because the maximum key length is exceeded (Specified key was too long; max key length is 767 bytes.). If possible, reduce the column size from 255 to 191 (because 191 * 4 = 764 < 767 < 192 * 4 = 768). After that, the table can be converted.

I am trying to connect to my MYSQL database using a utf8mb4 charset (Note the global settings for the database charset is already utf8mb4).

I can do this quite easily using the CLI like so:

mysql -h myhostname -u myuser -p --default-character-set=utf8mb4

When I do the following query:

SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';

I get the correct output as expected:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_general_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+

However, when I connect to my MySQL database using MySQL Workbench, and perform the same query I get the following:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8               |
| character_set_connection | utf8               |
| character_set_database   | latin1             |
| character_set_filesystem | binary             |
| character_set_results    | utf8               |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8_general_ci    |
| collation_database       | latin1_swedish_ci  |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+

The issue here is that I am struggling to change the default-character-set in MySQL Workbench GUI. I tried appending the following:

default-character-set=utf8mb4

in Manage Server Connections > Connection > Advanced > Others section,

but does not seem to have any affect.

How can I change the default character set on the MySQL Workbench GUI.

I am trying to connect to my MYSQL database using a utf8mb4 charset (Note the global settings for the database charset is already utf8mb4).

I can do this quite easily using the CLI like so:

mysql -h myhostname -u myuser -p --default-character-set=utf8mb4

When I do the following query:

SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';

I get the correct output as expected:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_general_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+

However, when I connect to my MySQL database using MySQL Workbench, and perform the same query I get the following:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8               |
| character_set_connection | utf8               |
| character_set_database   | latin1             |
| character_set_filesystem | binary             |
| character_set_results    | utf8               |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8_general_ci    |
| collation_database       | latin1_swedish_ci  |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+

The issue here is that I am struggling to change the default-character-set in MySQL Workbench GUI. I tried appending the following:

default-character-set=utf8mb4

in Manage Server Connections > Connection > Advanced > Others section,

but does not seem to have any affect.

How can I change the default character set on the MySQL Workbench GUI.

В данной статей рассказывается о переход к новому набору символов utf8mb4 в MySQL для поддержки хранения 4-х байтовых символов.

Шаг  1 — резервные копии

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

Шаг 2 — версия MySQL сервера

Набор символов utf8mb4 введён в MySQL начиная с версии 5.5.3, по этому, вам необходимо обновить версию MySQL сервера, если она ниже указанной, либо попросить это сделать своего системного администратора.

Шаг 3 — модификация базы, таблиц, столбцов

Измените набор символов и сравнение для базы данных, таблиц и столбцов на utf8mb4 вместо utf8. Для этого выполните следующие запросы:

Для базы данных:

ALTER DATABASE название_базы CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

Для каждой таблицы:

ALTER TABLE название_таблицы CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Для каждого столбца (не нужно копировать этот пример, для каждого столбца будет свой запрос, здесь указан лишь пример такого запроса для столбца с `VARCHAR`):

ALTER TABLE название_таблицы CHANGE название_столбца название_столбца VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Шаг 4 — проверка максимальной длины столбцов и ключей индексов

Самый трудный шаг на пути к корвертированию MySQL базы данных.

При конвертировании базы данных из utf8 в utf8mb4 максимальная длина столбцов или ключей индексов в байтах остаётся неизменной. Таким образом, она становится меньше в количестве символов, т.к. максимальная длина символа теперь 4 байта, вместо 3.

Например, TINYTEXT столбец может вместить до 255 байт, что коррелирует 85 3-х байтовым или 63 4-х байтовым символам. Допустим у вас есть TINYTEXT столбец, который использует utf8 набор символов, но должен содержать в себе больше 63 символов. Учитывая эти данные, вы не сможете конвертировать этот столбец в utf8mb4, до тех пор, пока не измените тип данных на более вместительный, например TEXT — потому, что, если вы попытаетесь заполнить столбец 4-х байтовыми символами, вы сможете вместить только 63 символа, но не более.

Тоже самое касается ключей индексов. Механизм хранения InnoDB имеет максимальную длину индекса 767 байт, поэтому для utf8 или utf8mb4 столбцов, вы можете инжексировать 255 или 191 символов, соответственно. Если у вас есть utf8 столбцы с индексами, длина которых превышает 191 символ, при использовании utf8mb4 вам нужно будет индексировать меньшее количество символов.

Например:

col1 VARCHAR(500) CHARACTER SET utf8, INDEX (col1(255))

Запрос при использовании utf8mb4 будет выглядеть вот так:

col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))

Шаг 5 — изменение настроек сервера

В конфигурационном файле MySQL необходимо изменить набор символов на utf8mb4:

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

Вы можете легко проверить корректность работы применимых настроек:

mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_unicode_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

Видно, что все соответствующие параметры заданы в utf8mb4, кроме character_set_filesystem, который всегда будет двоичным и character_set_system, который всегда в utf8 и не может быть изменён.

Шаг 6 — восстановление и оптимизация всех таблиц

После обновления версии MySQL сервера и применения описанных выше действий, необходимо произвести восстановление и оптимизацию всех баз данных и таблиц. Для этого вы можете выполнить следующие запросы для каждой таблицы:

REPAIR TABLE table_name;
OPTIMIZE TABLE table_name;

С использованием команды mysqlcheck

$ mysqlcheck -u root -p --auto-repair --optimize --all-databases

Итог

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

Копирование статьи без указания прямой ссылки на первоисточник — http://invisionbyte.ru строго запрещено!

  1. Доступные статьи

  2. MySQL

  3. Кодировки в MySQL

Работа с кодировками в MySQL 4.1.11 и выше

  1. Тестовая машина
  2. Устанавливаем MySQL
  3. Начало работы
  4. Разумные выводы
  5. Настройка кодировок
    • Через names
    • Через системные переменные
    • Через настройки сервера
  6. Что делать, если данные внесены в неправильной кодировке
  7. Правильный вариант работы с MySQL

Полезность первоисточника информации трудно переоценить, поэтому не поленитесь и скачайте полный мануал от разработчиков MySQL — http://dev.mysql.com/doc/

Тестовая машина

test# uname -a
FreeBSD test.dm 7.0-RELEASE FreeBSD 7.0-RELEASE #1: 
Fri May  9 15:40:21 YEKST 2008     zg@test.dm:/usr/obj/usr/src/sys/GATE  i386
test#

Устанавливаем MySQL 5.1

test# pkg_add -r mysql51-server
Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/
packages-7.0-release/Latest/mysql51-server.tbz... Done.
Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/
packages-7.0-release/All/mysql-client-5.1.22.tbz... Done.
Added group "mysql".
Added user "mysql".

************************************************************************

Remember to run mysql_upgrade (with the optional --datadir=<dbdir> flag)
the first time you start the MySQL server after an upgrade from an
earlier version.

************************************************************************

test# echo mysql_enable="YES" >> /etc/rc.conf
test# cp /usr/local/share/mysql/my-large.cnf /etc/my.cnf
test# /usr/local/etc/rc.d/mysql-server start
Starting mysql.
test# sockstat | grep mysql
mysql    mysqld     1154  13 tcp4   *:3306                *:*
mysql    mysqld     1154  14 stream /tmp/mysql.sock
test#

Пускай это не самый «правильный» способ установки MySQL-сервера, зато быстрый и рабочий.

Начало работы

Итак, sockstat показала, что сервер работает, а установка говорит о том, что сервер абсолютно девственный. Чем это грозит? Кодировки по умолчанию выставлены англоязычные, а значит, будут проблемы при использовании кирилицы. Но как это распознать? Проверяем:

test# mysql
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 2
Server version: 5.1.22-rc-log FreeBSD port: mysql-server-5.1.22

Type 'help;' or 'h' for help. Type 'c' to clear the buffer.

mysql> use test;
Database changed
mysql> create table `test` (`field` VARCHAR(60));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into `test` values ('иван'), ('родил'), ('девчёнку');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>

Первым делом используем тестовую базу, которая уже есть на сервере, затем создаём в ней таблицу и вставляем в неё три слова на русском, про кодировки мы пока ничего не знаем и знать не хотим ))).

Пока всё хорошо и радужно, никаких ошибок нет, пробуем сделать выборку:

mysql> select * from `test`;
+----------+
| field    |
+----------+
| иван     |
| родил    |
| девчёнку |
+----------+
3 rows in set (0.01 sec)

mysql> select * from `test` where `field` like "иван";
+-------+
| field |
+-------+
| иван  |
+-------+
1 row in set (0.00 sec)

Как видно, запросы работают абсолютно корректно, так где же грабли?… Оказывается мы на них уже стоим:

mysql> select * from `test` order by `field` DESC;
+----------+
| field    |
+----------+
| девчёнку |
| родил    |
| иван     |
+----------+
3 rows in set (0.01 sec)

Запрос на выборку с обратной сортировкой привёл к тому, что записи просто вывелись в обратном порядке, но не по алфавиту… До удара граблей остаются считанные секунды, но пока растянем удовольствие :) Сперва ответим на вопрос — почему поля не сортируются по алфавиту? У MySQL имеется мощный и богатый механизм для работы с интернациональными наборами символов, но.. но откуда MySQL узнает, что наши символы — есть русский алфавит, мы же качали английскую версию? Ничего не остаётся, как идти ковырять мануал на предмет кодировок…

После того, как загрузился 16-метровый мануал, можно не полениться и прочитать первые пару-тройку страниц с оглавлением )), а можно просто сделать поиск на предмет charset или character set. Не суть важно, но через некоторое время можно найти раздел 9.1.2. Character Sets and Collations in MySQL, в котором написано много и интересно, а, главное, содержательно про то, каким образом можно и нужно работать с кодировками.

Расставляя точки над и, Character Set — транслируется как «кодировка», а Collation — сравнение. В чём разница? Сравнение — это правила сравнения букв кодировки. Сравнения работают только в рамках кодировки, и нельзя сравнивать данные в латинице по правилам кирилицы. Поясню на примере: мы, как увидим позже, внесли данные в таблицу на латинице, а сортировать нужно на кирилице, для чего можно использовать ключевое слово collate:

mysql> select * from `test` order by `field` collate cp1251_general_ci DESC;
ERROR 1253 (42000): COLLATION 'cp1251_general_ci' is not valid for CHARACTER SET 'latin1'
mysql>

MySQL отказывается это делать… но почему? Потому, что latin1 не поддерживает сравнение в кирилице, а доступные «сравнения» можно увидеть так:

mysql> show collation like 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         | Yes      |       1 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       1 |
| latin1_danish_ci  | latin1  | 15 |         | Yes      |       1 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       1 |
| latin1_general_ci | latin1  | 48 |         | Yes      |       1 |
| latin1_general_cs | latin1  | 49 |         | Yes      |       1 |
| latin1_spanish_ci | latin1  | 94 |         | Yes      |       1 |
+-------------------+---------+----+---------+----------+---------+
8 rows in set (0.00 sec)

mysql>

Ни о какой кирилице не может идти и речи… Куда копать?.. В создание таблицы!

mysql> show create table `test`;
+-------+-------------------------------------------------+
| Table | Create Table                                    |
+-------+-------------------------------------------------+
| test  | CREATE TABLE `test` (
  `field` varchar(60) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1                    |
+-------+-------------------------------------------------+
1 row in set (0.00 sec)

Ага! По-умолчанию при создании таблицы была взята кодировка latin1, значит, если мы изменим таблицу и укажем ей, что надо использовать кирилистическую кодировку, то всё заработает?… В мануале написан пример про изменение кодировки таблицы, используем его:

mysql> alter table `test` charset "cp1251";
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

Ок! Проверяем, что получилось…

mysql> select * from `test` order by `field` collate cp1251_general_ci DESC;
ERROR 1253 (42000): COLLATION 'cp1251_general_ci' is not valid for CHARACTER SET 'latin1'

Хм.. опять та же ошибка, но откуда ей взяться?!..

mysql> show create table `test`;
+-------+-------------------------------------------------+
| Table | Create Table                                    |
+-------+-------------------------------------------------+
| test  | CREATE TABLE `test` (
  `field` varchar(60) CHARACTER SET latin1 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251                    |
+-------+-------------------------------------------------+
1 row in set (0.00 sec)

Ого, структура таблицы резко изменилась, теперь у неё задана одна кодировка, а у поля совсем другая.. :(( Порыв ещё мануал, можно изменить и кодировку столбца:

mysql> alter table `test` modify `field` varchar(60) charset "cp1251";
Query OK, 3 rows affected, 3 warnings (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> show create table `test`;
+-------+------------------------------------------+
| Table | Create Table                             |
+-------+------------------------------------------+
| test  | CREATE TABLE `test` (
  `field` varchar(60) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251             |
+-------+------------------------------------------+
1 row in set (0.01 sec)

Ну вот!!! Злой кодировки latin1 нет и в помине, можно проверять наш роддом )))

mysql> select * from `test` order by `field` collate cp1251_general_ci DESC;
+----------+
| field    |
+----------+
| ???????? |
| ?????    |
| ????     |
+----------+
3 rows in set (0.00 sec)

И вот тот страшный удар граблями, который так долго оттягивался! Внимательный читатель мог заметить, что когда была сделана попытка принудительно сменить кодировку столбца, содержащего данные в latin1, то на каждую запись, содержащую русские буквы, у MySQL был варнинг! Это был крик о том, что сервер не знает, каким образом можно перевести данные из latin1 в cp1251, ну и лучшего способа, чем заменить символы не latin1 вопросиками, он не нашёл :))). Роддом безвозвратно потерян потому, что теперь вместо кирилицы в базе содержатся вопросики..

Вопросиков можно было избежать

На самом деле, ситуация, когда изначально выставлена неправильная кодировка, встречается сплошь и рядом. Симптомы можно выявить следующим образом:

mysql> show variables like "char%";
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | latin1                           |
| character_set_connection | latin1                           |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | latin1                           |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

Именно эти переменные отвечают за дефолтные значения кодировок.

  • character_set_client — кодировка, в которой данные будут поступать от клиента
  • character_set_connection — кодировка по умолчанию для всего, что в рамках соединения не имеет кодировки
  • character_set_database — кодировка по умолчанию для баз
  • character_set_filesystem — кодировка для работы с файловой системой (LOAD DATA INFILE, SELECT … INTO OUTFILE, и т.д.)
  • character_set_results — кодировка, в которой будет выбран результат
  • character_set_server — кодировка, в которой работает сервер
  • character_set_system — кодировка, в которой задаются идентификаторы MySQL, всегда UTF8
  • character_sets_dir — папка с кодировками

ВАЖНО: Если character_sets_dir установлена неверно, то работа с кодировками будет под угрозой. Не пытайтесь менять её значение, если вы неуверены в своих силах. Если вы системный администратор, то перед установкой лучше ознакомиться с мануалом.

Наиболее значимые для простых пользователей следующие переменные: character_set_client, character_set_results, character_set_connection. Поскольку именно они отвечают за внесение, извлечение информации и создание таблиц/баз соответственно. Какими они могут быть?

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
| dec8     | DEC West European           | dec8_swedish_ci     |      1 |
| cp850    | DOS West European           | cp850_general_ci    |      1 |
| hp8      | HP West European            | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |      1 |
| latin1   | cp1252 West European        | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European | latin2_general_ci   |      1 |
| swe7     | 7bit Swedish                | swe7_swedish_ci     |      1 |
| ascii    | US ASCII                    | ascii_general_ci    |      1 |
| hebrew   | ISO 8859-8 Hebrew           | hebrew_general_ci   |      1 |
| koi8u    | KOI8-U Ukrainian            | koi8u_general_ci    |      1 |
| greek    | ISO 8859-7 Greek            | greek_general_ci    |      1 |
| cp1250   | Windows Central European    | cp1250_general_ci   |      1 |
| latin5   | ISO 8859-9 Turkish          | latin5_turkish_ci   |      1 |
| armscii8 | ARMSCII-8 Armenian          | armscii8_general_ci |      1 |
| utf8     | UTF-8 Unicode               | utf8_general_ci     |      3 |
| cp866    | DOS Russian                 | cp866_general_ci    |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak  | keybcs2_general_ci  |      1 |
| macce    | Mac Central European        | macce_general_ci    |      1 |
| macroman | Mac West European           | macroman_general_ci |      1 |
| cp852    | DOS Central European        | cp852_general_ci    |      1 |
| latin7   | ISO 8859-13 Baltic          | latin7_general_ci   |      1 |
| cp1251   | Windows Cyrillic            | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic              | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic              | cp1257_general_ci   |      1 |
| binary   | Binary pseudo charset       | binary              |      1 |
| geostd8  | GEOSTD8 Georgian            | geostd8_general_ci  |      1 |
+----------+-----------------------------+---------------------+--------+
26 rows in set (0.00 sec)

Любую из этих кодировок можно пользовать на свой вкус. Обычно русскоязычные пользователи предпочитают cp1251 или utf8, но по сути, неважно, в какой кодировке хранятся данные, важно, чтобы она была изначально правильно указана и данные были корректно внесены.

Настройка кодировок

Мануал предлагает нам три варианта задания кодировок:

  1. Через names
  2. Через непосредственно переменные character_set_*
  3. Через настройки самого сервера

ВНИМАНИЕ!!! Первые два варианта работают только в рамках текущего соединения. Это значит, что при следующем подключении все настройки вернутся в начальное состояние! Чтобы не выставлять кодировку каждый раз, нужно воспользоваться третьим вариантом.

Вариант 1 — Через names

mysql> set names 'cp1251';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | cp1251                           |
| character_set_connection | cp1251                           |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | cp1251                           |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

Ну, тут всё ясно, три самые нужные кодировки в одном )))

Вариант 2 — Через непосредственно переменные character_set_*

mysql> set @@character_set_client='cp1251';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | cp1251                           |
| character_set_connection | latin1                           |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | latin1                           |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.01 sec)

Более детальная настройка, чем names.

Вариант 3 — Через настройки самого сервера

Тут можно пойти двумя путями — либо через конфиг файл:

---- Файл my.cnf
[client]
# Для местного клиента
default-character-set=cp1251
....

[mysqld]
# Для всего сервера
default-character-set=cp1251
....

либо

shell> mysqld --character-set-server=cp1251

Ещё можно при конфигурировании задать кодировку по умолчанию

shell> ./configure --with-charset=latin1

Но лучше, когда кодировка настраивается прямо в соединении.

Что делать, если данные внесены в неправильной кодировке

Если база/таблица/данные были созданы/внесены в кодировке отличной от нужной, то необходимо сделать следующее:

  1. Создать бэкап базы данных
  2. Создать текстовый дамп базы в SQL-запросах (mysqldump или PhpMyAdmin)
  3. С помощью текстового редактора исправить вхождения неверной кодировки на нужную (а лучше попросту удалить всю информацию о кодировках и сравнениях)
  4. Удалить базу/таблицу
  5. Выставить нужную кодирвку на клиента/соединение
  6. Импортировать данные исправленного SQL-дампа

Этот вариант подходит почти для всех случаев, за исключением некоторых особых ситуаций, например, когда сравнение, выставленное по-умолчанию, не уместно для некоторых полей. Пример — поле для хранения пароля, необходимо сравнивать его с учётом регистра, тогда как по-умолчанию выставляется сравнение без учёта регистра.

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | latin1                           |
| character_set_connection | latin1                           |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | latin1                           |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

## Кодировки выставлены неверно, нужно их настроить
mysql> set names 'koi8r';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | koi8r                            |
| character_set_connection | koi8r                            |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | koi8r                            |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

## Я работаю через koi8r, поэтому и выставляю её, 
## но данные в таблице буду хранить в cp1251
mysql> create table `test2` (`field` varchar(60)) charset cp1251;
Query OK, 0 rows affected (0.01 sec)

## Проверяем, всё ли в порядке
mysql> show create table `test2`;
+-------+--------------------------------------------+
| Table | Create Table                               |
+-------+--------------------------------------------+
| test2 | CREATE TABLE `test2` (
  `field` varchar(60) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251
+-------+--------------------------------------------+
1 row in set (0.01 sec)

## Вносим данные 
mysql> insert into `test2` values ('и раз'), ('Два'),('три'), ('И ять'), ('шесть');
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

## Проверяем сортировки
## В обычном сравнении "И" и "и" одинаковы, поэтому 
## сравнение идёт до первого отличного символа
mysql> select * from `test2` order by `field` collate cp1251_general_ci ASC;
+-------+
| field |
+-------+
| Два   |
| и раз |
| И ять |
| три   |
| шесть |
+-------+
5 rows in set (0.01 sec)

## В бинарном сравнении "И" меньше чем "и", поскольку у неё код меньше
mysql> select * from `test2` order by `field` collate cp1251_bin ASC;
+-------+
| field |
+-------+
| Два   |
| И ять |
| и раз |
| три   |
| шесть |
+-------+
5 rows in set (0.00 sec)

Таким образом, клиент работает в KOI8-R, но данные хранятся в cp1251, MySQL знает об этом и делает перекодировку на лету.

Ну и на посошок:

mysql> set character_set_results='cp1251';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from `test2`;
+-------+
| field |
+-------+
| Х ПЮГ |
| дБЮ   |
| РПХ   |
| х ЪРЭ |
| ЬЕЯРЭ |
+-------+
5 rows in set (0.00 sec)

Выбирать данные можно в любой кодировке, так же, как и вносить, главное — правильно сообщить об этом MySQL.


Понравилась статья? Поделить с друзьями:
  • Certbot error unrecognized arguments preferred chain isrg root x1
  • Certbot error getting validation data
  • Character set database как изменить
  • Character set client как изменить
  • Character error rate python