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;”
查看錶結構,複製表結構時可用