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

大河奔流 导读 复 14 阅 2217

/ 1 首页 上页 下页 末页

O 【求助】mysql 里面邪门的 utf8mb4 问题 2 铁手 字698 2020-05-03 16:00:26
O 这个供你参考,也许有用 2 西电鲁丁 字29 2020-05-03 17:32:04
O 国内都是用utf8genic的 葡萄干 字0 2020-05-03 17:48:57
O 应该指定collation为utf8mb4_bin 4 骆筱 字308 2020-05-03 18:12:30
O 假设转换没出问题,就是collation的问题 2 shinji 字153 2020-05-03 19:03:01
O 多谢各位帮忙,有所改进,但问题依旧存在。 2 铁手 字1028 2020-05-03 21:55:14
O 感觉已经踏进了mysql quirk的领域 1 shinji 字230 2020-05-04 21:51:24
O 为什么不换成postgresql ? 1 投桃报李 字50 2020-05-05 03:09:43
O 手痒,试了一下,好像gbk 可以 2 懒厨 字702 2020-05-05 03:23:14
O 待认可未通过。偏要看 耗株钱:1
O GBK是没问题的 2 铁手 字174 2020-05-09 15:31:16
O 这个方便的话给多说说? 2 铁手 字372 2020-05-09 15:35:45
O 我现在是保存没问题,就是做唯一性索引的时候有问题 1 铁手 字147 2020-05-09 15:38:00
O 惭愧惭愧 懒厨 字51 2020-05-10 04:15:24
O 我又继续手痒 2 懒厨 字812 2020-05-10 05:12:45
2020-05-03 16:00:26
主题:4514702
铁手
铁手`352`/bbsIMG/upload/face/352.gif`70`46722`40940`506865`正九品上:儒林郎|仁勇校尉`2003-05-03 11:59:57`
【求助】mysql 里面邪门的 utf8mb4 问题 2

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

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

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

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

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


关键词(Tags): #utf8mb4#mysql
2020-05-03 16:00:26
这个供你参考,也许有用 2

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


2020-05-03 17:32:04
2020-05-03 18:12:30
4514716 复 4514702
骆筱骆筱`58805`/bbsIMG/face/0000.gif`70`65`553`4305`从八品上:承奉郎|御武(侮)校尉`2010-07-26 20:38:57`
应该指定collation为utf8mb4_bin 4

alter table t_unicode convert to character set utf8mb4 collate utf8mb4_bin

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

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


2020-05-03 18:12:30
2020-05-03 19:03:01
4514724 复 4514702
shinjishinji`58951`/bbsIMG/face/0000.gif`70`9834`3470`66425`从四品下:中大夫|明威将军`2010-07-27 14:17:01`
假设转换没出问题,就是collation的问题 2

现在的比较的没开width sensitive

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

改成

gbk_bin试试?

不行了再上

utf8mb4_bin


2020-05-03 19:03:01
2020-05-03 21:55:14
4514775 复 4514702
铁手
铁手`352`/bbsIMG/upload/face/352.gif`70`46722`40940`506865`正九品上:儒林郎|仁勇校尉`2003-05-03 11:59:57`
多谢各位帮忙,有所改进,但问题依旧存在。 2

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

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

Collation最早是用 gbk_chinese_ci

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

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

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

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

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

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


2020-05-03 21:55:14
2020-05-04 21:51:24
4515183 复 4514775
shinjishinji`58951`/bbsIMG/face/0000.gif`70`9834`3470`66425`从四品下:中大夫|明威将军`2010-07-27 14:17:01`
感觉已经踏进了mysql quirk的领域 1

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


最后于2020-05-04 21:58:37改,共1次;
2020-05-04 21:51:24
2020-05-05 03:23:14
4515257 复 4514775
懒厨
懒厨`2616`/bbsIMG/face/0000.gif`70`19857`10397`164080`正二品:特进|辅国大将军`2004-04-04 22:16:06`
手痒,试了一下,好像gbk 可以 2

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

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的。


2020-05-05 03:23:14
45153754514702 待认可未通过。偏要看 耗株钱:1 2020-05-05 11:49:22
2020-05-09 15:31:16
4517002 复 4515257
铁手
铁手`352`/bbsIMG/upload/face/352.gif`70`46722`40940`506865`正九品上:儒林郎|仁勇校尉`2003-05-03 11:59:57`
GBK是没问题的 2

我就是想从原来的GBK转到 utf8mb4 的其中一种,然后在 unique index上碰到了一些数据错误。

眼下看来,最靠谱大概就是用 utf8mb4_bin 了。


2020-05-09 15:31:16
2020-05-09 15:35:45
4517004 复 4515253
铁手
铁手`352`/bbsIMG/upload/face/352.gif`70`46722`40940`506865`正九品上:儒林郎|仁勇校尉`2003-05-03 11:59:57`
这个方便的话给多说说? 2

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

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


2020-05-09 15:35:45
2020-05-09 15:38:00
4517005 复 4515375
铁手
铁手`352`/bbsIMG/upload/face/352.gif`70`46722`40940`506865`正九品上:儒林郎|仁勇校尉`2003-05-03 11:59:57`
我现在是保存没问题,就是做唯一性索引的时候有问题 1

你的这个帖中提到的问题,看来是显示上全角半角分不清。出现这种问题,还真是只能哭了,怎么会想的到呢。


2020-05-09 15:38:00
4517199 复 4517002
懒厨
惭愧惭愧

是我看帖不仔细,没理解需求FF


2020-05-10 04:15:24
2020-05-10 05:12:45
4517212 复 4517002
懒厨
懒厨`2616`/bbsIMG/face/0000.gif`70`19857`10397`164080`正二品:特进|辅国大将军`2004-04-04 22:16:06`
我又继续手痒 2

接上面的脚本,我加了这句,把字段的Charset改了:

ALTER TABLE zzIronHand

CHANGE COLUMN `name` `name` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

然后再: select * from zzIronHand;

发现没有码,一切正常,索引也没报错。

如果换了其他collate, 尤其是那些ci结尾的,就会报错,说之前创建的唯一索引不对,这个是正常的,因为ci就是Case Insensitive,把e é当成一样的了。

不过好像MySQL的Charset/Collate是有些历史遗留问题的,可以参考一下这里:https://stackoverflow.com/questions/43644218/why-is-table-charset-set-to-utf8mb4-and-collation-to-utf8mb4-unicode-520-ci


2020-05-10 05:12:45
帖内引用

/ 1 首页 上页 下页 末页