Подтвердить что ты не робот

MySQL utf8mb4, Ошибки при сохранении Emojis

Я пытаюсь сохранить имена пользователей из службы в моей базе данных MySQL. Эти имена могут содержать смайлики, такие как 🙈😂😱🍰 (только для примера)

После небольшого поиска я обнаружил, что этот стекопоток связан с этим руководством. Я следовал за шагами, и похоже, что все настроено правильно.

У меня есть база данных (набор символов и сопоставление, равные utf8mb4 (_unicode_ci)), таблица с именем TestTable, также настроенная таким образом, а также столбец "Текст", настроенный таким образом (VARCHAR (191) utf8mb4_unicode_ci).

Когда я пытаюсь сохранить эмодзи, я получаю сообщение об ошибке:

Example of error for shortcake (🍰):
    Warning: #1300 Invalid utf8 character string: 'F09F8D'
    Warning: #1366 Incorrect string value: '\xF0\x9F\x8D\xB0' for column 'Text' at row 1

Единственное эмодзи, которое мне удалось спасти, это солнце was

Хотя я не пытался все из них, чтобы быть честным.

Что-то мне не хватает в конфигурации?

Обратите внимание: все тесты сохранения не были связаны с клиентской стороной. Я использую phpmyadmin, чтобы вручную изменить значения и сохранить данные. Поэтому о правильной конфигурации клиентской части я буду заботиться после того, как сервер должным образом сохранит эмодзи.

Еще одно замечание: в настоящее время при сохранении смайликов я либо получаю ошибку, как указано выше, либо не получаю ошибку, и данные имени Username 🍰 будут сохранены как Username???? , Ошибка или нет ошибки зависит от того, как я сохраняю. При создании/сохранении с помощью оператора SQL я сохраняю с вопросительными знаками, при редактировании inline я сохраняю с вопросительными знаками, при редактировании с помощью кнопки редактирования я получаю ошибку.

благодарю вас

РЕДАКТИРОВАТЬ 1: Хорошо, так что я думаю, что я обнаружил проблему, но не решение. Похоже, что конкретные переменные базы данных не изменились должным образом.

Когда я вошел в систему как root на моем сервере и считал переменные (глобальные):
Используемый запрос: 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)

Для моей базы данных (в phpmyadmin, тот же запрос) это выглядит следующим образом:

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

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

Изменить 2:

Вот мой файл my.cnf:

[client]
port=3306
socket=/var/run/mysqld/mysqld.sock
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld_safe]
socket=/var/run/mysqld/mysqld.sock

[mysqld]
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
port=3306
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
lc-messages-dir=/usr/share/mysql
log_error=/var/log/mysql/error.log
max_connections=200
max_user_connections=30
wait_timeout=30
interactive_timeout=50
long_query_time=5
innodb_file_per_table
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

!includedir /etc/mysql/conf.d/
4b9b3361

Ответ 1

character_set_client, _connection и _results должны быть utf8mb4 для того, чтобы этот пирог был съедобным.

Что-то, где-то, устанавливает подмножество этих элементов отдельно. Rummage через my.cnf и phpmyadmin настройки - что-то не устанавливает все три.

Если выполняется SET NAMES utf8mb4, все три установлены правильно.

Солнце сияет, потому что оно всего 3 байта - E2 98 80; utf8 достаточно для 3-байтовых кодировок utf8 символов Unicode.

Ответ 2

Вполне вероятно, что ваша служба/приложение соединяется с "utf8" вместо "utf8mb4" для набора символов клиента. Это до клиентского приложения.

Для приложения PHP см. Http://php.net/manual/en/function.mysql-set-charset.php или http://php.net/manual/en/mysqli.set-charset.php.

Для приложения Python см. Https://github.com/PyMySQL/PyMySQL#example или http://docs.sqlalchemy.org/en/latest/dialects/mysql.html#mysql-unicode.

Также убедитесь, что ваши столбцы действительно utf8mb4. Один прямой путь таков:

mysql> SELECT character_set_name FROM information_schema.'COLUMNS'  WHERE table_name = "user"   AND column_name = "displayname";
+--------------------+
| character_set_name |
+--------------------+
| utf8mb4            |
+--------------------+
1 row in set (0.00 sec)

Ответ 3

Для меня оказалось, что проблема связана с клиентом mysql.

Обновления клиента mysql my.cnf char на сервере и привели к непреднамеренной настройке символов.

Итак, мне нужно было просто добавить character-set-client-handshake = FALSE. Это отключает настройку клиента из-за нарушения настройки char.

my.cnf будет таким.

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

Надеюсь, что это поможет.

Ответ 4

ALTER TABLE table_name CHANGE column_name column_name VARCHAR (255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, NULL DEFAULT;

пример запроса:

ALTER TABLE 'reactions' CHANGE 'emoji' 'emoji' VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL;

enter image description here

После этого удачно в состоянии хранить смайлики в таблице:

enter image description here

Ответ 5

Я не горжусь этим ответом, потому что он использует грубую силу для очистки ввода. Это жестоко, но это работает

function cleanWord($string, $debug = false) {
    $new_string = "";

    for ($i=0;$i<strlen($string);$i++) {
        $letter = substr($string, $i, 1);
        if ($debug) {
            echo "Letter: " . $letter . "<BR>";
            echo "Code: " . ord($letter) . "<BR><BR>";
        }
        $blnSkip = false;
        if (ord($letter)=="146") {
            $letter = "&acute;";
            $blnSkip = true;
        }
        if (ord($letter)=="233") {
            $letter = "&eacute;";
            $blnSkip = true;
        }
        if (ord($letter)=="147" || ord($letter)=="148") {
            $letter = "&quot;";
            $blnSkip = true;
        }
        if (ord($letter)=="151") {
            $letter = "&#8211;";
            $blnSkip = true;
        }
        if ($blnSkip) {
            $new_string .= $letter;
            break;
        }

        if (ord($letter) > 127) {
            $letter = "&#0" . ord($letter) . ";";
        }

        $new_string .= $letter;
    }
    if ($new_string!="") {
        $string = $new_string;
    }
    //optional
    $string = str_replace("\r\n", "<BR>", $string);

    return $string;
}

//clean up the input
$message = cleanWord($message);

//now you can insert it as part of SQL statement
$sql = "INSERT INTO tbl_message ('message')
VALUES ('" . addslashes($message) . "')";