西西河

主题:【求助】mysql 里面邪门的 utf8mb4 问题 -- 铁手

共:💬15 🌺27 新:
分页树展主题 · 全看
  • 家园 【求助】mysql 里面邪门的 utf8mb4 问题

    网站数据库里原来是用的GBK,一直也没什么问题。现在为了支持 emoji,比如 😀 😁 😂 🤣 😃 😄 😅 😆 😉,所以要改为 utf8mb4。

    大部分还算顺利,但是在这个过程中碰到一个很邪门的问题。

    主要是中文里的全角字符,比如这个全角的数字:203和普通数字 203,在GBK中算是不同的东西,但是在 utf8mb4 里面变成了一样的东西。至少是在作 index 的时候,是同等看待,于是就造成了原来是 unique 的,变得重复了。

    试验了一下 utf8 编码,也是同样的问题。

    难道说在 utf8 中全角的概念?还是说 mysql 在处理字符集的时候有错误?

    关键词(Tags): #utf8mb4#mysql
    • 家园 为什么不换成postgresql ?

      postgresql 性能强大的多,而且稳如死狗

      • 家园 这个方便的话给多说说?

        我查来查去的结果,也是有很多人抱怨 mysql 这种字符支持的各种怪异。比如直觉上用 utf8 的,实际上要用 utf8mb4 才行。也有不少人热赞 postgresql 的。

        不知道这个学起来难度大不大?我现在用的是 PDO,估计转换起来也不会太多问题。关键是数据库的管理,比如备份之类的,怎么样?

    • 家园 多谢各位帮忙,有所改进,但问题依旧存在。

      这里汇报一下测试结果,看看大家有没有什么想法。@西电鲁丁 @葡萄干 @骆筱 @shinji

      首先需要确认的是,内容保存没有问题。输入什么,保存的也是什么。毛病出在索引上。

      Collation最早是用 gbk_chinese_ci

      以下是直接在库结构上改(不知道 DUMP 出来再 IMPORT 进去会不会有区别)的情况。

      如果改成 utf8mb4_general_ci 则全角和半角字符不再被同等看待,解决部分问题。但是出现 e 等同于 é 的情况。以及两个历史遗留的乱码变成等同。

      _ci 的意思是 case insensitive,所以这可能就是看似不同,但是被当作相同的原因。

      如果改成 utf8mb4_bin 则上述 全角字符问题,e 等同于 é 这两种情况不再存在。那两个乱码问题依旧存在。

      现在看来,大概就是只能用 utf8mb4_bin,然后手工修改那两个乱码。

      邪门的是,这两个乱码我怎么看都是一样的,不知道在 gbk_chinese_ci 的时候,为什么会被当作不一样。

      • 家园 手痒,试了一下,好像gbk 可以

        脚本在这,跑了一下,没有乱码,唯一索引也可以的:

        drop table if exists zzIronHand;

        create table if not exists zzIronHand (

        `id` int(11) NOT NULL AUTO_INCREMENT,

        `name` varchar(25) not null COMMENT '测试铁手问题的字段',

        PRIMARY KEY (`id`) USING BTREE

        ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=gbk ROW_FORMAT=COMPACT COMMENT='测试铁手问题';

        insert into zzIronHand(`name`) values ('203');

        insert into zzIronHand(`name`) values ('203');

        insert into zzIronHand(`name`) values ('e');

        insert into zzIronHand(`name`) values ('é');

        select * from zzIronHand;

        create unique index idxIronHand on zzIronHand(`name`);

        我这版本老了点,是MySQL 5.6的。

      • 家园 感觉已经踏进了mysql quirk的领域

        https://dev.mysql.com/doc/refman/8.0/en/faqs-cjk.html#faq-cjk-how-cjk-sort-unicode-1

        建议用utf8mb4_ja_0900_as_cs能解决老版本遗留的问题

        不过怎么看都是针对日语的,有兴趣可以试试utf8mb4_zh_0900_as_cs

    • 家园 假设转换没出问题,就是collation的问题

      现在的比较的没开width sensitive

      https://dev.mysql.com/doc/refman/8.0/en/charset-asian-sets.html

      改成

      gbk_bin试试?

      不行了再上

      utf8mb4_bin

    • 家园 应该指定collation为utf8mb4_bin

      alter table t_unicode convert to character set utf8mb4 collate utf8mb4_bin

      除了编码之外,collation决定如何比较字符串和顺序,有多个变种。用错了会造成不能区分大小写全半角,只考虑语意一致性。

      https://zudoh.com/mysql/should-use-collation-utf8mb4_bin-as-default

    • 家园 国内都是用utf8genic的
    • 家园 这个供你参考,也许有用

      https://www.v2ex.com/t/662096

分页树展主题 · 全看


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河