表情符号作为 MariaDB 主键中的问号

Emojis as question marks in MariaDB primary key

与以下 table, 使用 mariadb-server-10.1 10.1.32+maria-1~trusty:

CREATE TABLE `tags` (
  `tag_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
  `thing_id` int(11) NOT NULL,
  PRIMARY KEY (`thing_id`,`tag_name`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

显示为(在 SQLAlchemy 应用程序中):

IntegrityError: (IntegrityError) 
(1062, "Duplicate entry '1532-?' for key 'PRIMARY'")

在第二次尝试插入表情符号时。

第一个在数据库中似乎没问题(相信我,它在我的控制台和浏览器中显示为 "alien" 表情符号):

> select tag_name, HEX(tag_name) from tags;
+----------+----------------+
| tag_name | HEX(tag_name)  |
+----------+----------------+
| GOODGUY  | 474F4F44475559 |
|         | F09F91BD       |
+----------+----------------+
2 rows in set (0.00 sec)

我知道 Emoji's in mysql turns to question marks ,但是 my.cnf 有:

default-character-set = utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-character-set = utf8mb4

和 utf8mb4 正在客户端中使用(字符集作为 ?charset=utf8mb4 添加到连接字符串)。而且我相信主键是在服务器端检查的。

还有什么我遗漏的吗(可以检查)或者是一些 MariaDB 错误还是需要一些额外的配置?

不确定是否相关,但通过 mysql shell 插入时出现同样的问题。还尝试了这个以查看发生了什么(在 中找到):

> SELECT ''='' COLLATE utf8mb4_unicode_ci;
+------------------------------------+
| '?'='?' COLLATE utf8mb4_unicode_ci |
+------------------------------------+
|                                  1 |
+------------------------------------+

但不确定这是否相关。

我不明白:数据库有时显示正常(通过两个客户端 - shell 和 SQLAlchemy 应用程序),但随后无法在 header 中显示?从我得到的证据来看,我不明白这种糟糕的转换发生在哪里。数据库中的数据似乎没问题(见上面的十六进制),但是两个表情符号相当于主键?

再对比一下:

> SELECT ''='' COLLATE utf8mb4_bin;
+-----------------------------+
| '?'='?' COLLATE utf8mb4_bin |
+-----------------------------+
|                           0 |
+-----------------------------+

这种分指主键不使用二进制?在索引中使用之前,所有表情符号都转换成其他东西了吗?很奇怪。

mysql> SELECT ''='' COLLATE utf8mb4_unicode_520_ci;
+----------------------------------------+
| '?'='?' COLLATE utf8mb4_unicode_520_ci |
+----------------------------------------+
|                                      0 |
+----------------------------------------+

需要注意两点:

  • 520 归类将它们视为不同。
  • 问号是显示问题。

进一步隔离...

mysql> SELECT HEX('');
+----------+
| HEX('?') |
+----------+
| F09F9886 |
+----------+

我的观点是问号可能是 显示 问题,并且(正如您用十六进制指出的那样)它不是编码问题:

(1062, "Duplicate entry '1532-?' for key 'PRIMARY'")

并且,如果您想用两个表情符号标记 1532,则该列需要为 utf8mb4_unicode_520_ci(或 utf8mb4_bin)。