2018年11月10日星期六

在微信群有位朋友发了个错误,已经做了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包管理 centosyum来安装
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_idfsp 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!


以上就还原了,他的问题,原因其实就是第一个块数据出现损坏

没有评论:

发表评论