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

时间:2018-07-20 10:20:22

标签: unicode sqlalchemy mariadb primary-key emoji

使用下表,使用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'")

第二次插入表情符号。

第一个似乎在数据库中正常(相信我,它在我的控制台和浏览器中显示为“异形”表情符号):

> 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插入时出现相同的问题。还尝试了此操作以查看发生了什么(在mysql utf8mb4_unicode_ci cause unique key collision中找到了此操作):

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

但不确定是否与此相关。

我不明白:数据库有时可以正常显示(通过客户端-Shell和SQLAlchemy应用程序),但是无法在标头中显示?从我得到的证据来看,我不知道不良转换发生​​在哪里。数据在数据库中似乎没问题(请参见上面的十六进制),但是主键有两个等效的表情符号?

另一个对比:

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

这种指向手指的主键不使用二进制吗?所有表情符号在转换为索引之前都已转换为其他符号?很奇怪。

1 个答案:

答案 0 :(得分:1)

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

需要注意的两件事:

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

进一步隔离...

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

我的观点是问号可能是一个 display 问题,并且(如您所指出的那样,这不是一个编码问题)

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

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