我目前正在将数据从Windows上的MySQL 5.6.41迁移到Windows上的MySQL 8.0.21。总体而言,迁移过程非常顺利,但遇到了一些令人沮丧的问题。有一张看起来像这样的桌子:
CREATE TABLE `domains` (
`intDomainID` int(11) NOT NULL AUTO_INCREMENT,
`txtDomain` varchar(100) NOT NULL,
`dtDateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`blnTor` int(1) NOT NULL DEFAULT '0',
`txtTLD` varchar(100) NOT NULL,
PRIMARY KEY (`intDomainID`),
UNIQUE KEY `txtDomain` (`txtDomain`)
ENGINE=InnoDB AUTO_INCREMENT=10127897 DEFAULT CHARSET=utf8mb4;
CREATE SCHEMA已经完成,并且是由Workbench的“复制到剪贴板”->“创建模式”功能创建的。
当我使用内置的Workbench导出/导入时,导入总是失败,并显示“ txtDomain中的值重复”错误(此处解释),这很奇怪,因为原始表对该字段具有UNIQUE KEY约束,因此不能是重复项,我确认,它作为重复项找到的值不是原始数据库中的重复项。
然后我使用SELECT ... INTO OUTFILE
转储表,将文件移到新服务器上,然后执行LOAD DATE INFILE
。这也因相同的“ txtDomain中的值重复”错误而失败。
然后我删除了UNIQUE KEY约束,并重命名了LOAD DATE INFILE
。这样就可以了,数据在那里。但是,由于“重复”,我无法添加回UNIQUE KEY约束。我调查后发现:
在MySQL 5.6.41上的查询结果:
在MySQL 8.0.21上的查询结果:
现在,这是怎么回事?表定义,数据库,表和字段字符集/排序规则是相同的。我需要UNIQUE KEY约束...
为什么http://deepdot35wvmeyd5.onion:80
== http://dee-p---dot35w-vmeyd5.onion:80
??
如果有帮助,我的导出命令:
SELECT * INTO OUTFILE 'S:\\temp\\domains.txt'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
FROM domains;
我的导入命令:
LOAD DATA INFILE 'E:\\DB Backup\\ServerMigration\\domains.txt'
INTO TABLE domains
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\r\n';
集合: 排序规则旧服务器:utf8_general_ci [我不记得触摸此值了] 新服务器:utf8mb4_0900_ai_ci [我没有碰到这个值] 新旧数据库相同:utf8mb4_0900_ai_ci 新旧表相同:utf8mb4_0900_ai_ci
这是原始TXT文件在文件系统上的样子:
请注意,如果我将屏幕快照中的一个URL粘贴到此处,它将神奇地变成“正确”的值,没有破折号: 即:http://deepdot35wvmeyd5.onion:80
注2:使用Notepad ++,如果我将常规的“破折号”转换为十六进制,则会得到“ 2D”。但是,如果我从引起麻烦的URL中转换一个,则会得到HEX“ C2AD”。看来我正在处理一个奇怪的unicode字符而不是一个破折号?
注3:如果有人想要一个小的示例文件,则为: https://www.dropbox.com/s/1ssbl95t2jgn2xy/domains_small.zip
答案 0 :(得分:2)
有问题的字符是U + 00AD“ SOFT HYPHEN”-一种不可打印的字符,用于表示单词中可能的连字符点。
在新设置(使用默认排序规则设置的MySQL 8.0)上,使用COLLATION处理这些字符的方式似乎与在旧设置(使用默认排序规则设置的MySQL 5.7)上对字符的处理方式不同:
在比较中,现在这些<不可打印的字符被忽略。
您可以使用此简单的小提琴来测试差异。在5.6中比较为“ 0”,而在MySQL 8.0-> https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=a9bd0bf7de815dc14a886c5069bd1a0f
中为“ 1”请注意,SQL小提琴未明确指定时,也会使用默认排序规则配置。
您可以通过为txtDomain列设置二进制UTF-8排序规则来解决此问题,无论如何,这实际上是您想要的技术字符串:
CREATE TABLE `domains` (
`intDomainID` int(11) NOT NULL AUTO_INCREMENT,
`txtDomain` varchar(100) NOT NULL
CHARACTER SET utf8mb4
COLLATE utf8mb4_binary_ci,
`dtDateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`blnTor` int(1) NOT NULL DEFAULT '0',
`txtTLD` varchar(100) NOT NULL,
PRIMARY KEY (`intDomainID`),
UNIQUE KEY `txtDomain` (`txtDomain`)
) ENGINE=InnoDB AUTO_INCREMENT=10127897 DEFAULT CHARSET=utf8mb4;
更新:事实证明,旧版本(5.6)和新版本(8.0)的COLLATION必须有所不同,因为utf8mb4_0900_ai_ci
是MySQL 8.0引入的。旧排序规则必须是utf8mb4_general_ci
,在应用时也显示了MySQL 8.0中的所需行为。
但是,无论如何,您仍然应该对技术字符串(例如URL)使用二进制排序规则。