【问题标题】:Emojis as question marks in MariaDB primary key表情符号作为 MariaDB 主键中的问号
【发布时间】:2018-12-28 15:18:05
【问题描述】:

如下表,使用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 |
+-----------------------------+

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

【问题讨论】:

  • @RickJames 请不要这么快下结论。你提到的问题并没有解决我的问题。我已经在使用那里描述的技术了。
  • 难道#1532 已经被那个表情符号标记了?而你又是INSERTing 同一个标签?而“问号”实际上来自 SQLAlchemy,而不是 MySQL?如果是这样,请考虑INSERT IGNORE ...
  • 通过 mysql shell 也是一样的。我找到了另一个与排序相关的答案,但不确定该怎么做。将在一分钟内更新答案

标签: unicode sqlalchemy mariadb primary-key emoji


【解决方案1】:
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'")

而且,如果您想用两个 Emoji 标记 1532,则该列需要为 utf8mb4_unicode_520_ci(或 utf8mb4_bin)。

【讨论】:

  • 是的,我的结果和上面一样。但那是什么 utf8mb4_unicode_520_ci ?为什么我应该选择它而不是我当前的选择?我看到很多帖子如何摆脱“520”。
  • @RomanSusi - 520 将 Emoji 视为独特的。该链接正在谈论土耳其语。 520 不能很好地处理特定语言的要求。
  • stackoverflow.com/questions/42385099/… ,加上谷歌搜索的更多内容 - 我没有进一步阅读。当然,也有类似的错误建议将 utf8mb4 替换为 utf8
  • @RomanSusi - 第二个链接涉及有人从 5.6(有 520)降级到 5.5。同样,这是避免 520 的正当理由,但不是适用于您的理由。
猜你喜欢
  • 1970-01-01
  • 2017-04-12
  • 2017-02-09
  • 2019-08-21
  • 2021-03-16
  • 2021-04-26
  • 2013-01-06
  • 1970-01-01
  • 2021-05-29
相关资源
最近更新 更多