在微信群有位朋友发了个错误,已经做了innodb_force_recovery=6.强制恢复
2016-11-02 17:25:54 8480 [ERROR] InnoDB:
Space id in fsp header 19742095,but in the page header 5075
我们开始还原这个原因
我是谷歌了许久也没有找到实用的教程解决这个问题,突然想起今天看了下innodb_struct
我在测试机上用脚本生成一些数据
https://blog.jcole.us/2013/01/03/a-quick-introduction-to-innodb-ruby/

在进行这些操作时需要安装一个工具https://github.com/jeremycole/innodb_ruby
环境Ubuntu 16.04.1 LTS
apt-get install rubygems 安装ruby包管理 centos用yum来安装
gem install innodb_ruby
从错误内容我们可以找到原代码fsp0fsp.cc
/**********************************************************************//**
Reads the space id from the first page of a
tablespace.
@return space id, ULINT UNDEFINED if error
*/
ulint
fsp_header_get_space_id(
/*====================*/
const
page_t* page) /*!< in: first page of a tablespace */
{
ulint fsp_id;
ulint id;
fsp_id
= mach_read_from_4(FSP_HEADER_OFFSET + page + FSP_SPACE_ID);
id
= mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
DBUG_EXECUTE_IF("fsp_header_get_space_id_failure",
id
= ULINT_UNDEFINED;);
if
(id != fsp_id) {
ib::error()
<< "Space ID in fsp header is " << fsp_id
<<
", but in the page header it is " << id << ".";
return(ULINT_UNDEFINED);
}
return(id);
}
从上面信息可以看到是由于fsp_id!=id引起了错误,还可以得到信息这两个信息都在表空间第一个页(block,16K)上
Reads the space id from the first page of a tablespace.
fsp_id实际是FSP Header中的 Space ID
(4),只有第一个页有
id 实际是FIL Header 中的Space ID (4)这个是每个页都有
所以第一个页即有fsp_id 又有
id,两者都表示此空间id
以下IBD文件结构可以看到组成ibd文件结构,这个问题引起的原因就是第一个页中两个space_id值不等

查看表空间文件结构
root@ubuntu:/var/lib/mysql/test# ls
db.opt
t.frm t.ibd
root@ubuntu:/var/lib/mysql/test#
innodb_space -f t.ibd space-page-type-regions
start
end count type
0
0 1 FSP_HDR FSP_HDR: Filespace Header / Extent
Descriptor
1
1 1 IBUF_BITMAP IBUF_BITMAP: Insert Buffer Bookkeeping
2
2 1 INODE INODE: Index Node Information
3
37 35 INDEX INDEX: Root page of first index
38
63 26 FREE (ALLOCATED) ALLOCATED: Reserved but unused page
64
2155 2092 INDEX
2156
2175 20 FREE (ALLOCATED)
2176
2176 1 INDEX
2177
2239 63 FREE (ALLOCATED)
2240
2240 1 INDEX
2241
2303 63 FREE (ALLOCATED)
2304
2304 1 INDEX
2305
2367 63 FREE (ALLOCATED)
2368
2368 1 INDEX
2369
2431 63 FREE (ALLOCATED)
2432
2432 1 INDEX
2433
2687 255 FREE (ALLOCATED)
由于是第一个页引起的故障,那就查看第一个页中有什么内容,第一个页是从0号开始的
root@ubuntu:/var/lib/mysql/test1#
innodb_space -f t.ibd -p 0 page-dump | head -n40
#<Innodb::Page::FspHdrXdes:0x00000000af07a8>:
fil header:
{:checksum=>42864312,
:offset=>0,
:prev=>0,
:next=>0,
:lsn=>113959496,
:type=>:FSP_HDR,
:flush_lsn=>0,
:space_id=>27}
fil trailer:
{:checksum=>42864312,
:lsn_low32=>113959496}
fsp header:
{:space_id=>27,
:unused=>0,
:size=>768,
:free_limit=>384,
:flags=>
{:system_page_size=>16384,
:compressed=>true,
:page_size=>16384,
:post_antelope=>true,
:atomic_blobs=>true,
:data_directory=>false,
:value=>33},
:frag_n_used=>36,
:free=>从这我们可以看到
从上面信息我们可以看到fil header中的space_id与fsp header中的space_id是相等的
怎么才能使他们不相等呢,那我们得看fil header和 fsp header的结构及文件所占的位置

从这里可以看到
fil Header的结构,最重要可以看到FIL Header 中space_id的位置34-37

从这里可以看到FSP Header 的结构,最重要可以看到FSP Header 中space_id的位置38-41
通过hexdump命令来查看下
root@ubuntu:/var/lib/mysql/test1# hexdump
-C -v t.ibd | head -n5
00000000
02 8e 0e b8 00 00 00 00 00 00 00
00 00 00 00 00 |................| 0-15
00000010
00 00 00 00 06 ca e2 48 00 08 00
00 00 00 00 00 |.......H........| 16-31
00000020
00 00 00 00 00 1b 00 00 00 1b 00
00 00 00 00 00 |................| 32-47
00000030
03 00 00 00 01 80 00 00 00 21 00
00 00 24 00 00 |.........!...$..|
00000040
00 01 00 00 00 00 01 66 00 00 00
00 01 66 00 00 |.......f.....f..|
通个上面我们找到FIL Header 中space_id(34-37) 00 00 00 1b
= 27 由上面图可知占四个字节
FIL Header 中space_id
(38-41) 00 00 00 1b = 27
那要产生如此故障(2016-11-02 17:25:54 8480 [ERROR] InnoDB: Space id in fsp header
19742095,but in the page header 5075)我们可以通过修改ibd的第一个页的中的一个space_id使他们不相同
使用hexedit t.ibd 修改其中一个
root@ubuntu:/var/lib/mysql/test1# hexdump
-C -v t.ibd | head -n5
00000000
02 8e 0e b8 00 00 00 00 00 00 00
00 00 00 00 00 |................|
00000010
00 00 00 00 06 ca e2 48 00 08 00
00 00 00 00 00 |.......H........|
00000020
00 00 00 00 00 1a 00 00 00 1b 00
00 00 00 00 00 |................|
00000030
03 00 00 00 01 80 00 00 00 21 00
00 00 24 00 00 |.........!...$..|
00000040
00 01 00 00 00 00 01 66 00 00 00
00 01 66 00 00 |.......f.....f..|
通个上面我们找到FIL Header 中space_id(34-37) 00 00 00 1a
= 26
FIL Header 中space_id
(38-41) 00 00 00 1b = 27
root@ubuntu:/var/lib/mysql/test1#
innodb_space -f t.ibd -p 0 page-dump | head -n40
/var/lib/gems/2.3.0/gems/innodb_ruby-0.9.15/lib/innodb/space.rb:121:in
`raw_fsp_header_flags': Something is very wrong; FIL and FSP header Space IDs
don't match: FIL is 26 but FSP is 27 (RuntimeError)
这时我重启service mysql restart,不能启动,发现如下错误
2016-11-02T12:55:14.931152Z 0 [ERROR]
InnoDB: Space ID in fsp header is 26, but in the page header it is 27.
2016-11-02T12:55:14.931163Z 0 [ERROR]
[FATAL] InnoDB: Tablespace id is 27 in the data dictionary but in file
./test1/t.ibd it is 18446744073709551615!
以上就还原了,他的问题,原因其实就是第一个块数据出现损坏