MySQLサーバのMyISAMテーブルをこわれた原因はなんでしょうか?

MySQLサーバのMyISAMテーブルをこわれた原因はなんでしょうか?

 

適用範囲:

MySQLサーバー – バージョン:4.0〜5.5 – リリース:5.5

MySQLサーバ – バージョン:4.0 – リリース:4.0

MySQLサーバー – バージョン:4.0〜5.5 – リリース:4.0〜5.5

すべてのプラットフォーム

目標

MyISAMテーブルがこわれた具体的な原因を説明する。

 

解決策

MyISAM ストレージエンジンは非常に頼りになる。もしMyISAMテーブルがよく壊れることがあれば、それについての原因を考えてください。データを検索するときに、以下のエラが現れたとはテーブルがこわれたと意味する:

Error 1034 Incorrect key file for table: ‘…’. Try to repair it

あるいは以下のエラ番号を含んだ情報:

Error 126 = Index file is crashed

Error 127 = Record-file is crashed

Error 134 = Record was already deleted (or record file crashed)

Error 144 / Error 1195 = Table is crashed and last repair failed

Error 145 / Error 1194 = Table was marked as crashed and should be repaired

 

当查询本该查找到在表中的行但没有找到,或当一个查询返回不完整的数据,也可以假定发生了损坏。你可以使用CHECK TABLE 语句来验证MyISAM 表是否损坏。テーブルにあるはずの行が検出されないときあるいは不完全なデータが返されたときに、こわれたと推定してもいいと思う。また、CHECK TABLE文でMyISAMテーブルがこわれたかを確認できる。

 

MyISAMをこわれた原因はいろいろあるが、可能性大きいから小さいまでの順で、以下の通り:

  1. サーバシャットダウンあるいはハードウェアエラによる損害:
  • 書き込む途中で、mysqldプロセスが閉められるあるいは壊れる。
  • 電源エラでMySQLを運用するサーバ閉められて、壊れるかもしれない。
  • ハードウェアエラによるもの可能性もある。例えば、サーバのトラブル。
  • RAMの損害;ディスクを再起動して解決できる。操作システムのメモリーに壊れたデータがあれば、時に再起動して解決できる。これは極めてレアなトラブルが、ハードウェアにトラブルがあれば、起こる頻度が上がる。

サーバが再起動するときに、自動リカバリがこのトラブルを解決するが、時にはREPAIR TABLE SQL文あるいはより高等なテストオプションを使う必要がある。テーブルが巨大で、サーバがアウトラインより早いリカバリオプションがある場合にmyisamchkを使ってください。いろんなCPUコールがあって、それにテーブルにインディクスがいっぱいある場合に、より速くなるために、myisamchkオプションででマルチスレッドを使ってください。このオプションが失敗するときに報告されるから、見つけ出したが、一つのスレッドを使っているという状況はあまりないです。

 

2.ほかのプログラムによる損害

  • Myisamchkのような外部プログラムを使うと、サーバが運用する途中に変更されるから、よくこわされる。
  • 一部のアンチウイルスソフトウェアも損害を及ぼす、ときに古いテーブルをリカバリしたあるいは必要なファイルをテストしたから、損害を及ぼした。

これらの状況を解決する根本的な策は、どんなファイルを変更されたかを見つけ出す。テーブルをリカバリするのは一時的な方法である。

  1. bugによる損害
  • 2007の夏前のバーションサーバ構造を使ってください。2006年から2007までMySQLはシステムテストを実行して、レアでコピしにくいMyISAM損害bugを探し出した・おおよそ2007の夏で、bugに関連するトラブルはほぼ全部は古いバーションにある。リカバリ機能が強いバーションはあまり影響されていないから、バーションをアップグレードしてください。
  • もしbugがまだ損害を及ぼすなら、まずは最近に導入したサーバ機能を確認してください。

最近再起動したmysqldを検索して、テーブルの損害はサーバシャットダウンによるものかを確認できる。何のエラ情報もない、それに損害が正常なオペレーション期間に起こっているであればbugが原因かもしれない。コピできるテストを作成してトラブルを探し出す。My Oracle SupportでSupport Requestを使って、トラブルを報告してください。Mysqldを運用されていない場合に、myisamchkコマンドでテーブルをテストしてリカバリできる。

 

 

如何使用mysqlfrm工具从.frm文件中恢复表结构

表结构存储在.frm文件和InnoDB数据字典中。有时,通常在数据恢复问题中,我们需要恢复这些结构,以便能够找到丢失的数据或只是重建表。

 

有不同的操作方式,我们已经在博客中已经写过。例如,我们可以使用数据恢复工具从InnoDB字典恢复表结构,或使用MySQL服务器从.frm文件恢复。本文将是后者的更新。我会告诉你如何轻松从.frm文件恢复结构,在某些情况下,甚至不需要使用MySQL服务器。这将使过程更快,编写脚本更轻松。

 

MySQL 工具和mysqlfrm

 

 

MySQL工具是由Oracle发布的一组脚本,帮助我们更简单地执行常见的DBA任务。它是用Python编写的,它唯一的依赖是Python连接器。在各种工具的名单中,我们将使用mysqlfrm工具来帮助我们恢复结构。

像往常一样,图像胜过千言万语。我们恢复一些表结构:

这是我们的表:

 

CREATE TABLE `new_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `name_idx` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

 

现在我们尝试从.frm文件恢复该信息,看看结果:

 

$ mysqlfrm --diagnostic /usr/local/mysql/data/test/new_table.frm
# WARNING: Cannot generate character set or collation names without the --server option.
[...]
CREATE TABLE `test`.`new_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` tinyint(4) NOT NULL,
PRIMARY KEY `PRIMARY` (`id`),
KEY `name_idx` (`name`)
) ENGINE=InnoDB;

 

 

结果挺不错

要注意的是这个工具有两种方法进行恢复。

  • 第一个是生成一个新的MySQL实例,并在那里运行结构恢复,类似于PeterZ在他的博客中解释的。你需要使用-server或-basedir目录以及-port。恢复完成后,它会关闭生成的实例。
  • 第二个与-diagnostic使用,读取.frm文件的每个字节来恢复所有可能的信息,但不需要MySQL实例。因此,这种方法可用于从损坏的.frm文件恢复所有可能的,甚至连MySQL都不能读取的信息。

正如我们在上一个例子的警告中看到的,并非所有信息可以通过第二种方法恢复。例如字符集和归类不能没有-server选项(第一种方法)进行恢复。我们看看如何使用生成的服务器来恢复.frm的信息:

 

$ mysqlfrm --server=root@127.0.0.1 --port 3307 ./new_table.frm
# Source on 127.0.0.1: ... connected.
# Starting the spawned server on port 3307 ... done.
# Reading .frm files
#
# Reading the new_table.frm file.
#
# CREATE statement for ./new_table.frm:
#




CREATE TABLE `new_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `name_idx` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

 

 

 

该工具连接到MySQL服务器,获得它需要的所有信息(basedir等),并在端口3307生成新实例。然后它使用新的实例来恢复.frm文件的信息。方便快捷:)

值得一提的是,不是所有需要的信息都存储在这些.frm文件。有一些信息是无法恢复的,例如FK约束和AI数字序列。

结论

MySQL工具是一个非常有用的工具集。在特定情况下,mysqlfrm可以用来从它们的.frm文件恢复一长列的表结构,使过程快速且易于编写脚本。

 

MySQL InnoDB 数据字典介绍

为什么InnoDB 需要字典

 

 

InnoDB字典是InnoDB用于维护用户表的各种信息的一组内部表。它作为人类和数据库之间的API。人类根据他们的名字参考表,而InnoDB通过整数标识符。字典存储表名和index_id之间的对应关系。

字典表是普通的InnoDB表,但对用户不可见。然而一些版本的MySQL在information_schema数据库中提供的字典只读访问。

字典被存储在ibdata1中。例如,SYS_TABLES的root页有id 8,所以它是ibdata1开头的第八页。

即使是MySQL 5.6,字典页也是冗余格式。我可能会在以后写更多关于记录格式的文章。现在只要知道冗余度是最早的记录格式就行了。它自4.0版本起可用,是当时唯一的格式。

 

 

SYS_TABLES

 

 

CREATE TABLE `SYS_TABLES` (
`NAME` varchar(255) NOT NULL DEFAULT '',
`ID` bigint(20) unsigned NOT NULL DEFAULT '0',
`N_COLS` int(10) DEFAULT NULL,
`TYPE` int(10) unsigned DEFAULT NULL,
`MIX_ID` bigint(20) unsigned DEFAULT NULL,
`MIX_LEN` int(10) unsigned DEFAULT NULL,
`CLUSTER_NAME` varchar(255) DEFAULT NULL,
`SPACE` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

 

所有字典表具有预定义的硬编码index_ids。这并不奇怪,只要InnoDB没有字典的字典:)。 SYS_TABLES有index_id 0-1。 SYS_TABLES的root页是页id 8。

 

NAME 是人类可读的表名。数据库名和表名。例如,对于表 sakila.actor ,NAME 就是 “sakila/actor”。

ID 为表的标识符。它是一个整数。在其他字典表中,表通过table_id 被引用。

N_COLS 是表中的列数。

 

我假设 TYPEMIX_IDMIX_LEN and CLUSTER_NAME 不重要。其实,我不知道这些字段是什么。不管怎样,它们从不用于数据恢复,所以我们把它们放到之后再研究。

SPACE 是表空间的标识符。因此ibdata1是SPACE 0,ibdata2是SPACE 1,每​​一个ibd文件都有自己的SPACE标识符。 SPACE表示表的索引存储在哪个表空间。

 

表sakila.actor的样本记录:

 

 

# ./bin/constraints_parser.SYS_TABLES -4f pages-1402815586/FIL_PAGE_INDEX/0-1 | grep sakila/actor
"sakila/actor" 61 4 1 0 80 "" 47
“sakila/actor” – 显然是表名. 61 – 表 id。4 是表中的字段数:

mysql> show create table sakila.actor\G
*************************** 1. row ***************************
Table: actor
Create Table: CREATE TABLE `actor` (
`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`actor_id`),
KEY `idx_actor_last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8

47 是SPACE 标识符。如果是0,如果innodb_file_per_table 被禁用。这不是在我的环境中:

If would be 0 if innodb_file_per_table were disabled. It’s not in my environment:

mysql> show variables like 'innodb_file_per_table';

+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

 

 

SYS_INDEXES

 

 

另一个重要的字典表SYS_INDEXES。它存储有关InnoDB索引的信息。

它的 index_id 是 0-3 ,且root 页储存在页11。

 

 

CREATE TABLE `SYS_INDEXES` (
`TABLE_ID` bigint(20) unsigned NOT NULL DEFAULT '0',
`ID` bigint(20) unsigned NOT NULL DEFAULT '0',
`NAME` varchar(120) DEFAULT NULL,
`N_FIELDS` int(10) unsigned DEFAULT NULL,
`TYPE` int(10) unsigned DEFAULT NULL,
`SPACE` int(10) unsigned DEFAULT NULL,
`PAGE_NO` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`TABLE_ID`,`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

表中的字段:

 

TABLE_ID 是表标识符。它是一个来自SYS_TABLES。

ID 是索引标识符。这是非常重要的字段。这是每个InnoDB页包含在其所属索引的头index_id中包含的。因此,如果我们想恢复一些表,我们需要找到属于表的PRIMARY索引,这意味着我们需要有一些具体的index_id的所有页。NAME 是索引名称。表sakila.actor 有两个索引:PRIMARY 和idx_actor_last_name。所以这些就是SYS_INDEXES 中的名称。

N_FIELDS 是索引中字段数。idx_actor_last_name 有一个字段,在SYS_INDEXES中也是。

TYPE 不是重要的字段。

SPACE 是InnoDB 表空间标识符,索引储存在其中。也许InnoDB 开发者遇见到在不同文件储存索引的可能性,当对目前MySQL版本,它与在SYS_TABLES中相同。

PAGE_NO 是所以的root页的标识符。我们知道InnoDB 以 B+tree 数据结构储存索引。所以B+tree 的root节点是由这个字段标识的root 页。

 

btree1z1

 

SYS_COLUMNS

 

SYS_COLUMNS 描述在表中的独立字段。它作为index_id 0-2储存。

 

CREATE TABLE `SYS_COLUMNS` (
`TABLE_ID` bigint(20) unsigned NOT NULL,
`POS` int(10) unsigned NOT NULL,
`NAME` varchar(255) DEFAULT NULL,
`MTYPE` int(10) unsigned DEFAULT NULL,
`PRTYPE` int(10) unsigned DEFAULT NULL,
`LEN` int(10) unsigned DEFAULT NULL,
`PREC` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`TABLE_ID`,`POS`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

 

TABLE_ID 是表标识符,它来自SYS_TABLES

 

POS 是在表中的字段的相对位置。

 

NAME 是字段名称。

 

MTYPE 和 PRTYPE 编码MySQL字段类型。InnoDB作为单独的产品开始了它的历史,与MySQL不相关。这两个字段是那个时候的产物。MySQL和InnoDB类型之间没有严格的对应关系。 InnoDB使用最适合特定MySQL类型的类型。这里的编码和归类也被存储。

LEN 是字段长度。

 

PREC 是一些MySQL类型的精度。

 

看到表 sakila.actor的示例是不是很有趣?就在这里。记得table_id 是61? 我们从SYS_TABLES得知。

 

 

61      0       "actor\_id"     6       1794    2       0
61      1       "first\_name"   12      2162959 135     0
61      2       "last\_name"    12      2162959 135     0
61      3       "last\_update"  3       525575  4       0

 

 

我们可以看到,smallint是两个字节,时间戳是四个字节。varchar(45)是135个字节。显然,这是最大的尺寸,不是字段的实际大小,它在每个记录都应不同。但是,为什么是135,而不是45。因为字段是UTF8,每个字符最多可以使用3个字节。 3*45等于 135。

 

SYS_FIELDS

今天最后一个表(也很重要)是 SYS_FIELDS。它储存在index_id 0-4。
它列出在所有索引的单个字段。

 

 

CREATE TABLE `SYS_FIELDS` (
`INDEX_ID` bigint(20) unsigned NOT NULL,
`POS` int(10) unsigned NOT NULL,
`COL_NAME` varchar(255) DEFAULT NULL,
PRIMARY KEY (`INDEX_ID`,`POS`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

 

该表非常简单。

INDEX_ID 是索引标识符,可以在SYS_INDEXES中找到。

POS 是在索引中的字段的位置。

COL_NAME 是字段名。

为什么关注?

我们究竟为什么需要InnoDB 字典?

有两个原因。首先,如果我们需要恢复表A,我们需要知道它的PRIMARY索引的index_id。学习它最简单的方法是InnoDB字典。

其次,你可能会注意到InnoDB字典储存有关字段名称和类型的信息。所以,如果我们不知道的表结构,我们可以从字典恢复。

 

 

 

恢复损坏的MySQL数据库Innodb引擎

 

unDROP for InnoDB 工具能用于恢复损坏的MySQL数据库。在这篇文章中,我们会展示当MySQL数据库的文件损坏,甚至innodb_force_recovery=6也无法帮助时,如何恢复数据库。

 

InnoDB表空间的损坏可能是多种原因造成的。一个即将报废的硬盘可能写入垃圾数据,导致页校验错误。然后InnoDB报告给错误日志:

 

InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 4.

 

MySQL差劲的启动脚本是众所周知的。一个简单的升级过程可能出现两个mysqld的进程写入同一表空间的情况。这也会导致损坏。有时,电源复位不仅损坏InnoDB文件,而且使文件系统对操作系统不可用。

InnoDB 对于页的操作非常严格。如果校验不匹配或头中一些字段包含非预期值,InnoDB明智地倾向于崩溃,以避免进一步的损坏。

首先会尝试以innodb_force_recovery选项启动MySQL。此选项的目的是让用户转储其数据。由于无法修复表空间,用户必须删除表空间,创建新的,并加载回数据。

innodb_force_recovery 接受从1到6的值。值越高,InnoDB就会禁用越多功能。

 

在本文章,我们假设MySQL 即使在innodb_force_recovery=6的情况下也不能启动。

 

恢复工具包直接对InnoDB文件进行操作,它可以从InnoDB页面读取记录。如果页的某一部分被破坏,它将跳过那块,并继续进一步读取页的记录。

所以,我们来损坏一些InnoDB文件并对表进行恢复。

 

损坏InnoDB

 

简单起见,我们将重写.ibd 文件用户数据的一部分。

 

事情情况中,损坏可能发生在索引PRIMARY的任何地方。

 

在表sakila.actor的PRIMARY索引的中间,我们将数据用128个字符“A”重写:

 

0000C058  00 00 00 02 00 32 01 00 02 00 1C 69 6E 66 69 6D 75 6D 00 05 .....2.....infimum..
0000C06C  00 0B 00 00 73 75 70 72 65 6D 75 6D 07 08 00 00 10 00 29 00 ....supremum......).
0000C080  01 00 00 00 00 05 1E 9F 00 00 01 4D 01 10 50 45 4E 45 4C 4F ...........M..PENELO
0000C094  50 45 47 55 49 4E 45 53 53 43 F2 F5 A9 08 04 00 00 18 00 26 PEGUINESSC.........&
0000C0A8  00 02 00 00 00 00 05 1E 9F 00 00 01 4D 01 1A 4E 49 43 4B 57 ............M..NICKW
0000C0BC  41 48 4C 42 45 52 47 43 F2 F5 A9 05 02 00 00 20 00 21 00 03 AHLBERGC....... .!..
0000C0D0  00 00 00 00 05 1E 9F 00 00 01 4D 01 24 45 44 43 48 41 53 45 ..........M.$EDCHASE
0000C0E4  43 F2 F5 A9 05 08 04 00 28 00 27 00 04 00 00 00 00 05 1E 9F C.......(.'.........
0000C0F8  00 00 01 4D 01 2E 4A 45 4E 4E 49 46 45 52 44 41 56 49 53 43 ...M..JENNIFERDAVISC
0000C10C  F2 F5 A9 0C 06 00 00 30 00 2C 00 05 00 00 00 00 05 1E 9F 00 .......0.,..........
0000C120  00 01 4D 01 38 4A 4F 48 4E 4E 59 4C 4F 4C 4C 4F 42 52 49 47 ..M.8JOHNNYLOLLOBRIG
0000C134  49 44 41 43 F2 F5 A9 09 05 00 00 38 00 28 00 06 00 00 00 00 IDAC.......8.(......
0000C148  05 1E 9F 00 00 01 41 41 41 41 41 41 41 41 41 41 41 41 41 41 ......AAAAAAAAAAAAAA
0000C15C  41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAAAAAA
0000C170  41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAAAAAA
0000C184  41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAAAAAA
0000C198  41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAAAAAA
0000C1AC  41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAAAAAA
0000C1C0  41 41 41 41 41 41 41 41 41 41 41 41 41 41 4E 4B 43 F2 F5 A9 AAAAAAAAAAAAAANKC...
0000C1D4  05 09 00 00 58 00 28 00 0A 00 00 00 00 05 1E 9F 00 00 01 4D ....X.(............M
0000C1E8  01 6A 43 48 52 49 53 54 49 41 4E 47 41 42 4C 45 43 F2 F5 A9 .jCHRISTIANGABLEC...
0000C1FC  04 04 00 00 60 00 22 00 0B 00 00 00 00 05 1E 9F 00 00 01 4D ....`."............M

 

 

 

损坏的 InnoDB 表使MySQL崩溃

 

MySQL如果读取损坏的数据页,mysql服务会崩溃:

 

 

mysql> SELECT COUNT(*) FROM sakila.actor

+----------+
| COUNT(*) |
+----------+
|      200 |
+----------+
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query

 

 

在崩溃之前,MySQL将究竟哪里出了问题写入错误日志,并转储错误页:

 

 

Version: '5.6.19-67.0'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  Percona Server (GPL), Release 67.0, Revision 618
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 4.
InnoDB: You may have to recover from a backup.
2014-07-14 20:18:44 7f060bfff700 InnoDB: Page dump in ascii and hex (16384 bytes):
len 16384; hex 1bce9a5000000004ffffffffffffffff0000000026c3095945bf00000000000000000

 

 

恢复 InnoDB 表损坏

 

当你看到在InnoDB表空间中有损坏,要做的第一件事就是以innodb_force_recovery选项启动MySQL。尝试从一到六的所有值是有意义的。

 

我们假定即使innodb_force_recovery=6,MySQL也不启动,或者它启动了,但任何SELECT都使它崩溃。

恢复计划如下:

  • 将损坏的 InnoDB 表空间拆分成页;以类型和index_id进行排序
  • 从表的PRIMARY索引中获取记录
  • DROP 损坏的表并创建一个新的
  • 将记录载入回MySQL

 

我们需要分析两个表空间:ibdata1中和actor.ibd(因为选项innodb_file_per_table= ON)。 InnoDB字典存储在ibdata1中,我们需要它才能知道表sakila.actor的PRIMARY索引的index_id。

 

 

解析Mysql的系统表空间ibdata1

 

 

root@test:~/recovery/undrop-for-innodb# ./stream_parser -f /var/lib/mysql/ibdata1
Opening file: /var/lib/mysql/ibdata1
File information:
ID of device containing file:        64768
inode number:                         8028
protection:                         100660 (regular file)
number of hard links:                    1
user ID of owner:                      106
group ID of owner:                     114
device ID (if special file):             0
blocksize for filesystem I/O:         4096
number of blocks allocated:          36864
time of last access:            1406832698 Thu Jul 31 14:51:38 2014
time of last modification:      1406833058 Thu Jul 31 14:57:38 2014
time of last status change:     1406833058 Thu Jul 31 14:57:38 2014
total size, in bytes:             18874368 (18.000 MiB)
Size to process:                  18874368 (18.000 MiB)
All workers finished in 0 sec

 

 

 

然后是actor.ibd

 

 

root@test:~/recovery/undrop-for-innodb# ./stream_parser -f /var/lib/mysql/sakila/actor.ibd
Opening file: /var/lib/mysql/sakila/actor.ibd
File information:

ID of device containing file:        64768
inode number:                         8037
protection:                         100660 (regular file)
number of hard links:                    1
user ID of owner:                      106
group ID of owner:                     114
device ID (if special file):             0
blocksize for filesystem I/O:         4096
number of blocks allocated:            224
time of last access:            1406832349 Thu Jul 31 14:45:49 2014
time of last modification:      1406832300 Thu Jul 31 14:45:00 2014
time of last status change:     1406832300 Thu Jul 31 14:45:00 2014
total size, in bytes:               114688 (112.000 kiB)
Size to process:                    114688 (112.000 kiB)
All workers finished in 0 sec
root@test:~/recovery/undrop-for-innodb#

 

恢复 InnoDB 字典

 

我们需要知道表sakila.actor的PRIMARY索引的index_id。参考关于InnoDB字典的更多信息。现在,我们只要获取sakila.actor的index_id:

 

 

root@test:~/recovery/undrop-for-innodb# ./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page -t dictionary/SYS_TABLES.sql |grep actor
000000000504    85000001320110  SYS_TABLES      "sakila/actor"  13      4       1       0       0       ""      1
00000000050D    8E0000013B0110  SYS_TABLES      "sakila/film\_actor"    20      3       1       0       0       ""      8
...

root@test:~/recovery/undrop-for-innodb# ./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page -t dictionary/SYS_INDEXES.sql |grep 13
000000000300    810000012D01D3  SYS_INDEXES     11      13      "REF\_IND"      1       0       0       304
000000000504    85000001320178  SYS_INDEXES     13      15      "PRIMARY"       1       3       1       3
000000000504    850000013201A6  SYS_INDEXES     13      16      "idx\_actor\_last\_name"        1       0       1       4
000000000505    860000013301CE  SYS_INDEXES     14      17      "PRIMARY"       1       3       2       3
...

 

 

 

因此,sakila.actor表的PRIMARY索引的index_id是15,转储数据中的第五列。

 

从表的PRIMARY索引恢复记录

 

 

c_parser 读取 InnoDB 页,将其与给定表结构进行匹配,并以制表符分隔值格式转储记录。

与InnoDB相反,当c_parser遇到损坏区域,它会跳过并继续读取页。

我们从 index_id 15读取记录,根据字典,它就是PRIMARY 索引。

 

 

root@test:~/recovery/undrop-for-innodb# ./c_parser -6f pages-actor.ibd/FIL_PAGE_INDEX/0000000000000015.page -t sakila/actor.sql > dumps/default/actor 2> dumps/default/actor_load.sql
root@test:~/recovery/undrop-for-innodb# cat dumps/default/actor
-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)
72656D756D07    08000010002900  actor   30064   "
root@test:~/recovery/undrop-for-innodb# ./c_parser -6f pages-actor.ibd/FIL_PAGE_INDEX/0000000000000015.page -t sakila/actor.sql > dumps/default/actor 2> dumps/default/actor_load.sql
root@test:~/recovery/undrop-for-innodb# cat dumps/default/actor
-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)
72656D756D07    08000010002900  actor   30064   "\0\0\0\0"      ""      "1972-09-20 23:07:44"
1050454E454C    4F50454755494E  actor   19713   "ESSC" ""      "2100-08-09 07:52:36"
00000000051E    9F0000014D011A  actor   2       "NICK"  "WAHLBERG"      "2006-02-15 04:34:33"
00000000051E    9F0000014D0124  actor   3       "ED"    "CHASE" "2006-02-15 04:34:33"
00000000051E    9F0000014D012E  actor   4       "JENNIFER"      "DAVIS" "2006-02-15 04:34:33"
00000000051E    9F0000014D0138  actor   5       "JOHNNY"        "LOLLOBRIGIDA"  "2006-02-15 04:34:33"
00000000051E    9F000001414141  actor   6       "AAAAA" "AAAAAAAAA"     "2004-09-10 01:53:05"
00000000051E    9F0000014D016A  actor   10      "CHRISTIAN"     "GABLE" "2006-02-15 04:34:33"
...
root@test:~/recovery/undrop-for-innodb# ./c_parser -6f pages-actor.ibd/FIL_PAGE_INDEX/0000000000000015.page -t sakila/actor.sql > dumps/default/actor 2> dumps/default/actor_load.sql
root@test:~/recovery/undrop-for-innodb# cat dumps/default/actor
-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)
72656D756D07    08000010002900  actor   30064   "\0\0\0\0"      ""      "1972-09-20 23:07:44"
1050454E454C    4F50454755494E  actor   19713   "ESSC" ""      "2100-08-09 07:52:36"
00000000051E    9F0000014D011A  actor   2       "NICK"  "WAHLBERG"      "2006-02-15 04:34:33"
00000000051E    9F0000014D0124  actor   3       "ED"    "CHASE" "2006-02-15 04:34:33"
00000000051E    9F0000014D012E  actor   4       "JENNIFER"      "DAVIS" "2006-02-15 04:34:33"
00000000051E    9F0000014D0138  actor   5       "JOHNNY"        "LOLLOBRIGIDA"  "2006-02-15 04:34:33"
00000000051E    9F000001414141  actor   6       "AAAAA" "AAAAAAAAA"     "2004-09-10 01:53:05"
00000000051E    9F0000014D016A  actor   10      "CHRISTIAN"     "GABLE" "2006-02-15 04:34:33"
...
root@test:~/recovery/undrop-for-innodb# ./c_parser -6f pages-actor.ibd/FIL_PAGE_INDEX/0000000000000015.page -t sakila/actor.sql > dumps/default/actor 2> dumps/default/actor_load.sql
root@test:~/recovery/undrop-for-innodb# cat dumps/default/actor
-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)
72656D756D07    08000010002900  actor   30064   "\0\0\0\0"      ""      "1972-09-20 23:07:44"
1050454E454C    4F50454755494E  actor   19713   "ESSC" ""      "2100-08-09 07:52:36"
00000000051E    9F0000014D011A  actor   2       "NICK"  "WAHLBERG"      "2006-02-15 04:34:33"
00000000051E    9F0000014D0124  actor   3       "ED"    "CHASE" "2006-02-15 04:34:33"
00000000051E    9F0000014D012E  actor   4       "JENNIFER"      "DAVIS" "2006-02-15 04:34:33"
00000000051E    9F0000014D0138  actor   5       "JOHNNY"        "LOLLOBRIGIDA"  "2006-02-15 04:34:33"
00000000051E    9F000001414141  actor   6       "AAAAA" "AAAAAAAAA"     "2004-09-10 01:53:05"
00000000051E    9F0000014D016A  actor   10      "CHRISTIAN"     "GABLE" "2006-02-15 04:34:33"
...
root@test:~/recovery/undrop-for-innodb# ./c_parser -6f pages-actor.ibd/FIL_PAGE_INDEX/0000000000000015.page -t sakila/actor.sql > dumps/default/actor 2> dumps/default/actor_load.sql
root@test:~/recovery/undrop-for-innodb# cat dumps/default/actor
-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)
72656D756D07    08000010002900  actor   30064   "\0\0\0\0"      ""      "1972-09-20 23:07:44"
1050454E454C    4F50454755494E  actor   19713   "ESSC" ""      "2100-08-09 07:52:36"
00000000051E    9F0000014D011A  actor   2       "NICK"  "WAHLBERG"      "2006-02-15 04:34:33"
00000000051E    9F0000014D0124  actor   3       "ED"    "CHASE" "2006-02-15 04:34:33"
00000000051E    9F0000014D012E  actor   4       "JENNIFER"      "DAVIS" "2006-02-15 04:34:33"
00000000051E    9F0000014D0138  actor   5       "JOHNNY"        "LOLLOBRIGIDA"  "2006-02-15 04:34:33"
00000000051E    9F000001414141  actor   6       "AAAAA" "AAAAAAAAA"     "2004-09-10 01:53:05"
00000000051E    9F0000014D016A  actor   10      "CHRISTIAN"     "GABLE" "2006-02-15 04:34:33"
...
"      ""      "1972-09-20 23:07:44" 1050454E454C    4F50454755494E  actor   19713   "ESSC" ""      "2100-08-09 07:52:36" 00000000051E    9F0000014D011A  actor   2       "NICK"  "WAHLBERG"      "2006-02-15 04:34:33" 00000000051E    9F0000014D0124  actor   3       "ED"    "CHASE" "2006-02-15 04:34:33" 00000000051E    9F0000014D012E  actor   4       "JENNIFER"      "DAVIS" "2006-02-15 04:34:33" 00000000051E    9F0000014D0138  actor   5       "JOHNNY"        "LOLLOBRIGIDA"  "2006-02-15 04:34:33" 00000000051E    9F000001414141  actor   6       "AAAAA" "AAAAAAAAA"     "2004-09-10 01:53:05" 00000000051E    9F0000014D016A  actor   10      "CHRISTIAN"     "GABLE" "2006-02-15 04:34:33" ...

 

 

我们找出了一些有效的记录,但肯定也有一些“垃圾”。注意在Nick Wahlberg之前恢复的记录。绝对应该有Penelope Guiness的,因为我们还没有在actor.ibd文件中重写该数据。

 

 

过滤器

 

我们可以通过对某些字段的可能值应用过滤器来提高恢复质量。在原始表中有200个记录,但前两个“垃圾”记录有一些奇怪的标识符(30064和19713)。我们知道actor标识符应在[1..300]的范围内。因此,我们要告诉解析器相匹配的条件。为此,我们在定义的actor表的actor.sql文件的注释中添加一个提示。该注释应当是特殊的格式事解析器能识别它们。 actor.sql部分文件的列表(注意注释后有一个逗号!):

 

 

CREATE TABLE `actor` (
`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT
/*!FILTER
int_min_val: 1
int_max_val: 300 */,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`actor_id`),
KEY `idx_actor_last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8;

 

应用过滤器后,识别出的记录看上去好多了:

 

root@test:~/recovery/undrop-for-innodb# ./c_parser -6f pages-actor.ibd/FIL_PAGE_INDEX/0000000000000015.page -t sakila/actor.sql > dumps/default/actor 2> dumps/default/actor_load.sql
root@test:~/recovery/undrop-for-innodb# head -10 dumps/default/actor
-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)
00000000051E    9F0000014D0110  actor   1       "PENELOPE"      "GUINESS"       "2006-02-15 04:34:33"
00000000051E    9F0000014D011A  actor   2       "NICK"  "WAHLBERG"      "2006-02-15 04:34:33"
00000000051E    9F0000014D0124  actor   3       "ED"    "CHASE" "2006-02-15 04:34:33"
00000000051E    9F0000014D012E  actor   4       "JENNIFER"      "DAVIS" "2006-02-15 04:34:33"
00000000051E    9F0000014D0138  actor   5       "JOHNNY"        "LOLLOBRIGIDA"  "2006-02-15 04:34:33"
00000000051E    9F000001414141  actor   6       "AAAAA" "AAAAAAAAA"     "2004-09-10 01:53:05"
00000000051E    9F0000014D016A  actor   10      "CHRISTIAN"     "GABLE" "2006-02-15 04:34:33"
00000000051E    9F0000014D0174  actor   11      "ZERO"  "CAGE"  "2006-02-15 04:34:33"
00000000051E    9F0000014D017E  actor   12      "KARL"  "BERRY" "2006-02-15 04:34:33"

 

 

你看,Penelope Guiness 的记录已经有啦。唯一的问题是 – 无效记录6-“AAAAA”-“AAAAAAAAA”。这是因为记录的actor_id 似乎为6,这与预期的相符。理想情况下,转储必须没有垃圾记录,所以你可能要尝试添加更多其他键的过滤器。

 

或者,我们可以稍后手动删除数据库中这个记录。

 

 

DROP 损坏的表并创建一个新表

一旦有了所有表的转储,我们就需要创建MySQL的新实例。

如果这是单一的表损坏,尝试innodb_force_recovery=6来删除表是有用的。

如果MySQL连启动都不行,尝试将损坏的actor.ibd移到其他地方。在DROP TABLEactor后的恢复模式中,MySQL会从字典中删除记录。如果actor.frm仍存在就删除它。

目的是清理并运行MySQL,准备好导入表转储。

一旦MySQL 准备创建一个空表actor时:

 

 

mysql> CREATE TABLE `actor` (
->     `actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
->     `first_name` varchar(45) NOT NULL,
->     `last_name` varchar(45) NOT NULL,
->     `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
->      PRIMARY KEY (`actor_id`),
->      KEY `idx_actor_last_name` (`last_name`)
->      ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Query OK, 0 rows affected (0.01 sec)
mysql>

 

 

将记录载入MySQL

接下来我们将从恢复的转储加载信息:

 

 

root@test:~/recovery/undrop-for-innodb# mysql --local-infile -uroot -p$mypass

Welcome to the MySQL monitor.  Commands end with ; or \g.
...
mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> source dumps/default/actor_load.sql
Query OK, 0 rows affected (0.00 sec)
Query OK, 199 rows affected, 1 warning (0.00 sec)
Records: 198  Deleted: 1  Skipped: 0  Warnings: 1

 

 

 

最后,我们要知道我们由于损坏丢失了多少数据。

c_parser 提供预期和实际找回数据的计数

 

在每页的开头,它给出了预期记录的数字:

 

-- Page id: 3, Format: COMPACT, Records list: Invalid, Expected records: (0 200)

 

这表示预期有200 个记录,但记录列表被破坏(因此,记录列表:无效)。

在每页的最后,它给出实际找到记录的总计。

 

-- Page id: 3, Found records: 197, Lost records: YES, Leaf page: YES

 

Mysqld: Incorrect Key File For Table ‘./mysql/ndb_binlog_index.myi’; 尝试恢复

适用于:

MySQL集群版本6.3及以上

本文信息适用于所有平台。

 

症状

在特定情况下,系统表ndb_binlog_index可能被损坏。

 

当尝试执行以下查询时,这个损坏最常见的症状是ERROR 1194:

 

 

query:
mysql> SELECT * from ndb_binlog_index;
ERROR 1194 (HY000): Table 'ndb_binlog_ index' is marked as crashed and should be repaired

 

表损坏也能从MySQL错误日志中被证实:

 

Faile d to flush master info file
Slave I/O thread exiting, read u p to log 'log‐bin.NNNNNN', position MMMMMMMMM
Error reading relay log event: slave SQL thread was killed
Error writing file 'path‐to‐binlog/log‐bin' (errno: 30)
mysqld: Incorrect key file for table './mysql/ndb_binlo g_index.MYI'; try to repair it
NDB Binlog: Writing row (A,B,C) to ndb_binlog_index: N

 

 

原因

磁盘故障是这种情况最可能的原因。

 

实际上,损坏可能就在磁盘故障后发生,示例如下:

 

 

kernel: sd 0:0:0:0: SCSI error: return code = 0x06000000
kernel: end_request: I/O error, dev sda, sector 112313
kernel: Buffer I/O error on device sda1, logical block 14039
kernel: lost page write due to I/O error on sda1
kernel: Aborting journal on device sda1.
kernel: journal commit I/O error
kernel: journal commit I/O error
kernel: journal commit I/O error
kernel: journal commit I/O error
kernel: ext3_abort called.
kernel: EXT3‐fs error (dev ice sda1): ext3_journal_start_sb: Detected aborted journal
kernel: Remounting filesystem read‐only
logrotd: Rotating log /var/log/ldapfe
mysqld: Failed to flush master info f ile
mysqld: Slave I/O thread exiting, read u p to log 'log‐bin.000007', position 59561189
mysqld: Error reading relay log event: slave SQL thread was killed

 

解决方案

建议的方法是使用以下命令:

 

REPAIR TABLE ndb_binlog_index table;

 

参考

https://dev.mysql.com/doc/refman/5.6/en/repairtable.html

 

 

MySQL错误日志中”InnoDB: Serious error! InnoDB is trying to free page though it is already marked as free in the tablespace! Assertion failure in thread in file fsp0fsp.c line mysqld got signal 11″

适用于:

MySQL服务器版本5.1及以上

本文档的信息适用于所有平台

 

症状

MySQL无法以运行中InnoDB存储引擎重启,你会在MySQL错误日志中看到像这样的错误:

 

 

InnoDB: Serious error! InnoDB is trying to free page 11200
InnoDB: though it is already marked as free in the tablespa ce!
InnoDB: Assertion failure in thread 16363778 in file fsp0fsp.c line 2981
mysqld got signal 11 ;

 

页号和线程号会不同。在fsp0fsp.c源代码文件中的行可能也不同但文件相同。

 

原因

有三种可能的原因,从最可能到最不可能排序;

  • 断电和写入缓冲开启或写入缓冲控制器没有运作的备用电池的磁盘驱动。
  • 两个MySQL的备份尝试与同一InnoDB数据文件工作。
    • 显示尝试与InnoDB同时运作的两个MySQL备份的错误日志中复制启动信息和时间戳检查。锁通常恩能够避免这个情况的发生。
  • 在InnoDB插件版本中的关于blob存储的罕见错误在MySQL 5.1.51和5.7中被修复。这一系列bugs包含这些情况:Bug:11762662, Bug:11762893, Bug:11763287

 

症状是当在InnoDB日志中指示其在崩溃恢复期间空闲,它检查到一个页被标记为空闲。

 

解决方案

如果你开启服务请求,我们有可能找到一个通常不可能的造成损坏较小的方法。用你的判断力决定是否立即启动恢复或寻求帮助。

 

恢复

首先创建数据目录,所有子目录和其他MySQL备份储存数据的位置的二进制(文件复制)备份。Gzip或其他压缩能减少需要的空间。很少情况下,一个恢复方法的尝试会阻碍其他方法,而且使用这个备份时必要的。部分的恢复过程如没有执行妥当,很可能会删除数据,所以一个好的备份仍是必须的。

 

你应该使用最低可能性的innodb_force_recovery级别来重新获取你的数据,从级别2 (5.5, 5.1, 5.0, 4.0及以下)开始。如果你没有使用很高级别,这对于启动后崩溃几秒到一分钟的服务器来说很正常,所以在你能访问服务器后尝试更多工作之前等待60秒。不要担心崩溃,它是因为后台清理,回滚,插入缓冲合并或撤销日志扫描任务的行为。只要转移到下一个级别。一旦能访问时间,继续以下步骤:

 

  1. 使用以下方法之一创建数据备份:
  2. 使用ALTER TABLE来讲所有InnoDB表转换为MyISAM。如果你在使用innodb_file_per_table,这个方法的磁盘使用空间最低并且通常会在工作时释放空间。如果需要的话,你也能说出索引来减少磁盘空间使用,但注意删除的是哪个,因为你需要之后再重建它们。
  3. 使用mysqldump程序来创建所有InnoDB表(5.5, 5.1, 5.0. 4.1及以下)的备份。一旦创建了备份,使用DROP TABLE来删除它们。
  4. 对于这部分的恢复,不要使用备份方法如InnoDB热备份或创建二进制副本的MySQL企业版备份。这些会复制将数据与错误一起复制。这是之前创建的二进制文件备份的附加。如果你没有两个备份的空间,你可能需要删除初始二进制副本来完成第一步。
  5. 如果INFORMATION_SCHEMA存在于你的MySQL版本,使用SELECT from INFORMATION_SCHEMA来确保所有表被转换,否则使用SHOW TABLES和操作系统搜索子目录中的*.ibd。留在InnoDB中的任何数据都将在下一步丢失,因此执行彻底检查是至关重要的。
  6. 删除所有遗留的InnoDB文件,ib_logfile *和ibdata *。这将删除在服务器中的所有InnoDB数据,失去尚未备份或转换为MyISAM的任何数据。请务必在执行之前认真检查你的备份或表转换为MyISAM。
  7. 重启MySQL,它会创造新的,空的,InnoDB文件。
  8. 或者使用ALTER TABLE从MyISAM转换回InnoDB,或重新加载mysqldump备份文件。一旦完成这个操作,你的服务器应该恢复正常。如果你删除索引来释放磁盘空间,现在将它们重新添加。

 

防止今后此类事件的发生

确保用于存储数据,在所有硬盘驱动的写缓冲被关闭。

确保任何写入缓存磁盘控制器有一个备用电池。

If you are affected by the blob bug, upgrade to MySQL 5.1.51 or 5.5.7 or later. 如果你受blob bug的影响,升级到MySQL 5.1.51或5.5.7或更高版本。

MySQL Error: 1039 Unexpected EOF found when reading file ‘%s’ (errno: %d)

讨论

该错误可能在MySQL读取表文件,VIEW,.frm文件,logs文件,全文索引文件,或有时间区信息的文件时发生。

 

意外的EOF错误表示MySQL得到一个小于预期的文件。一般情况下,你不会得到这个错误。但它说明你有损坏的文件系统,或损坏的表文件或日志或其他文件。或者是由于在MySQL本身的错误发生。

 

MySQL Error: 1015 Can’t lock file (errno: %d)

该错误表示MySQL在尝试锁一个文件时,接收到来自文件系统的错误信息。

该错误信息最常见的原因是外部应用访问MySQL数据文件。

这些情况通常包括:

  • Mysql运行时运行文件备份过程
  • 反病毒软件锁住文件(在Windows上)
  • Mysql运行时myisamchk被错误使用
  • 多个mysqld服务器访问同一数据文件
  • 你对mysqld指定了 –external-locking选项且系统锁不可靠

 

考虑到–external-locking选项,它应该从my.cnf被移除,除非你运行多个mysqld daemon访问相同数据文件(不建议使用)。更多信息参见系统文档边缘的外部资源链接。

MySQL Error: 1194 Table ‘%s’ is marked as crashed and should be repaired.

 

MySQL Error: 1194 Table ‘%s’ is marked as crashed and should be repaired.

以上信息表示指定表由于意外硬件或一个MySQL服务器的崩溃而处于不一致的状态。要完整检查表的一致性,使用以下语句:

 

CHECK TABLE table_name EXTENDED;

 

以上语句会扫描在给定表的所有行和键,并报告发现的错误。

CHECK TABLE选项和输出的完整描述参见MySQL手册 (查看在边框的外部资源)。

 

如果你得到任何’OK’或’Table is already up to date’以外的状态信息,你应该正常运行表的修复。运行以下语句进行恢复:

 

REPAIR TABLE table_name EXTENDED;

 

以上语句会指示MySQL尝试恢复指定表并报告状态。

REPAIR TABLE选项和输出的完整描述参见MySQL手册 (查看在边框的外部资源)。

强制MySQL InnoDB恢复参数innodb_force_recovery

强制InnoDB恢复

 

为了研究数据库页损坏,你能用SELECT … INTO OUTFILE从数据库中转储表。通常,以这种方式获得的大部分数据是完整的。严重的损坏可能导致SELECT* FROM tbl_name语句或InnoDB的后台操作崩溃或断言,甚至造成InnoDB前滚恢复崩溃。 在这样的情况下,可以使用innodb_force_recovery选项强制InnoDB存储引擎启动同时阻止后台操作运行,这样你就能转储表了。例如,你可以在重新启动服务器之前添加以下行到选项文件的[mysqld]部分:

 

[mysqld]

innodb_force_recovery = 1

 

 

警告

 

只有在紧急情况下将innodb_force_recovery设为大于0的值,你才能启动InnoDB并转储表。在进行此操作之前,确保你有数据库的备份副本,以备需要重建它。4及以上的值可以永久破坏数据文件。只有在数据库的独立物理副本的成功地测试了设置,才能在生产服务器实例使用4及以上的innodb_force_recovery设置。当强制InnoDB恢复,你应该总是以innodb_force_recovery=1启动,且仅在需要时增加值。

 

innodb_force_recovery默认为0(没有强制恢复的正常启动)。对于innodb_force_recovery允许的非零值是1至6。较大值包括较小值的功能。例如,为3的值包括所有的值1和2的功能。

 

如果你能以innodb_force_recovery为3或更低值转储你的表,那么你是比较安全的,只有在损坏的个人页的一些数据会丢失。4或更大的值被认为是危险的,因为数据文件可以被永久地损坏。值6被认为是严重的,数据库页被留在一个陈旧的状态,这反过来又可能带给B-trees和其它数据库结构更多的损坏。

 

作为一个安全措施,InnoDB 在innodb_force_recovery大于0时阻止INSERT,UPDATE或DELETE操作。对于MySQL5.6.15,将innodb_force_recovery设为4或更高会让InnoDB处于只读模式。

 

  • 1 (SRV_FORCE_IGNORE_CORRUPT)

即使服务器检测到损坏的页仍让它运行。试图使SELECT* FROM tbl_name跳过损坏的索引记录和页,这样有助于转储表。

 

  • 2 (SRV_FORCE_NO_BACKGROUND)

阻止主线程和任何清除线程的运行。如果崩溃会在清除操作中发生,该恢复值会阻止它。

 

  • 3 (SRV_FORCE_NO_TRX_UNDO)

不要在崩溃恢复后运行事务回滚。

 

  • 4 (SRV_FORCE_NO_IBUF_MERGE)

阻止插入缓冲合并操作。如果它们会导致崩溃,不要做这些。不计算表统计。这个值可以永久损坏数据文件。使用这个值后,准备好删除并重建所有辅助索引。在MySQL5.6.15中,设置InnoDB为只读。

 

  • 5 (SRV_FORCE_NO_UNDO_LOG_SCAN)

在启动数据库时不检查撤消日志:InnoDB将即使未完成的事务也作为已提交。这个值可能永久损坏数据文件。在MySQL5.6.15中,设置InnoDB为只读。

 

  • 6 (SRV_FORCE_NO_LOG_REDO)

在启动数据库过程中不检查重做日志文件:跳过恢复对重做日志进行前滚。这个值可能永久损坏数据文件。数据库页被留在一个陈旧的状态,这反过来又可能带给B-trees和其它数据库结构更多的损坏。在MySQL5.6.15中,设置InnoDB为只读。

 

你可以从表中SELECT来转储它们。innodb_force_recovery的值为3或更低,你可以DROP或CREATE表。在MySQL 5.6.27中,DROP TABLE还受大于3的innodb_force_recovery值支持。

 

如果你知道一个给定表在回滚造成崩溃,你可以将其删除。如果遇到所造成失败的大规模导入的失控回滚或ALTER TABLE,你可以杀掉mysqld进程,并设置innodb_force_recovery为3使数据库启动而不回滚,然后DROP导致失控回滚的表。

 

如果表数据中的损坏阻止你转储整个表的内容,带ORDER BY primary_key DESC子句的查询能够转储损坏部分后的表的部分。

设置innodb_force_recovery为大于1的值后,虽然你可以绕过一些问题,例如强制启动MYSQL实例,同时绕过一些已经损坏的数据结构。但却可能引发复杂查询(含有WHERE,ORDER BY或其他子句的查询)出现报错。在这种情况下,你可能只能运行基本的SELECT* FROM t 的全表查询;这种情况就全库导出重建吧!

 

 

 

沪ICP备14014813号-2

沪公网安备 31010802001379号