昨天我在 AWS 的 EC2 上运行的 MySQL 5.5 从属数据库之一遇到了一个新问题。数据库是从另一个从站的快照创建的。数据是正确的,但对于至少一个表,二级索引返回的结果不完整。通过父 id 查询子表返回 498 行,而它应该返回 504。通过主键查询丢失的 6 行有效,并且返回了正确的父 id,所以问题出在二级索引上。
这个问题对我来说非常重要,因为即使从服务器上的所有数据都与主服务器匹配,我仍然会从从服务器上运行的某些查询中得到不正确的结果。
我的蛮力解决方案是像这样重建整个表:
alter table my_table engine = innodb;
这解决了这个特定表的问题,但我留下了以下问题:
1) How can I determine if other tables have similar index corruption?
2) What's the most efficient way to fix the corrupt indexes?
我在网上找到了一些很好的资源来查找和修复 InnoDB 数据损坏,但没有找到与 InnoDB 索引损坏相关的任何内容。
我查看了 MySQL 错误日志并没有发现确凿证据。我确实发现了一些令人不安的 InnoDB 错误。我假设这是一个单独的问题,但它可能是相关的:
130109 9:46:41 InnoDB: unable to find a record to delete-mark
InnoDB: tuple DATA TUPLE: 2 fields;
0: len 4; hex 04af1f21; asc !;;
1: len 4; hex 0a1c03bd; asc ;;
InnoDB: record PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 04af1f21; asc !;;
1: len 4; hex 0a052a77; asc *w;;
感谢 Rolando 和 Michael 的回复。
为了结束循环,这是我为最初的问题提出的答案:
答:使用
CHECK TABLE
。我mysqlcheck -c
在所有相关的 InnoDB 表上运行以找出哪些有索引损坏问:修复损坏索引的最有效方法是什么?
OPTIMIZE TABLE
重建索引损坏的 InnoDB 表。这会导致修复损坏的完整表重建。您可能有最简单的解决方案。但是,我想澄清一些事情:
使用正在运行的 MySQL 实例创建快照可能会影响负责二级索引操作的一个文件:ibdata1。
系统表空间
ibdata1
是 7 类 InnoDB 信息的所在地我要担心的关键类是双写缓冲区和插入缓冲区。在其中任何一个未正确写入的情况下执行实时快照都会导致数据损坏。
这样做并不会像人们想象的那样
FLUSH TABLES WITH READ LOCK;
停止对 ibdata1 的写入。我以前写过这个主题。我曾经认为确实如此,直到DBA.SE 成员 @ShlomiNoach指出了这一点。想想 InnoDB 缓冲池。您必须清除其中的每个脏页才能将所有内容静默到磁盘。以下强制每个表的所有脏页:
SET GLOBAL innodb_fast_shutdown = 0;
其次是service mysql stop
SET GLOBAL innodb_max_dirty_pages_pct = 0;
并等到 1% 的 Buffer Pool 变脏另外,不要忘记二进制日志和中继日志依赖于操作系统进行刷新。
在这些方面,EC2 快照不是 MySQL 感知的,就像 LVM 快照一样。这就是为什么像 CDP 的 R1Soft 这样的备份软件在这种情况下有一个 MySQL 模块的原因。
相反,Amazon RDS MYSQL 实例可以感知并构建此类以 InnoDb 为中心的场景。只有当 RDS 实例中有活动的 MyISAM 表时
FLUSH TABLES WITH READ LOCK;
,手动执行才是必要的。关于您最初的问题,当您运行时,
ALTER TABLE my_table ENGINE=InnoDB;
您只需重建从表的数据页读取的索引页,很可能绕过 ibdata1 插入缓冲区。这就是为什么这对你有用。如果您可以
--single-transaction --master-data=1
在主服务器上执行 mysqldump,将 mysqldump scp 到从服务器,并且不收取任何费用,那么这将是设置 EC2 从服务器的更安全的方法。如果您必须执行快照操作,请在从站上执行此操作:
SET GLOBAL innodb_fast_shutdown = 0;
service mysql stop
service mysql start
/etc/my.cnf
附加信息: ib_logilfe0 和 ib_logfile1 越小,关闭越快。
我希望这能解释很多。
更新 2013-01-14 10:36 EDT
你最近在评论区问
请记住,您使用的是 EC2 而不是 RDS。借助 RDS,Amazon 负责 VM 和 MySQL 实例的整体状态。对于 EC2,Amazon 仅负责 VM。MySQL 实例的整体状态现在由您掌握。您可能希望将数据库移植到 RDS,因为它带有额外的花里胡哨来防止这种损坏。
使用下面的命令,你会像现在一样开心。
我相信您知道您应该根据您的存储偏好更改大写字母,不是吗?:)