您如何识别InnoDB表损坏?


24

我有一些表已分区,并且在复制的从属服务器上有多个索引。将快照(已验证安全)复制到新的从属并将mysqld从5.1.42升级到5.5.15并重新启动复制后,我收到InnoDB崩溃的错误消息“ Invalid pointer ...”。

这些错误已在具有不同硬件和O / S的2台服务器上发生。运行后:

ALTER TABLE .... COALESCE PARTION n;

该表的问题消失了。

我的问题是,范围更大,那就是“如何识别InnoDB表损坏?” 或改写为“您如何评估InnoDB表的运行状况?” 是“检查表”可用于识别问题预碰撞唯一的工具?

不确定是否重要,但是崩溃发生在运行:版本:'5.5.15-55-log'套接字:'/opt/mysql.sock'端口:3306 Percona Server(GPL),版本rel21.0,修订版158


2
嗨,兰迪!我认为这里的回答是可信的-InnoDB确定了自己的腐败。也许您应该重新表述您的问题,为什么您所做的操作会导致InnoDB损坏?
Morgan Tocker

Answers:


18

Morgan在其评论中暗示InnoDB通过对其读取的页面进行校验和来不断检查损坏的页面。如果InnoDB发现校验和不匹配,将导致服务器崩溃

如果您想加快该过程(而不是等待InnoDB读取损坏的页面),可以使用innochecksum

因为校验和不匹配将导致InnoDB故意关闭正在运行的服务器,所以最好使用此工具,而不是等待生产环境中的服务器遇到损坏的页面。

一个有趣的警告:

innochecksum不能用于服务器已打开的表空间文件。对于此类文件,应使用CHECK TABLE来检查表空间中的表。

所以是的,因为在线表CHECK TABLE可能是该工具(或者,如果您想一次执行多个数据库操作,则可以在另一个答案中 指出mysqlcheck)。

如果可以关闭数据库,则可以使用以下命令强制执行校验和 innochecksum

轶事: 在29GB的innodb表空间(带有innodb_file_per_table=1)上,此脚本花费了大约2分钟

#!/bin/bash
for i in $(ls /var/lib/mysql/*/*.ibd)
do
  innochecksum -v $i
done

不过,作为奖励,由于您正在运行Percona,因此他们实现了一种用于innodb快速校验和的新方法。我从未使用过它,但是它可能会加快过程。


1
要在这里尝试一下,似乎是解决方案@randymelder正在寻找+1
marcio

2
Percona服务器还具有其他一些不错的功能。见innodb_corrupt_table_action percona.com/doc/percona-server/5.5/reliability/...(!!)
摩根Tocker

@DTest:innochecksum是必经之路。这是一个门将。+1 !!!
RolandoMySQLDBA 2011年

@DTest:今天就向您致敬!
RolandoMySQLDBA 2011年

@MorganTocker有趣。将不得不让我的知识真空和对percona做一些研究
Derek Downey

6

警告:在尝试执行任何这些说明之前,强烈建议您验证手中是否有健康的数据库备份,以防万一。(感谢@Nick提供警告)

尝试使用mysqlcheck命令。在终端上:

mysqlcheck -u username -p --databases database1 database2

此命令将输出所有表的列表和状态,告诉您是否存在某种损坏:

table1  OK
table2  OK
table3  OK
tableN  OK

有了这些,您将已经知道必须修理哪些表。万一您想一次修理所有东西,请执行以下操作:

mysqlcheck -u username -p --auto-repair --databases database1 database2 

有关更多信息mysqlcheckhttp : //dev.mysql.com/doc/refman/5.0/en/mysqlcheck.html

注意:您用标记了您的问题。我不知道那是什么,所以我用谷歌搜索。它似乎是MySQL的一个分支,但是我没有理由相信这些命令是不兼容的(手指交叉)。


有人向我指出了该指南,该指南针对在整个数据库无法启动的更关键情况下的InnoDB数据库恢复提供了更具体的说明:http : //www.softwareprojects.com/resources/programming/t-how-to-fix-mysql -database-myisam-innodb-1634.html


1
mysqlcheck是“检查表...”
-randomx 2011年


不对。首先,mysqlcheck是一个命令行实用程序,而CHECK TABLE是一个SQL语句(就像将Orange和lemmons进行比较)。此外,您不能使用CHECK TABLE检查整个数据库而不在SQL语句中包含所有表名(它也不会非常有生产力)
marcio

mysqlcheck有一个选项--auto-repair修复损坏的表,而CHECK TABLE仅检查表是否损坏,但不能进行任何修复。
marcio

2
@randymelder-您错误地说mysqlcheck是的同义词CHECK TABLE。您链接到状态的文档:“ mysqlcheck使用SQL语句CHECK TABLEREPAIR TABLEANALYZE TABLE,并OPTIMIZE TABLE为用户提供方便的方式它确定哪些语句使用您要执行的操作,然后将要执行的语句到服务器。 ” 那不是同义词。这是语句集合的用户界面。
Nick Chammas

6

根据MySQL 5.0认证研究指南,第443,444页第30.4节

您可以使用CHECK TABLE命令或使用客户端程序来为您发布该语句来检查InnoDB表。但是,如果InnoDB表存在问题,则无法使用REPAIR TABLE对其进行修复,因为该语句仅适用于MyISAM。

如果表检查表明InnoDB表有问题,您应该能够通过使用mysqldump转储该表,将其删除并从该转储中重新创建该表来将其恢复到一致状态。

如果MySQL服务器或运行它的主机崩溃,则某些InnoDB表可能需要修复。通常,仅需重新启动服务器即可,因为InnoDB存储引擎将自动恢复作为其启动顺序的一部分。在极少数情况下,由于InnoDB自动恢复失败,服务器可能无法启动。如果发生这种情况,请使用以下过程:

  • 将--innodb_force_recovery选项设置为从1到6的值来重新启动服务器。这些值表示为避免崩溃而增加的谨慎级别,以及对已恢复的表中可能出现的不一致的容忍级别。一个不错的开始是4。

  • 在将--innodb_force_recovery设置为非零值的情况下启动服务器时,InnoDB将表空间视为只读。因此,您应该使用mysqldump转储InnoDB表,然后在该选项生效时将其删除。然后,在不使用--innodb_force_recovery选项的情况下重新启动服务器。服务器启动时,从转储文件中恢复InnoDB表。

  • 如果上述步骤失败,则有必要从以前的备份中还原InnoDB表。

请阅读有关InnoDB强制恢复的 MySQL文档  


3
FWIW,认证指南在政治上有一个非常正确的答案:)如果您在InnoDB表上检查表并且它实际上已损坏,则它将永远不会返回“ corrupt”,这将使服务器崩溃。该语句在InnoDB中几乎已过时,因为每次阅读InnoDB页面时,它都会检查损坏(通过页面校验和)。
Morgan Tocker 2011年

2

我不知道如果有人使用通过InnoDB插件创建的InnoDB数据,然后切换到另一个版本的InnoDB,会发生什么情况。在mysqld的眼中,这可能会导致页面损坏。

请注意有关此可能性的有关InnoDB文件格式MySQL文档所说的:

通常,较新版本的InnoDB可能会创建一个表或索引,而该表或索引无法安全地用InnoDB的先前版本进行读写,而不会导致崩溃,死机,错误的结果或损坏。InnoDB插件引入了一种新机制来防范这些情况,并有助于保持数据库文件和InnoDB版本之间的兼容性。

我会在从属服务器上废弃数据。实际上,我只是通过获取数据的逻辑转储(mysqldump)来使用蛮力:

  • 在从服务器上使用InnoDB删除所有数据库
  • 关闭奴隶上的mysql
  • 删除从站上的ibdata1,ib_logfile0和ib_logfile1
  • 在从属服务器上启动mysql,重新创建ibdata1,ib_logfile0和ib_logfile1
  • mysql将数据从主数据库转储到从数据库

我最初发布的答案被认为是“老派”。但是,在这种情况下,我肯定会研究.ibd和/或ibdata1使用的文件格式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.