MySQL InnoDB 表损坏,显示错误: “MySQL is trying to open a table handle but the .ibd file for table ### does not exist”

适用于:

MySQL服务器版本4.0及以上

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

 

症状

当尝试访问表test.t1时,出现以下错误:

 

150512 16:30:01 [ERROR] MySQL is trying to open a table handle but the .ibd
file for
table test/t1 does not exist.
Have you deleted the .ibd fil e from the database directory under
the MySQL datadir, or have you used DISCARD TABLESPACE?
See http://dev.mysql.com/doc/refman/5.1/en/innodb‐troubl eshooting.html
how you can resolve the problem.

 

原因

这个问题的原因是缺少相关表t1中的.ibd文件。这表示没有任何语句可以对表T1运行。

由错误本身以及检查该文件是否存在确认:

 

 

shell> ls ‐lahR /var/lib/mysql/
/var/lib/mysql/test:
total 21G
drwx‐‐‐‐‐‐ 2 mysql mysql 32K may 12 03:55 .
drwxr‐xr‐x 7 mysql mysql 4,0K nov 10 2014 ..
...
‐rw‐rw‐‐‐‐ 1 mysql mysql 8,6K may 12 03:16 t.frm
‐rw‐rw‐‐‐‐ 1 mysql mysql 20M may 12 13:37 t.ibd
‐rw‐rw‐‐‐‐ 1 mysql mysql 8,5K ago 10 2014 t1.frm
‐rw‐rw‐‐‐‐ 1 mysql mysql 8,5K may 12 03:16 t2.frm
‐rw‐rw‐‐‐‐ 1 mysql mysql 128K may 12 03:16 t2.ibd

 

 

进一步查看MySQL错误日志,当错误开始出现,即truncate table在运行时,就能看到。该语句无法重建各自的.ibd文件,所以文件丢失:

 

 

140810 5:05:03 InnoDB: TRUNCATE TABLE test/t1 failed to create a new tablespace

 

解决方案

重建表:

 

Drop table:

mysql> DROP TABLE test.t1;
The following error may be seen in the error log afterwards, but it's basically saying the
tablespace was still present in InnoDB Data Dictionary and that eventually was removed:
150513 14:49:08 InnoDB: Error: table 'test/t1'
InnoDB: in InnoDB data dictionary has tables pace id 607381,
InnoDB: but tablespace with that id or name does not exist. Have
InnoDB: you deleted or moved .ibd files?
InnoDB: This may also be a table created with CREATE TEMPORARY TABLE
InnoDB: whose .ibd and .frm files MySQL automatically removed, but t he
InnoDB: table still exists in the InnoDB internal data dictionary.
InnoDB: Please refer to
InnoDB: http://dev.mysql .com/doc/refman/5.1/en/innodb‐troubleshootingdatadict.html
InnoDB: for how to resolve the issue.
InnoDB: We removed now the InnoDB int ernal data dictionary entry
InnoDB: of table `test`.`t1`.

 

  1. 再次Create table
  2. 测试表的访问来确认现在能运行 (ex: optimize table)

 

mysql> OPTIMIZE TABLE test.t1;

 

参考

https://dev.mysql.com/doc/en/glossary.html#glos_ibd_file

https://dev.mysql.com/doc/en/truncatetable.html

https://dev.mysql.com/doc/en/droptable.html

https://dev.mysql.com/doc/en/createtable.html

https://dev.mysql.com/doc/en/innodbtroubleshooting.html

Keywords

DATA DICTIONARY; DISCARD; ERROR; FILES; FRM; MISSING; MYSQL; TABLESPACE; TRUNCATE TABLE

MySQL 物理备份恢复到非空数据目录后的多个InnoDB损坏或崩溃

适用于:

MySQL企业版备份版本3.5及以上

MySQL服务器版本4.0及以上

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

 

症状

InnoDB引擎依赖于数据和日志文件的逻辑一致性。

 

InnoDB可能会遇到不可预知的行为,包括与来自不同环境的混合的文件损坏有关的崩溃和错误。

 

一个错误的例子:

2015‐03‐18 11:24:44 11904 [Note] InnoDB: Database was not shutdown normally!
2015‐03‐18 11:24:44 11904 [Note] InnoDB: Starting crash recovery.
2015‐03‐18 11:24:44 11904 [Note] InnoDB: Reading tablespace infor mation from the .ibd files...
2015‐03‐18 11:24:44 11904 [ERROR] InnoDB: Attempted to open a previously opened tablespace. 
Previous tablespace test/t uses space ID: 3695 at filepath: ./test/t.ibd.
Cannot open tablespace test/#sql2‐1ab0‐5 which uses space ID: 3695 at filepath: ./test/#sql2‐1ab0‐5.ibd
2015‐03‐18 11:24:44 7fe 914a04720 InnoDB: Operating system error number 2 in a file operation.
InnoDB: Th e error means the system cannot find the path specified.
InnoDB: If you are installing InnoDB, remember that you must creat e
InnoDB: directories yourself, InnoDB does not create them.
InnoDB: Error: could not open single‐table tablespace file ./test/#sql2‐1ab0‐5.ibd

 

原因

备份被还原到有有旧的InnoDB数据或日志文件的目录中。

 

解决方案

保证InnoDB文件之间的一致性最简单的方法就是将备份恢复到空目录中。

 

MySQL Enterprise Backup (MEB) – 执行恢复操作:

Important

  • 当执行一个完整的恢复(例如,当备份数据被用来建立一个新的MySQL服务器或用于替换现有MySQL服务器的所有数据),确保目标数据目录都是干净的,不含旧的或不需要的数据文件(这可能需要手动删除文件位置,通过– datadir 和 –innodb_data_file_path两个选项);否则,将–force选项添加到restore命令来覆盖旧数据。使用–use-tts选项创建的备份恢复不需要同样的清理(在这种情况下,其他要求在第1.4节,“恢复备份创建与–use-TTS选项”应用),通常对恢复部分备份没有必要。

 

参考

http://dev.mysql.com/doc/mysqlenterprisebackup/en/restore.restore.html

Keywords

CRASH; DATABASE; ERROR; MYSQL; RESTORE

解决 CSV Table is Marked as Crashed and Should be Repaired; Corrupted or Mangled Data; Error 1194

适用于:

MySQL服务器版本4.1及以上

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

 

症状

当尝试访问一个CSV表时,发生以下错误。

ERROR 1194 (HY000): Table ‘t1’ is marked as crashed and should be repaired

 

表的损坏不会总显示为以上错误。根据数据的损坏,SELECT可能有用,但会返回损坏的数据。

 

更改

这通常会发生在以下情况之后:

  • MySQL的崩溃 – 这包括操作系统崩溃,如由于断电等情况 。
  • 数据目录的磁盘不够。

 

原因

CSV表被损坏。像之前说到的,这通常由于非正常情况发生。

 

注:当 SELECT 语句由于损坏失败,INSERT 语句仍会运行,因为对于CSV表,插入行是一行或多行数据文件的简单追加。

 

你可以看到由于其表打开.CSV副本的损坏。例如,假设是表csvtest.t1,那么该文件是${datadir}/csvtest/t1.CSV,其中${datadir}是用于MySQL实例的数据目录。损坏通常会看起来像一行已被清空,且下一行在在同一列开始:

1,”2014-01-11 12:32:22″,”abc”

2,”2014-01-15 13:11:12″,”def”

3,”20144,”2014-01-28 18:00:19″,”jkl”

5,”2014-02-04 12:49:30″,”mno”

6,”2014-02-04 13:22:25″,”pqr”

 

在上面的示例中第三行被损坏且包含两部分:

  • 3,”2014

这是被清空的行

  • 4,”2014-01-28 18:00:19″,”jkl”

这是下一行

 

解决方案

你可以通过两种方式解决该问题:

使用 REPAIR TABLE

手动编辑数据文件的文件

 

REPAIR TABLE

REPAIR TABLE命令是最简单的方法,但是只有当表被标记为崩溃的时才能运行命令。它的运作方法是在行被损坏之前清空数据文件:

REPAIR TABLE csvtest.t1;

 

警告:因为REPAIR TABLE for a CSV table 在发现第一行被损坏时就会清空表,数据丢失会发生!

 

手动编辑数据文件

手动编辑文件能在文本编辑器中通过删除文件被损坏的部分完成。例如根据以上示例,文件能被更改为:

1,”2014-01-11 12:32:22″,”abc”

2,”2014-01-15 13:11:12″,”def”

4,”2014-01-28 18:00:19″,”jkl”

5,”2014-02-04 12:49:30″,”mno”

6,”2014-02-04 13:22:25″,”pqr”

 

强烈建议对数据文件的副本进行操作。

 

这种方法的优点是,你必须改变更细粒度的控制,例如上述更改,仅行id=3将丢失,而不是id> =3的所有行。

 

要复制回数据文件,使用以下步骤(假设Linux或Unix;类似的步骤应用于Windows)将csvtest 和 t1 用你的表的数据库和表名替换:

  1. mysql> LOCK TABLES csvtest.t1 WRITE;
  2. mysql> FLUSH TABLES csvtest.t1;
  3. shell$ ls ‐l /var/lib/msyql/csvtest/t1.CSV
  4. shell$ cp /tmp/t1.CSV /var/lib/msyql/csvtest/t1.CSV
  5. Make sure the /var/lib/msyql/csvtest/t1.CSV has the same owner and access permissions as found

in step 3.

  1. mysql> UNLOCK TABLES;
  2. mysql> SELECT * FROM csvtest.t1 WHERE id = 6;

 

在步骤7. 的查询验证在CSV文件的最后一行是否能被找到 – 这在损坏发生之后。

 

参考

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

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

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

NOTE:1023810.1 How do I exchange data between applications using CSV Tables?

 

Keywords

CSV; DATA FILE; MYSQL; OUT OF DISK; CORRUPTED DATA

MySQL创建函数由于Error 1548失败

适用于:

MySQL服务器版本5.5及以上

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

 

症状

尝试从GUI客户端创建函数语法如下:

 

CREATE FUNCTION `mydb`.`f_seq_gen` (`applicationid` text) RETURNS INT
BEGIN
DECLA RE nextval bigint(20);
select seqno into nextval from mydb.seqgen where application_id =
applicationid;
update mydb.se qgen SET seqno = seqno + 1 where application_id = applicationid;
RETURN nextval;
END

 

但是失败了:

 

 

ERROR 1548 (HY000): Cannot load from mysql.proc. The table is probably
corrupted

 

原因

 

表mysql.proc被损坏或表结构不正确。

通常这由于从不同版本的更新或转储/恢复造成。

 

解决方案

首先的步骤应该是:

 

CHECK TABLE `mysql`.`proc` EXTENDED;
REPAIR TABLE `mysql`.`proc`;

 

然后尝试重建储存的函数。

 

如果失败,很可能是因为表结构不正确。这通常是由于从不同版本的更新或转储/恢复造成的。

 

直接的解决方案是运行

 

mysql_upgrade -uroot  --force -p

 

使系统表回到正确结构。

 

如果你不想检查所有的数据表(以免耗时太长),那就指定选项upgradesystemtables。

 

Keywords

MYSQL; UPGRADE

解决MySQL Server Crash: “InnoDB: Error: trying to access page number … which is outside the tablespace bounds.”

适用于:

MySQL服务器版本5.1到5.1 [发行版5.1]

MySQL服务器版本4.0及以上

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

 

症状

当尝试在例如断电的崩溃后启动MySQL时,发生类似以下的错误:

 

InnoDB: Assertion failure in thread 4096 in file fil0fil.c line 3959
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing‐recovery.html
InnoDB: about forcing recovery.
130227 11:54:17 ‐ mysqld got signal 11 ;

 

原因

这是由于InnoDB在文件系统级别的数据文件损坏导致的。

 

注意事项

许多操作系统和一些磁盘硬件愚弄flushtodisk操作。它们可能会告诉mysqld flush已经发生,即使并没有。那么写入磁盘的变化的耐久性得不到保障,而且在最坏的情况下,突然断电甚至能损坏InnoDB数据库。在SCSI磁盘控制器或在磁盘本身使用电池备用的磁盘高速缓存加快文件刷新,并使得操作更安全。你也可以尝试使用Unix命令hdparm的禁用磁盘写入硬件缓存的缓存,或使用对特定硬件供应商的一些其他命令。

 

解决方案

可以采取以下步骤从损坏中恢复:

  1. 当MySQL被关闭,通过复制所有数据库文件创建备份。

这是非常重要的,因为innodb_force_recovery的使用会导致进一步的损坏。

  1. 尝试在innodb_force_recovery启用下启动MySQL。很可能会需要很大的值。在恢复模式下,尝试转储尽可能多的数据,在这之后InnoDB必须被重新初始化。这个过程在参考手册中有描述:Starting

InnoDB on a Corrupted Database.

  1. 从备份中恢复。这通常是唯一能成功的方法。如果你选择该方法,建议首先创建损坏的文件的备份,便需要进一步从其中恢复数据。

 

参考

https://dev.mysql.com/doc/refman/5.6/en/innodbparameters. html#sysvar_innodb_force_recovery

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

NOTE:1348707.1 Errors and/or Corruption when Performing DDL on Partitioned Tables

NOTE:1343198.1 InnoDB: error in sec index entry Message in MySQL Server Error Log File

NOTE:1024121.1 ” InnoDB: Warning: purge reached the head of the history list” in MySQL Error Log

NOTE:1438677.1 MySQL Server Variable: innodb_doublewrite; The InnoDB Doublewrite Buffer; Innodb_dblwr_pages_written; Innodb_dblwr_writes;

NOTE:1476982.1 What do I do with InnoDB message “Database page corruption on disk or a failed fileread of page”

 

Keywords

ASSERTION; DATA FILE; FILE SYSTEM; INNODB STORAGE ENGINE; MYSQL; PAGE NUMBER; RECOVER; SCSI; TABLESPACE

解决MySQL InnoDB Error: Data File ibdata2 Uses Page Size … But the Only Supported Page Size In This Release Ss=16384

适用于:

MySQL服务器版本5.5到5.5 [发行版5.5]

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

 

症状

当重新启动MySQL5.5.20或5.5.21时,MySQL无法启动,并且在错误日志中出现以下错误:

 

121215 11:25:25 InnoDB: Error: data file /mysql_data/mysql_databases/ibdata2 uses page size
1024,
12121 5 11:25:25 InnoDB: but the only supported page size in this release is=16384
121215 11:25:25 InnoDB: Could not open or create data files.

 

报告的ibdata2页大小可以有除了1024的其他尺寸。

 

更改

这个问题通常在使用ALTER TABLE语句改变一个InnoDB表的KEY_BLOCK_SIZE属性时发生,例如从一个未压缩表切换到压缩表时。

 

原因

这是由于防止从MySQL5.6降级的更改而造成的复原,其支持除16k以外的页大小。

 

参见 Bug 13698765 64160: PAGE SIZE 1024 BUT THE ONLY SUPPORTED PAGE SIZE IN THIS RELEASE IS=16384.

 

解决方案

解决的办法是升级到MySQL5.5.22或更高版本。

建议升级到最新的补丁版本,以获得所有最新的补丁。

 

参见:

How to Download MySQL Server 5.6, 5.5, 5.1 or 5.0; Standard Edition, Enterprise Edition; Advanced, Pro, Classic, Patch

How to Upgrade your Existing MySQL Server to MySQL 5.6 Version (this also applies to MySQL 5.5)

 

参考

BUG:13698765 64160:

PAGE SIZE 1024 BUT THE ONLY SUPPORTED PAGE SIZE IN THIS RELEASE

IS=16384

 

 

NOTE:1300654.1 How to Download MySQL Server 5.6, 5.5, 5.1 or 5.0; Standard Edition, Enterprise Edition; Advanced, Pro, Classic, Patch

NOTE:1319877.1 How to Upgrade your Existing MySQL Server to MySQL 5.6 Version

NOTE:1589556.1 How does Patching Work in MySQL?; How to Apply All the Latest Patches?; How to Find the Latest Patches

Didn’t find what you are looking for?

 

Keywords

DATA FILE; MYSQL; PATCH; REGRESSION; TABLESPACE; INNODB STORAGE ENGINE

MySQL ERROR 1033 Accessing Table

适用于:

MySQL服务器版本5.0到5.6 [发行版5.0到5.6]

本文信息适用于所有平台

 

目标

如果在访问表时你看到以下错误信息,这表示表结构文件.frm已被损坏。

 

ERROR 1033 (HY000): Incorrect information in file: './world/Country.frm'"

 

解决方案

如果.frm文件已被严重损坏,那就没有简单的方法来恢复它。你能从备份中恢复表,或按照以下的解决方法:

 

  1. 假设你有表结构,在同一服务器的另外数据库中创建一个类似的表。
  2. 现在从其他数据库将.frm文件复制到world数据库: cp Country.frm <datadir>/world/
  3. 检查文件的权限,并确保新复制的文件与现有的文件是相同的所有者和组,
  4. 现在,你应该能够用现有数据访问表
  5. 你现在可以正常执行所有表操作。

 

注:你能在线操作,不需要重启。但是要确保表在活动时无法被任何线程访问,这可能会再次导致崩溃。

 

Keywords

ERROR MESSAGE; FRM; RECOVER; TABLE STRUCTURE

如何处理MySQL InnoDB信息 “Database page corruption on disk or a failed file read of page”

 

适用于:

MySQL服务器版本4.0及以上

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

 

症状

MySQL服务器由以下信息崩溃:

 

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

 

原因

为了保护数据,InnoDB使用校验和(与页储存在一起)。当InnoDB从磁盘读取时,它计算每个页的校验和,并与磁盘加载的校验和进行比较。如果值是不同的,可能真的发生了一些错误。InnoDB将关闭MySQL服务器,以防止进一步的逻辑或物理损坏。

 

解决方案

如何找出损坏发生的原因

没有通用的解决方案。最典型的是有一些硬件问题,例如:物理磁盘或内存故障,坏的驱动器/控制器,甚至操作系统内核的bug。下面是一些建议:

 

  • 在Linux平台上,有时会重置页缓存能解决这个问题:

echo 2 > /proc/sys/vm/drop_caches

  • 检查系统日志有没有可能的硬件故障。
  • 如果InnoDB每次在特定页崩溃,最典型的是物理磁盘发生故障:运行对于你的OS /硬件的详细磁盘诊断。
  • 如果崩溃是随机的且不在相同查询重复,可能是RAM故障:运行详细的RAM诊断。
  • 在MySQL关闭时,用innochecksum工具检查InnoDB文件是有帮助的。

 

如何从损坏中恢复

最重要的是执行详细的硬件诊断,以消除问题扩散的机会。如果操作系统I / O缓存是磁盘读损坏的原因,重置缓存或重新启动操作系统应有助于消除当前的问题,数据库可能会重新运作。

 

有时唯一的解决办法是在有效恢复模式下备份数据。Sometimes the only

 

参考

http://dev.mysql.com/doc/en/forcinginnodbrecovery.html

http://dev.mysql.com/doc/en/innochecksum.html

MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据

适用于:

MySQL服务器版本4.1到5.6 [发行版4.1到5.6]

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

 

目标

如何使用undrop for innodb从损坏的表中提取数据

 

 

解决方案

使用工具有时可能从无法用innodb_force_recovery读取的表中恢复数据。

undrop可以直接读取数据库的ibdata1文件,来获取数据字典信息和必要的恢复信息。

通常,该工具从整个(多个)ibdata文件且/或独立的InnoDB tablespace文件 (innodb_file_per_table在使用中的.ibd文件)提取索引页。Blob页被提取到可应用的另外的子目录

一旦数据被提取到索引页,下一步就是从数据目录恢复主键或一般聚类索引ID,然后将数据提取到适于使用LOAD DATA INFILE的文件。

如果可以的话,以要恢复的(多个)数据库的至少一个schema dump启动,需要时使用innodb_force_recovery。即使一个过时的备份也好过什么都没有。虽然UnDROP有时能从ibdata文件中提取一个有效表定义,它不擅于处理所有列类型。如果你完全没有备份,.frm文件能被用于重建表定义。如果你没有任何备份或.frm文件,那么最后一招就是UnDROP 能从idbata提取的表定义能尝试至少恢复一些数据。

 

首先stream_parser是用于从ibdata提取页的工具。它的使用很简单:

 

./stream_parser -f <path_to_ibdata>

 

页会被默认提取到”pages-<ibdata_file_name>”。索引页被储存在子目录FIL_PAGE_INDEX,且blob页被储存在子目录FIL_PAGE_TYPE_BLOB。

 

 

要提取表的所有数据,有必要识别表的主键的数据目录索引ID (在没有主键时的一般索引)。这能通过使用UnDROP工具的”recover_dictionary.sh”脚本,将从被提取的索引页提取的字典数据放到在运行服务器的’test’ schema,像这样:

 

$ ./recover_dictionary.sh

Generating dictionary tables dumps... OK
Creating test database ... OK
Creating dictionary tables in database test:
SYS_TABLES ... OK
SYS_COLUMNS ... OK
SYS_INDEXES ... OK
SYS_FIELDS ... OK
All OK
Loading dictionary tables data:
SYS_TABLES ... 1845 recs OK
SYS_COLUMNS ... 22029 recs OK
SYS_INDEXES ... 4994 recs OK
SYS_FIELDS ... 6070 recs OK

All OK


现在字典能被查询来找出索引相对于任何给定表的索引ID。

给出的示例是对于在moodle2 schema中的表mdl2_user:

 

mysql> SELECT SYS_TABLES.NAME TABLE_NAME, SYS_TABLES.ID TABLE_ID,
SYS_INDEXES.NAME INDEX_NAME, SYS_INDEXES.ID INDEX_ID FROM SYS_TABLES LEFT JOIN
SYS_INDEXES ON SYS_TABLES.ID = SYS_INDEXES.TABLE_ID WHERE SYS_INDEXES.NAME LIKE '%PRIMARY%' AND SYS_TABLES.NAME LIKE 'moodle2/mdl2_user' AND SYS_INDEXES.NAME IN ('PRIMARY', 'GENERAL_CLUSTERED_INDEX');

+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐ ‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+
| TABLE_NAME | TABLE_ID | INDEX_NAME | INDEX_ID |
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐ ‐‐‐‐‐‐+
| moodle2/mdl2_user | 646 | PRIMARY | 1867 |
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐ +‐‐‐‐‐‐‐‐‐‐+

1 row in set (0.00 sec)


INDEX_ID返回与名称1相应的提取的页文件:

$ ls pages‐ibdata1/FIL_PAGE_INDEX/*1867.page
pages‐ibdata1/FIL_PAGE_INDEX/0000000000001867.page
c_parser



此时有了已知的表定义,数据能被c_parser恢复,像这样,其中mdl2_user.sql 包含表定义:


$ ./c_parser ‐b "./pages‐ibdata1/FIL_PAGE_TYPE_BLOB" ‐p "dumps/moodle2" ‐l
dumps/moodle/mdl2_user.load ‐5f pagesibdata1/
FIL_PAGE_INDEX/0000000000001867.page ‐t mdl2_user.sql

 

对每个schema使用以下脚本和在转储目录中的给定表定义,所有在数据目录找到的表能被提取到适合LOAD DATA INFILE的文件,以及分开的.load文件来加载它们。如果原始表定义不能被提供或从.frm文件被提取,反注释sys_parser行只作为最后方法。如果原始表defs能被提供,它们应该被作为分开的sql文件储存在dumps/<schema>/<table>.sql:

 

#!/bin/bash

RECOVERY_DB="test"
USER="root"
PASS="somepass"
DUMPS="dumps"

# Create schema

echo > ${DUMPS}/schema.sql
for DB in `mysql ‐‐user=${USER} ‐‐password=${PASS} ‐NBe "select name from
${RECOVERY_DB}.sys_tables" | sed ‐r "s/^(.*)\/.*$//" | grep ‐v SYS_ | sort ‐u `
do
mkdir ‐p ${DUMPS}/${DB}
echo "Creating schema for $DB..."
echo >> ${DUMPS}/schema.sql
echo "CREATE DATABASE IF NOT EXISTS $DB;" >> ${DUMPS}/schema.sql
for TABLE in `mysql ${RECOVERY_DB} ‐‐user=${USER} ‐‐password=${PASS} ‐NBe
"SELECT NAME FROM SYS_TABLES WHERE NAME LIKE '${DB}/%'"`

do
echo $TABLE
# ./sys_parser ‐u${USER} ‐p${PASS} ‐d ${RECOVERY_DB} ${TABLE} | tee
${DUMPS}/${TABLE}.sql >> ${DUMPS}/schema.sql
PKEY=`mysql ${RECOVERY_DB} ‐BNe "SELECT SYS_INDEXES.ID FROM SYS_TABLES
LEFT JOIN SYS_INDEXES ON (SYS_TABLES.ID = SYS_INDEXES.TABLE_ID) WHERE
SYS_TABLES.NAME = \"${TABLE}\" AND SYS_INDEXES.NAME=\"PRIMARY\""`
echo "pkey = $PKEY"
PAGE="pages‐ibdata1/FIL_PAGE_INDEX/`printf '%016u' ${PKEY}`.page"
echo "PAGE = $PAGE"
./c_parser ‐b "./pages‐ibdata1/FIL_PAGE_TYPE_BLOB" ‐p "./${DUMPS}/${DB}" ‐
l ${DUMPS}/${TABLE}.load ‐5f ${PAGE} ‐t ${DUMPS}/${TABLE}.sql > ${DUMPS}/${TABLE}

done
done

sys_parser

 

像之前所说的,sys_parser能被用于从ibdata文件提取表定义,但它仅应当作为最后手段。可能需要一些猜测,而且如果不能提供有效的表定义,从ibdata完整提取可用数据就不太可能了。

 

从.frm文件提取有效表定义

 

使用MySQL Utilities包的mysqlfrm从未损坏的.frm文件提取有效定义是可能的。要注意的是在诊断模式下使用mysqlfrm可能遇到与使用sys_parser从ibdata提取数据相同的问题。所以使用mysqlfrm与服务器标识是很重要的。输出必须被调整来与c_parser运作,因为如果命令行,警告,或默认字符集信息在表定义中被找到,c_parser会终止。这里是提取表定义和单个schema.sql被用于从在给定目录中找到的所有.frm文件创建schema(s)的方式:

 

 

#!/bin/bash

for FRM in `find ../datadir/ ‐type f ‐wholename "*frm" | sort`

do

mysqlfrm ‐‐server=root:somepass@localhost:../datadir/mysql.sock ‐‐port=33307
$FRM | extract_schema.pl
if [ ${PIPESTATUS[0]} ‐ne 0 ]; then
echo "$FRM is corrupt"
fi
done
extract_schema.pl像这样:

!/usr/bin/perl
open (SCHEMAFILE, '>>', "schema.sql") or die "Can not write to schema.sql $!";
$schema = "";
$table = "";

while (<STDIN>) {
$origline = $ _;
chomp;
if (/^ CREATE TABLE.*$/) {
m/.*CREATE TABLE \`(. *)\`\.\`(.*)\`[[:space:]]\(/;
$schema = $1;
$table = $2;
print "Creat ing $schema.$table\n";
unless (‐e $schema or mkdir $schem a) {
die "Unable to create dir for sche ma $schema";
}

print SCHEMAFILE "CREATE DATABASE IF NOT EXISTS $schema;\n";
print SCHEMAFILE "USE $schema;\n";
print SCHEMAFILE "$origline";
open (TABLEFILE, '>', "$schem a/$table.sql") or die "Can not write to $schema/$table.sql";
print TABLEF ILE "CREATE TABLE $table (\n";
} 

else {

s/ENGINE=(.*?)[[:space:]].*/ENGINE=;/;
s/`PRIMARY`//;
s/^#.*$//;
s/^WARNING.*$//;
$origline =~ s/(.*ENGINE.*$)/;/;
$origline =~ s/^#.*$//;
$origline =~ s/^WARNING.*$//;
print SCHEMAFILE "$origline" if (!/^\s*$/);
print TABLEFILE "$_\n" if (!/^\s*$/);
}
}

 

 

尽管undrop 可用令人高兴 , 但遇到必须使用它的情况是非常糟糕的。

 

当数据库损坏时,它不能保证任何数据能被恢复。避免陷入这种情况的方法就是使用MySQL Enterprise Backup来定期创建可用的备份,以及至少一个复制slave。关心数据安全的聪明管理员会在远程创建一个复制slave,将服务器的定期备份作为灾难恢复的准备。

 

 

MySQL在MyISAM表中DML生成: “ERROR 144 (HY000): Table ???? is marked as crashed and last (automatic?) repair failed”

适用于:

MySQL服务器版本5.0及以上

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

 

症状

MyISAM表使用DML (inserts, deletes, selects,),以下错误可能发生:

 

101001 14:57:57 [ERROR] ./bin/mysqld: Table './test/t2' 
is marked as crashed and last (automatic?) repair failed

 

 

原因

 

Bug 11764345 –SHOW TABLE STATUS + SMALL MYISAM_SORT_BUFFER_SIZE IN REPAIR, TABLE CRASHE

当小的myisam_sort_buffer_sizerepair by sort发生,且有人运行 ‘show table status’ 或引用表selects from information_schema tables,错误在日志中出现。

check table在运行时,表不显示损坏。

 

解决方案

变通方案

 

1. 在错误表中运行REPAIR TABLE来修复表

2. 增加变量myisam_sort_buffer_size的值来防止bug的发生

 

永久解决方案

 

参考 Bug 11764345。要监控问题,按照Doc

ID 1298390.1 How to Monitor a Code or Enhancement Request (ER) Bug from My Oracle Support 的指导。

参考

BUG:11764345 SHOW TABLE STATUS + SMALL MYISAM_SORT_BUFFER_SIZE IN REPAIR, TABLE CRASHE

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

https://dev.mysql.com/doc/en/serversystemvariables.html#sysvar_myisam_sort_buffer_size

NOTE:1023264.1 What can Cause Corrupted MyISAM Tables in MySQL Server?

沪ICP备14014813号-2

沪公网安备 31010802001379号