http://www.mysqlperformanceblog.com/2008/07/04/recovering-innodb-table-corruption/
http://cgaolei.javaeye.com/blog/412157
今天早上照样想去查一下videos表看看有多少数据跑出来了,得到还是该句提示(此文3对“【】”里的内容为sql代码):
【【【
mysql> select count(*) from videos where title is not null;
ERROR 2013 (HY000): Lost connection to MySQL server during query
】】】
去Google了一把,找到了javaeye上的《修复损坏的InnoDB表格》这篇文章,看了后跟自己遇到的情况一模一样,然后仔细看完,并按照它的操作慢慢进行下来,虽然遇到几个有疑问的地方,但是我的数据确实大部分恢复回来了(丢失了287条数据)。
描述总结一下今天遇到问题的情况:
1. 一些基本情况:
a). host: 192.168.1.243
b). OS: Linux version 2.6.18-4-686 (Debian 2.6.18.dfsg.1-12) ([email protected]) (gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)) #1 SMP Mon Mar 26 17:17:36 UTC 2007
c). mysql.version: 5.0.32-Debian_7etch5-log
d). database: video_tracker
e). table: videos
f). total.count(*): 133871
g). repaired.count(*): 133584
h). lost.count(*): 287
2. 修复过程中
a). 修改/etc/mysql/my.cnf,在[mysqld]配置下增加innodb_force_recovery = 1,但是check table时得到的提示还是原来的2013错误(或许上文中是因为手动损坏的原因,后来通过译者的解释,是因为表的损坏程度比较严重。),未修改前提示和文中的表现一样
b). 然后复制videos表的表结构到新的videos2表,但是videos2表的存储方式使用MyISAM:
【【【
mysql> show create table videos;
…
mysql> create table videos2 (
…
#根据videos表字段定义
…
) ENGINE=MyISAM DEFAULT CHARSET=utf8
】】】
再执行下面的语句:
【【【
mysql> INSERT INTO videos2 SELECT * FROM videos;
ERROR 2013 (HY000): Lost connection TO MySQL server during query
】】】
得到的提示信息与文中表现一样,并且成功复制出了前面的69373条数据。
同时通过文章中提及的方法找出被损坏数据所处的大概位置
【【【
mysql> INSERT IGNORE INTO videos2 SELECT * FROM videos LIMIT 10;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
】】】
再通过下面的语句找到准确的位置——id>=69685 and id<=69397,处于这段ID之间的数据均已经损坏。
【【【
mysql> SELECT max(id) FROM videos2;
+---------+
| max(id) |
+---------+
| 69373 |
+---------+
1 row IN SET (0.21 sec)
mysql> INSERT IGNORE INTO videos2 SELECT * FROM test WHERE id>69397;
ERROR 2013 (HY000): Lost connection TO MySQL server during query
mysql> INSERT IGNORE INTO videos2 SELECT * FROM test WHERE id>69686;
Query OK, 64325 rows affected (2.37sec)
Records: 64325 Duplicates: 0 Warnings: 0
】】】
c). 成功备份出未被损坏的数据,然后drop原来的videos表,然后| alter table videos2 rename to videos; |,再把它的数据存储方式改回InnoDB:
【【【
mysql> alter table videos type InnoDB;
ERROR 1030 (HY000): Got error -1 from storage engine
】】】
得到这个提示后,这篇文章中并未提及,又去网上Google了,找出,原因就是因为原来修改了/etc/mysql/my.cnf配置文件(增加了innodb_force_recovery = 1配置),删除该配置项后,重启mysql,修改存储方式成功。 (参考:
http://forums.devshed.com/mysql-help-4/error-1030-hy000-got-error--1-from-storage-engine-291134.html )
3. 总结:
a). mysql配置文件中“innodb_force_recovery = 1”该项设置是用来尝试导出已经被损坏的InnoDB表中数据的,在表损坏程度不严重的情况下,(严重就设置级别高点>1),该选项是把库中的innodb表设置成只读,不能修改状态。可能可以成功导出表中数据。
【【【
1. # 如果你发现InnoDB表空间损坏, 设置此值为一个非零值可能帮助你导出你的表.
2. # 从1开始并且增加此值知道你能够成功的导出表.
3. #innodb_force_recovery=1
】】】(摘自http://promiseforever.com/blog/show-361-1.html)
b). 语句“INSERT IGNORE INTO videos2 SELECT * FROM videos LIMIT 10;”
发现这样的组合可以从另外一个表取几条数据出来到另外一张临时表,再进行进一步的查询,select后面还可以加where,order by的条件,建立临时表进行查询是不是就用到了这个呢?(mysql建立临时表用create temporary table tmp_table,mysql在连接断开的情况下自动会删除该表,这里的语句可能可以用到,不过还有很高深的,慢慢再研究)(mysql refman中“问题和常见错误”A.7.3,MySQL临时表使用方法)
c). 语句“show create table videos;”
查看表结构,复制表结构时可用