MySQL数据库INNODB 表损坏修复处理过程
突然收到MySQL报警【bào jǐng】,从库的【cóng kù de】🙈数据库挂了🎐,一直在不停的【bú tíng de】重启【chóng qǐ】⏰,打开错🚒误日志,发现有张表坏了。innodb表损坏☕不能通【bú néng tōng】🖐过repair table 等修复myisam的命令操作【cāo zuò】🐀。现在记录下解决过程【jué guò chéng】,下次遇📵到就不🐛会这么【huì zhè me】手忙脚乱了【luàn le】。
处理过🏋程【chéng】👪:
一遇到报警之后【hòu】,直接打开错误👱日志,里面的【lǐ miàn de】信息:
InnoDB: Database page corruption on disk or a failed InnoDB: file read of page 30506. InnoDB: You may have to recover from a backup. 130509 20:33:48 InnoDB: Page dump in ascii and hex (16384 bytes): ##很多十【hěn duō shí】六进制的代码【de dài mǎ】 …… …… InnoDB: End of page dump 130509 20:37:34 InnoDB: Page checksum 1958578898, prior-to-4.0.14-form checksum 3765017239 InnoDB: stored checksum 3904709694, prior-to-4.0.14-form stored checksum 3765017239 InnoDB: Page lsn 5 614270220, low 4 bytes of lsn at page end 614270220 InnoDB: Page number (if stored to page already) 30506, InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 19 InnoDB: Page may be an index page where index id is 54 InnoDB: (index "PRIMARY" of table "maitem"."email_status") InnoDB: Database page corruption on disk or a failed InnoDB: file read of page 30506. InnoDB: You may have to recover from a backup. InnoDB: It is also possible that your operating InnoDB: system has corrupted its own file cache InnoDB: and rebooting your computer removes the InnoDB: error. InnoDB: If the corrupt page is an index page InnoDB: you can also try to fix the corruption InnoDB: by dumping, dropping, and reimporting InnoDB: the corrupt table. You can use CHECK InnoDB: TABLE to scan your table for corruption. InnoDB: See also http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html InnoDB: about forcing recovery. InnoDB: A new raw disk partition was initialized or InnoDB: innodb_force_recovery is on: we do not allow InnoDB: database modifications by the user. Shut down InnoDB: mysqld and edit my.cnf so that newraw is replaced InnoDB: with raw, and innodb_force_... is removed. 130509 20:39:35 [Warning] Invalid (old?) table or database name '#sql2-19c4-5'
从错误【cóng cuò wù】日志里面很清楚的知【chǔ de zhī】道哪里出现了【chū xiàn le】问题🎷,该怎么处理👽。这时候🤪数据库🕡隔几【gé jǐ】s就重启【jiù chóng qǐ】,所以差🐳不多可以说你是访问✏不了数🕜据库的【de】。所以马【suǒ yǐ mǎ】上想到🚲要修复🗣innodb表了🥜。
以前在【yǐ qián zài】Performance的【de】blog上看过类似文章。
当时想到的是【dào de shì】在修复📇之前保证数据【zhèng shù jù】库正常【kù zhèng cháng】👧,不是这么异常的无休【de wú xiū】🈚止的重启。所以就🌄修改了配置文件的一【jiàn de yī】个参数🎄:innodb_force_recovery
innodb_force_recovery影响整【yǐng xiǎng zhěng】个【gè】✋InnoDB存储引擎的恢复状况【fù zhuàng kuàng】。默认为0,表😘示当需要恢复【yào huī fù】时执行【shí zhí háng】所有的 innodb_force_recovery可以设置为【shè zhì wéi】🍰1-6,大的数字包含前面所有数字【yǒu shù zì】🦊的影响【de yǐng xiǎng】。当设置【dāng shè zhì】参数值大于🔏0后🕣,可以对📹表😘进行select,create,drop操作【cāo zuò】,但【dàn】insert,update或者🌔delete这类操作【cāo zuò】是不允许的。 1(SRV_FORCE_IGNORE_CORRUPT):忽略检🦎查到的🚗corrupt页【yè】🎺。 2(SRV_FORCE_NO_BACKGROUND):阻止主🚵线程的🔊运行,如主线🧑程需要执行full purge操作【cāo zuò】,会导致🎟crash。 3(SRV_FORCE_NO_TRX_UNDO):不执行【bú zhí háng】🕊事务回🍠滚操作【gǔn cāo zuò】。 4(SRV_FORCE_NO_IBUF_MERGE):不执行【bú zhí háng】🕊插入缓冲的合【chōng de hé】并操作【cāo zuò】。 5(SRV_FORCE_NO_UNDO_LOG_SCAN):不查看【bú chá kàn】重做日📖志【zhì】,InnoDB存储引擎会将未提交【wèi tí jiāo】🗯的事务视为已🚂提交【tí jiāo】⏭。 6(SRV_FORCE_NO_LOG_REDO):不执行【bú zhí háng】🕊前滚的操作【cāo zuò】。
因为错误日志【zhì】里面提示出现🏓了坏页【le huài yè】🌬,导致数⚽据库崩【jù kù bēng】溃,所以这里把innodb_force_recovery 设置为【shè zhì wéi】🍰1,忽略检🦎查到的🚗坏页【huài yè】🍗。重启数据库之后🕣,正常了【zhèng cháng le】,没有出现上面【xiàn shàng miàn】的错误【de cuò wù】信息🆙。找到错误信息【wù xìn xī】🆙出现的表😘:
(index "PRIMARY" of table "maitem"."email_status")
数据页【shù jù yè】面的主✏键索引🥒(clustered key index)被损坏。这种情【zhè zhǒng qíng】况和数据的二级索引💊(secondary indexes)被损坏相比要【xiàng bǐ yào】🐇糟很多🚹,因为后者可以通过使用【yòng】🎧OPTIMIZE TABLE命令来【mìng lìng lái】修复,但这和【dàn zhè hé】💙更难以恢复的🚒表格目录(table dictionary)被破坏【bèi pò huài】的情况来说要好一些【hǎo yī xiē】。
操作步【cāo zuò bù】骤【zhòu】:
因为被破坏的⏫地方只在索引的部分【de bù fèn】,所以当🎅使用🍟innodb_force_recovery = 1运行InnoDB时【shí】,操作如🛫下:
执行check,repair table 都无效 alter table email_status engine =myisam; #也报错🌶了📪,因为模【yīn wéi mó】式是【shì shì】innodb_force_recovery =1。 ERROR 1025 (HY000): Error on rename of '...' to '....' (errno: -1)
建立一【jiàn lì yī】张表【zhāng biǎo】🍍: create table email_status_bak #和原表结构一【jié gòu yī】样,只是把👑INNODB改成了【gǎi chéng le】📪MYISAM。 把数据导进去 insert into email_status_bak select * from email_status; 删除掉【shān chú diào】🍚原表: drop table email_status; 注释掉【zhù shì diào】🕹innodb_force_recovery 之后,重启。 重命名💽: rename table edm_email_status_bak to email_status; 最后该【zuì hòu gāi】回存储引擎【yǐn qíng】 alter table edm_email_status engine = innodb
总结【zǒng jié】🚽:
这里的一个重要知识🐸点就是【diǎn jiù shì】 对👁 innodb_force_recovery 参数的【cān shù de】理解了📪,要是遇🎒到数据损坏🐦甚至是其他的损坏🐦。可能上面的方【miàn de fāng】法不行了📪,需要尝试另一个方法:insert into tb select * from ta limit X;甚至是dump出去【chū qù】🔤,再🔘load回来。
关键词:MySQL,数据库
阅读本文后您有什么感想? 已有 人给出评价!
- 78
- 33
- 25
- 10
- 6
- 35