【问题标题】:mysqldump data loss after restorationmysqldump 恢复后数据丢失
【发布时间】:2014-04-01 13:54:22
【问题描述】:

我尝试使用带有 innodb 默认存储引擎的系统 A 中的 mysqldump 将大约 40gb 的数据库 db1 转储到 sql 文件中,并尝试在另一个系统 B 上恢复它。两者都具有默认存储引擎作为 innodb 和相同的 mysql 版本。我使用检查表状态检查了系统 A 上的任何表损坏,但无法在其上找到任何表损坏。我使用下面的查询来计算系统 A 和系统 B 上两个数据库 (db1) 上的表大小和每个表的行数,发现系统 B 的 db1 上大约有 6GB 的数据丢失。

SELECT table_schema,
    -> SUM(data_length+index_length)/1024/1024 AS total_mb,
    -> SUM(data_length)/1024/1024 AS data_mb,
    -> SUM(index_length)/1024/1024 AS index_mb,
    -> COUNT(*) AS tables,
    -> CURDATE() AS today
    -> FROM information_schema.tables
    -> GROUP BY table_schema
    -> ORDER BY 2 DESC

当 Innodb 是默认存储引擎时,我们可以依靠信息模式来计算确切的行数、确切的表大小(数据长度 + 索引长度)吗?为什么使用 mysql dump 的转储会导致在系统 B 上恢复时出现大量数据丢失?

【问题讨论】:

  • 能否请您分解每个表/索引的 6GB 差异?
  • @bpgergo 6GB 数据差异是在几个表中观察到的总数据丢失

标签: mysql innodb mysqldump


【解决方案1】:

InnoDB 无法给出在表中找到的记录的准确计数(使用 SELECT COUNT() 查询)。当您使用 InnoDB 引擎请求表上的记录计数时,您会注意到计数会波动。

有关更多信息,我想向您推荐 InnoDB 的 MySQL 开发人员页面 http://dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html

InnoDB 表的限制

ANALYZE TABLE 通过对每个索引树进行八次随机潜水并相应地更新索引基数估计来确定索引基数(如 SHOW INDEX 输出的基数列中所示)。因为这些只是估计值,所以重复运行 ANALYZE TABLE 可能会产生不同的数字。这使得 ANALYZE TABLE 在 InnoDB 表上快速,但不是 100% 准确,因为它没有考虑所有行。

MySQL 仅在连接优化中使用索引基数估计。如果某些连接没有以正确的方式优化,您可以尝试使用 ANALYZE TABLE。在 ANALYZE TABLE 不能为您的特定表生成足够好的值的少数情况下,您可以在查询中使用 FORCE INDEX 以强制使用特定索引,或设置 max_seeks_for_key 系统变量以确保 MySQL 更喜欢索引查找而不是表扫描。请参阅第 5.1.4 节“服务器系统变量”和第 C.5.6 节“优化器相关问题”。

SHOW TABLE STATUS 不提供有关 InnoDB 表的准确统计信息,但表保留的物理大小除外。行数只是 SQL 优化中使用的粗略估计。

InnoDB 不保留表中的内部行数,因为并发事务可能同时“看到”不同数量的行。为了处理 SELECT COUNT(*) FROM t 语句,InnoDB 扫描表的索引,如果索引不完全在缓冲池中,这需要一些时间。如果您的表不经常更改,使用 MySQL 查询缓存是一个很好的解决方案。要获得快速计数,您必须使用您自己创建的计数器表,并让您的应用程序根据它所做的插入和删除来更新它。如果近似行数足够,则可以使用 SHOW TABLE STATUS。请参阅第 14.2.12.1 节,“InnoDB 性能调优技巧”。

【讨论】:

  • 您的陈述“InnoDB 无法提供在表中找到的准确记录数”是错误的。通过查看information_schema 来获取行数只是错误的方法
  • 你说得对,但我指的是示例中使用的计数。这也是我提供有关 InnoDB 限制的附加信息的原因。
  • @naitsirch 我已经更新了我的答案以澄清我所指的计数。
  • @Bearwulf 非常感谢我们可以依赖 Innodb 信息模式报告的 data_length,index_length 吗?这是一个确切的数字吗?如果不是,我怎样才能获得每个表的确切表大小?
  • @user3393007 当使用 SHOW TABLE STATUS 时,InnoDB 将提供表使用的实际空间。您可以使用它来确定您的整体数据库大小。
【解决方案2】:

检查是否有任何数据丢失的最佳解决方案是比较数据库的内容。

mysqldump --skip-comments --skip-extended-insert -u root -p dbName1 > file1.sql
mysqldump --skip-comments --skip-extended-insert -u root -p dbName2 > file2.sql
diff file1.sql file2.sql

更多信息请参见this topic

此解决方案的另一个优点是您可以看到差异在哪里。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-23
    • 2015-06-18
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 2019-03-28
    • 2022-01-14
    • 2019-03-06
    相关资源
    最近更新 更多