抱歉,我看到了类似的帖子,但我仍然找不到它来解决我的问题另外,我需要更多关于这方面的信息。
要求:创建现有数据库“db3”的精确副本“db4”。
程序如下:
- mysqldump -uuser -ppass db3 > db3.sql(大小为6G)
- mysql -uuser -ppass db4 < db3.sql(db4 是新创建的空白数据库)
第二步抛出错误:
ERROR 1062 (23000) at line 5524: Duplicate entry '600806' for key 1"
我用 --force 再次运行了第二步。还原已完成,但还有 2 个类似的错误:
ERROR 1062 (23000) at line 6309: Duplicate entry '187694' for key 1
ERROR 1062 (23000) at line 6572: Duplicate entry '1567400' for key 1
当我查询 db4 数据库的某些表时,我能够看到丢失的记录。
问题:
这是否表示 db3 数据库已损坏/有问题?
如何继续创建 db3 的“一致/工作”副本 (db4)?
谢谢,
出现这种“重复”的原因有多种:
错误消息确实引用了第一个键,在大多数数据库模式中它是第一个值。查看原始转储输出,尤其是 INSERT 语句并检查
扫描错误消息中给出的 mysql 转储的行号。
我期待什么样的 mysqldump 示例:
在自动递增字段的“正常”INSERT 语句中,值“0”指定自动递增字段,因此不应出现在使用自动递增字段的数据库 SQL 转储中。通过 SQL 转储重新加载数据库,您的转储要求 SQL 服务器将当前字段值递增 1 并插入该 ID。如果有人在插入记录后手动将身份更新为零,您的 MySQL 转储也会包含这个奇怪的 ID。
如果您将此转储重播到一个空表中,这将尝试创建以下记录:
由于“id”字段已设置为唯一自动增量,第二个 INSERT 将创建一个“错误”记录(预期:0,4,5;实际:2,4,5)与以下记录冲突(id = 2 ) 并因此给出错误消息。
在这种变化中,有人“手动”将身份更新为一个已经存在的值,然后将记录更改为“唯一”。如果当前数据符合要求,将记录类型更改为唯一不会使 MySQL 重新验证,因此会出现延迟错误。此变体可能会创建如下转储:
由于唯一约束,尝试插入第二行将失败。
在这两种情况下,使用“--force”只会忽略“冲突”行并继续导入。“冲突”行将丢失,但可能会存在导致此冲突的行(但 ID 记录错误)。
如果我的想法符合您的问题,请检查您的数据库转储。如果是这种情况,这里有两个解决方法来“让它工作”:
分两步导入数据,首先是模式,然后是数据。在导入数据之前从模式中删除唯一约束,稍后再次添加唯一约束(“ALTER TABLE ... 添加唯一...”)。
强制导入模式和所有数据,导致“不同”约束问题。手动检查哪些记录是正确的,并将错误的记录重新分配给它们的原始值。
后一期的例子:
这确实会强制导入所有冲突的记录,甚至违反任何真正的唯一约束。导入后,您将拥有这三个记录(600806、187694 和 1567400)的多个条目,并且您必须通过检查转储来手动挑选出正确的条目,哪些“重复项”确实导致了冲突并手动将错误记录“回”更新为零(或转储中的冲突行所说的任何内容)。
在这两种情况下,您的数据仍然违反给定的模式:您的模式说数据是唯一的,但事实并非如此。从长远来看,数据需要固定在应用程序级别。
首先,检查原始数据库中是否存在处于该状态的相关行。
发生的情况很可能是以下情况之一:
如果只有 3 行显示问题,请更正它们的键字段,如果可能,执行该实例的转储和导入,看看错误是否不会再次出现。我猜,它应该消失了。
前言
因此,在我们的一个复制服务器进入不一致状态后,我遇到了这个问题。我们无法通过快速修复使其恢复在线,因此决定使用新备份重新初始化复制。
上面提到的问题不是同一个问题,但确实会返回相同的错误,因此我决定添加这个答案以防其他人正在寻找它。
它也是DBA Stack Exchange上这个问题的完全重复,但是因为这个问题在(我的)Google 结果中排名更高,所以我也将它发布在这里。
我们做了什么
我们使用 MySQL Workbench 删除了实例上的所有数据库,我重新启动了实例并仔细检查了实例上没有数据库的地方。在主服务器上,我们已经开始使用我们一直使用的脚本创建新备份。
然后一旦备份在故障服务器上,我们就开始导入,几个小时后它导入了大部分数据并因以下类型的错误而失败:
我们想好吧,也许创建备份时出了问题,我检查了备份中的数据但没有发现任何错误。我们再次重试了所有步骤,以确保我们没有遗漏任何东西,但不幸的是没有雪茄。
实际问题
显示的错误不是实际插入数据而是创建索引。这就是为什么数据插入没有问题(我们检查过)但仍然产生错误的原因。显然删除所有表是不够的,索引数据仍然存在于服务器上(这可能是由于 MySQL 5.6 中的更改,因为我们以前从未遇到过这个问题)。而且因为这些索引的导入是在导入文件中间的某个地方,所以其余的数据没有被导入。
修复
我们删除了ibdata1文件和mysql数据库文件夹下的所有innodb_index_stats和innodb_table_stats文件,然后启动了实例。然后 MySQL 会告诉您缺少一些系统表, 您可以在此处找到更多相关信息
这解决了我们的问题,我们的服务器现在正在按预期进行复制。
希望这可以为某个地方的某人节省一些时间 :)