innodb实例损坏情况下恢复数据及相关工具的开发

作者介绍:谢浩,现任职于云和恩墨(北京)信息技术有限公司,具有多年oracle数据库企业级运维经验,擅长结合业务、硬件系统制定各种项目方案,具有丰富mysql相关的工作经验。

假设你在使用MySQL中的InnoDB驱动,由于遇到了驱动程序错误,内核错误,电源故障或某些罕见的MySQL错误,而在InnoDB ibdata1文件损坏,实例不能启动。你该怎么办呢?

案例描述

某门户mysql innodb数据库实例损坏,数据库服务无法启动,使用文件系统上的数据库frm及bid文件恢复数据库内的业务数据。

相关知识点

Mysql innodb数据库将实例的基础字典信息存储在data目录下的ibdata1文件以及mysql实例中,可以将其理解为oracle数据库的system表空间以及数据字典,如果损坏数据实例将无法启动。

Mysql innodb引擎打开innodb_file_per_table后,每个表都会单独存放在一个表空间中,包含了tablename.frm和tablename.ibd文件,其中.frm后缀的文件记录表的结构信息,.ibd后缀的文件记录表的数据。在mysql实例无法启动的情况下使用这两个文件可以恢复数据库内的业务数据。

恢复过程中需要获得每个数据表的字段个数和每个表空间文件的table id(5.5版本),其中字段个数记录在frm文件中。

1、分析frm文件格式获得表字段个数

分析mysql源代码中位于table.cc文件中的open_binary_frm函数获得frm文件中记录字段数的位置:

open_binary_frm函数中位于table.cc文件第766行调用了get_from_pos函数,该函数负责计算frm文件内字段信息集合的起始偏移量:

该函数中首先seek到file head+64,然后读取“(head+4的dword)+(head+8的dword)*4”的数据,最后pos=buf+length,这里之所以不直接读取,是因为读到的位置可能不是双数,因此要从第64字节读取后整个buffer进行小头转换再读取最后的目标pos。

对该段代码进行解释,pos的值就是frm文件从第64字节开始,跳过head+4的dword内记录的字节数后读取(head+8的dword)*4个字节内的值。

举例说明:

第4、5字节为03 00,小头转换后为0003,第8、9字节为01 00,转换后为00 01。按上述算法,从第64字节开始读取3+1*4=7个字节,读取后进行小头转换为“2F 2F 00 00 00 20 00”,最后截取第3到结束为“00 00 20 00”等于10进制的8192,这就是frm文件中字段信息的保存起始偏移量。

再次观察open_binary_frm函数,我们需要的表字段数实际上是记录在字段信息的保存起始偏移量+258位置:

在本例中为8192+258=8450=0x2102的位置

04 00小头转换后为0004,表示该表有4个字段。

至此字段数量信息读取完成。

2、获得表对应的space_id

space_id 可以从ibd文件的第38~39字节、42~43字节两处处获得:

两处完全一样,读取其中一个即可。

手工恢复流程

1、模拟数据库字典信息损坏

将数据库data目录下ibdata文件改名为ibdata.1,此时启动数据库服务失败,err日志中出现以下信息:

2、在辅助实例生成数据表ddl语句

在目标库建立与原库名称相同字段数量相同的表(字段名任意),将原库frm文件复制到辅助实例,并设置innodb_force_recovery==6

3、在目标实例创建空表并分离数据

执行上述create table命令,对齐space_id,并执行表空间分离

4、使用原frm、ibd文件覆盖目标库同名文件

停止目标实例服务,将需要恢复的原数据库内的frm、ibd文件覆盖目标实例的同名文件,并import表空间:

恢复流程整理及相关工具开发

恢复过程中重要点如下:

1、批量快速获得表的字段数

生产系统包含大量数据表,人工逐个分析frm文件速度慢,需要开发工具批量自动获取。

2、批量获得space_id并生成对齐语句

Space_id的对齐是指在目标库某个表在全实例被创建的顺位必须相同(5.5版本,5.6及以上版本不需要),比如某个表在原库的space_id=100,在目标库上必须先建立99个空表,再建立这个表就能使该表的space_id相同。核心逻辑如下:

3、原地恢复

生产系统数据表数量多、体积大,全部复制到目标实例data目录下时间太长,因此需要将目标实例的data目录指向原实例,同时需要批量将原实例data目录下的所有文件改名。部分代码如下:

流程梳理

1、建立辅助实例、目标实例(人工)

2、批量获得原库表字段个数、space_id(工具)

3、辅助实例批量生成create table语句并自动生成space_id对齐(建空表)语句(工具)

4、目标库文件改名、目标库使用生成的createtable语句建立空表(工具)

5、目标库覆盖(工具)

原文发布于微信公众号 - 数据和云(OraNews)

原文发表时间:2018-02-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Play & Scala 技术分享

HTTP Cookie的域名和路径匹配

2545
来自专栏JetpropelledSnake

Python入门之logging日志模块以及多进程日志

本篇文章主要对 python logging 的介绍加深理解。更主要是 讨论在多进程环境下如何使用logging 来输出日志, 如何安全地切分日志文件。 1. ...

4157
来自专栏狂码一生

深入PHP FTP类的详解

FTP是一种文件传输协议,它支持两种模式,一种方式叫做Standard (也就是Active,主动方式),一种是 Passive (也就是PASV,被动方式)。...

3598
来自专栏Golang语言社区

使用Beego+Swagger构建更好的API服务

题图 By NewYorker From Twitter 一. 更好的API服务 在你已经在工作中写了很多版本,很多规范的API服务之后,你会发现,后端服务很多...

37911
来自专栏北京马哥教育

Python爬虫基础知识:urllib2的使用技巧

糖豆贴心提醒,本文阅读时间6分钟 前面说到了urllib2的简单入门,下面整理了一部分urllib2的使用细节。 1.Proxy 的设置 urllib2 默认...

2615
来自专栏IMWeb前端团队

bigpipe性能优化

本文作者:IMWeb moonye 原文出处:IMWeb社区 未经同意,禁止转载 背景 当前网速越来越快,但是随着网页内容越来越丰富,其实我们打开网页...

21510
来自专栏菩提树下的杨过

基于webmagic的爬虫项目经验小结

大概在1个月前,利用webmagic做了一个爬虫项目,下面是该项目的一些个人心得,贴在这里备份: 一、为什么选择webmagic? 说实话,开源的爬虫框架已经很...

3008
来自专栏小白客

requests库的基本用法

Requests 是使用Python语言编写,基于urllib,采用Apache2 Licensed开源协议的HTTP库。 它比urllib库更加方便,可以节约...

851
来自专栏Jackson0714

30分钟全面解析-图解AJAX原理

26612
来自专栏网络

Nginx 教程(1):基本概念

英文:netguru,翻译:开源中国 www.oschina.net/translate/nginx-tutorial-basics-concepts 简介 嗨...

17510

扫描关注云+社区