我目前正在将数据从MySQL 5.6.41迁移到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;创建模式已经完成,并且是由Workbench的“复制到剪贴板”-> "Create“函数创建的。
当我使用内置的Workbench导出/导入时,导入总是失败,并带有“txtDomain中的重复值”(在这里解释)错误,这很奇怪,因为原始表在该字段上有一个唯一的键约束,所以不能重复,并且我确认了它作为副本找到的值在原始数据库中不是重复的。
然后使用SELECT ... INTO OUTFILE转储表,将文件移到新服务器,并执行LOAD DATE INFILE。同样的“txtDomain中的重复值”错误也失败了。
然后,我删除了唯一的键约束,并重新做了LOAD DATE INFILE。这起作用了,数据就在那里。但是,由于“重复”,我不能返回唯一的键约束。我调查发现:
MySQL 5.6.41上的查询结果:

MySQL 8.0.21上的查询结果:

现在,怎么回事?表定义、数据库、表和字段字符集/排序规则是相同的。我需要拿回唯一的密钥约束..。
为什么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 --我不记得接触过这个值-- New : utf8mb4_0900_ai_ci --我没有碰这个值-- DB旧/新是一样的: utf8mb4_0900_ai_ci表旧/新是一样的: utf8mb4_0900_ai_ci
这是原始TXT文件在文件系统上的样子:

注意,如果我将屏幕截图中的一个URL粘贴到这里,它将神奇地变成“正确”值,而不需要破折号:即:http://deepdot35wvmeyd5.onion:80。
Note2:使用Notepad++,如果我将常规的“破折号”转换为HEX,就会得到"2D“。然而,如果我转换一个从URL,是造成麻烦,我得到HEX "C2AD“。看来我是在处理一个奇怪的unicode字符而不是破折号?
Note3:如果有人想要一个小的示例文件,那么它就是:https://www.dropbox.com/s/1ssbl95t2jgn2xy/domains_small.zip
发布于 2020-09-14 19:14:38
所讨论的字符是U+00AD“软连字符”--一个不可打印的字符,用于向单词内的一个可能的连字符发出信号。
在新设置(带有默认排序规则设置的MySQL 8.0 )上,所使用的排序规则似乎与旧设置(默认排序规则设置为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 )设置之间一定是不同的,因为utf8mb4_0900_ai_ci是在MySQL 8.0中引入的。旧的排序规则一定是utf8mb4_general_ci,在应用时,它也在MySQL 8.0中显示了所需的行为。
但是,无论如何,您应该使用二进制排序规则来处理技术字符串,比如URL。
https://stackoverflow.com/questions/63889274
复制相似问题