"Век живи - век учись".
В свое время перевернул форум в UTF-8, просто воткнул во все возможные места, где-то "utf-8", где-то "utf8". Путаница еще та. Выяснилось, что при сохранении символы расширенного UNICODE (за пределами BMP - Basic Multilingual Plane) просто выкидываются. Например, такое
💩
в базу поместить было нельзя. Нельзя сказать, что я был этим просто потрясен, однако периодически за все полгода, что я это терпел, порывался найти место, где это не работает. Собственно, что виновата база, я нашел только значительно позднее, обвиняя PHP. Вот он не виноват. В PHP UTF-8 подразумевает нормальный юникод, в т.ч. 4-байтный. А в мускуле (MySQL/MariaDB) это исключительно трехбайтная кодировка. Т.е. большинство emoji, например, идут лесом, обрезаясь и превращаясь в вопросики. Я пробовал разные варианты, в том числе
с экранированием, но в случае с уже написанным форумом это повлекло такую лавину связей в коде, что я сложил руки и решил включить 4 байта в MariaDB.
Для начала правим my.conf
Код:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
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)
Включаем кодировку по умолчанию
SQL код:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
Дальше для каждой таблицы необходимо выполнить
SQL код:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Собственно, можно еще для каждой колонки озаботиться
SQL код:
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Но конвертировать, собственно, нечего, поскольку значение наследуется от таблицы.
Я себе скриптик собрал для переворачивания всех таблиц
Код:
mysql --skip-column-names --silent -e"SELECT table_name FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'имя_базы' AND table_collation = 'utf8_general_ci'" | xargs -I{} mysql имя_базы -e"ALTER TABLE {} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
Собственно, нюансов одновременно и очень много в целом, и достаточно мало тех, с которыми вы столкнетесь. Из основных - нельзя сделать общий FULLTEXT индекс на столбцы с разной кодировкой. На некоторых таблицах размерность (а она все так же в байтах считается) может не влезть в четырехкратное увеличение. У меня такие таблицы были в пределах BMP по содержимому, потому я вообще оставил их в utf8.