Пожалуйста, объясните, как Wordpress работает с набором символов MySQL и сопоставлением на низком уровне.

10

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

Я установил Wordpress, следуя инструкциям на их странице установки:

https://codex.wordpress.org/Installing_WordPress

Как часть инструкций, я последовал их совету по созданию базы данных MySQL вручную из командной строки, а именно:

mysql> CREATE DATABASE databasename;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON databasename.* TO "wordpressusername"@"hostname"
-> IDENTIFIED BY "password";
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)

mysql> EXIT

Далее, в соответствии с инструкциями, я отредактировал файл "wp-config.php" для использования набора символов UTF-8:

define( 'DB_CHARSET', 'utf8' );

... и оставил параметр сортировки пустым:

define( 'DB_COLLATE', '' );

Здесь начинается самое интересное ...

  1. Если я введу символ, который не является частью MySQL UTF-8, но является частью UTF-8 MB4, например, 𝌆, в сообщение, оно корректно отображается на отображаемой странице. Я ожидал бы, что этого не произойдет, так как я установил не UTF-8 MB4, а более ограниченный UTF-8 (как определено MySQL, конечно, не так, как обычно понимают).

  2. Если я исследую проблему в MySQL в командной строке, это становится более странным. Если я бегу show variables like 'char%';, я получаю этот ответ:

    +--------------------------+----------------------------+
    | 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/ |
    +--------------------------+----------------------------+
    

Я ожидал бы, что набор символов базы данных будет UTF-8, а не латиницей1.

  1. Если я запускаю команду show variables like 'collation%';, вывод:

    +----------------------+-------------------+
    | Variable_name        | Value             |
    +----------------------+-------------------+
    | collation_connection | utf8_general_ci   |
    | collation_database   | latin1_swedish_ci |
    | collation_server     | latin1_swedish_ci |
    +----------------------+-------------------+
    

Это даже более странно по очевидным причинам (не ожидал, что по умолчанию сортировка latin1_swedish_ci в базе данных UTF-8).

  1. Наконец, если я запускаю show full columns from mywpdatabase.wp_posts;, выходные строки, где значение не NULL, показывают, что сортировка будет:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

Тогда мой вопрос - как это можно объяснить? Почему мой Wordpress правильно устанавливает рендеринг символов UTF-8 MB4, если в конфигурации база данных определена как UTF-8? И почему база данных в MySQL отображается как latin1, шведское сопоставление, а не UTF-8? И как получилось, что, несмотря на все это, отдельные поля в таблице являются utf8mb4_unicode_ci? Низкоуровневое объяснение того, как Wordpress работает с MySQL, было бы очень полезно. Спасибо!

X-Mann
источник

Ответы:

11

В wp-config.php веб-сайта WordPress есть два определения:

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

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

Создание базы данных полностью независимо от создания таблицы. WordPress не создает базу данных и не заботится о наборе символов и сопоставлении по умолчанию, если он может подключаться к базе данных.

Значение «utf8» в первом определении означает наименее ограниченный набор символов из семейства «utf8», которое является либо «utf8», либо «utf8mb4».

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

Ниже перечислены вещи, которые WordPress анализирует для определения своего выбора во время установки:

  • Версия MySQL
  • сопоставление базы данных (в wp-config.php)

На основе версии MySQL WordPress решает, какую группу семейства utf8 использовать. Есть два, отличающихся своими именами: utf8 и utf8mb4 . Наборы символов из группы utf8 , позволяют хранить максимум 3 байта длинных символов. Наборы символов из группы utf8mb4 , позволяют хранить максимум 4 байта длинных символов.

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

Примеры

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

Если MySQL не поддерживает utf8mb4 (более старые версии), тогда набор символов таблиц будет utf8, а параметры сортировки - utf8_general_ci . В противном случае мы можем ожидать utf8mb4 и utf8mb4_unicode_520_ci или utf8mb4_unicode_ci (зависит от версии MySQL) соответственно.

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', 'utf8_polish_ci');

Старая версия MySQL - utf8 и utf8_polish_ci . Более новая версия MySQL - utf8mb4 и utf8mb4_polish_ci ( суффикс _polish_ci приветствуется )

define('DB_CHARSET', 'cp1250');
define('DB_COLLATE', 'cp1250_polish_ci');

Любая версия MySQL - cp1250 и cp1250_polish_ci .

define('DB_CHARSET', 'cp1250');
define('DB_COLLATE', 'utf8_general_ci');

Любая версия MySQL - ошибка (несоответствие набора символов и параметров сортировки)

Резюме

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

Примечание: это объясняет, почему символ 𝌆 был сохранен и получен правильно. Проще говоря , ваш набор символов таблиц принадлежал группе utf8mb4 , а не utf8 .

Фрэнк П. Валентинович
источник
1
Спасибо за объяснение того, как Wordpress устанавливает параметры сортировки, но вы не рассмотрели остальные вопросы. Почему, если набор символов UTF-8 определен, MySQL показывает, что база данных является латинской1? И почему он показывает сортировку базы данных как шведскую? Кроме того, вы, кажется, путаете набор символов и сопоставление. Сортировка определяет только порядок, правила сравнения, а не набор символов. Следовательно, независимо от того, какое сопоставление используется, если UTF-8 является набором символов, символы вне его (как определено в более узком смысле MySQL) не должны отображаться.
X-Mann
Я обновлю свой ответ, чтобы объяснить более четко процесс.
Фрэнк П. Валентинович
1
Спасибо за обновление! Я принял ваш ответ, теперь все ясно. Проблема связана с MySQL и моим отсутствием опыта в этом - я не знал, что таблицы могут использовать более широкий набор символов, чем сама база данных. Эта новая информация успокоила меня. Мне не нужно менять набор символов по умолчанию в MySQL, Wordpress заботится об этом на уровне таблицы.
Икс-Манн
Добро пожаловать. Я рад, что это помогло.
Фрэнк П. Валентинович