mysql page header_由InnoDB: Space id in fsp header ,but in the page header 展开的思考

首先说明我是做ORACLE的,但是工作需要,并且加上兴趣,现在正在学习INNODB。如果有不对的结论大家一起讨论,在这篇文章中修改了块的字节,没有出现问题,而ORACLE却是不能随意修改的,因为他有自己的一套算法来计算CHECKSUM。但是几个小工具可以有助大家学习和研究!

谢谢!

今天启动MYSQL的时候发现如下问题:

2015-12-14 20:51:59 2098 [ERROR] InnoDB: Space id in fsp header 131225,but in the page header 65

2015-12-14 20:51:59 2098 [ERROR] InnoDB: inconsistent data in space header in tablespace ./test/oneblock.ibd (table test/oneblock)

innodb的存储包含

tablespace--segment--extent--block(pages)

而tablespace有一个space id 及用于描述表空间的唯一编号,ibdata的space id为0,这个ibdata为,

SYSTEM SPACE,其中会包含很多普通SPACE_ID 不包含的数据段,或者说数据块,如回滚段。

如果开启了innodb_file_per_table,每个innodb 表文件都有space id,其中文件包含了表的数据和索引数据。

而普通的space 包含的信息较少一些

我们这里主要分析这里也只要分析普通的space,也就是innodb_file_per_table建立的ibd文件。

使用工具(自己写的工具):

[root@hadoop1 test]# mysqlblock c1.ibd -t

***************************************************

USEAGE: mysqlblock datafile -t/-d

This small tool used in study and test database,not

uesd on online database!

This tool is used to find how many blocks and types

in specified datafile,Exp:how many undo block in d

ata file!

QQ:22389860

***************************************************

-t Only Total blocks types in ibdata!

-d Blocks types detail  in ibdata!

***************************************************

FILE SIZE IS : 10485760

Total Block Status    :

Total  block                   :   640,Total size is: 10.000000 MB

Total undo block               :     0,Total size is: 0.000000 MB

Total index node block         :     1,Total size is: 0.015625 MB

Total insert buffer free blocks:     0,Total size is: 0.000000 MB

Total data(leaf node) block    :   113,Total size is: 1.765625 MB

Total new allocate blocks      :   524,Total size is: 8.187500 MB

Total insert buf bitmap blocks :     1,Total size is: 0.015625 MB

Total system blocks            :     0,Total size is: 0.000000 MB

Total transaction system blocks:     0,Total size is: 0.000000 MB

Total file space header blocks :     1,Total size is: 0.015625 MB

Total extrenl disc blocks      :     0,Total size is: 0.000000 MB

Total LOB blocks               :     0,Total size is: 0.000000 MB

Total Unkown blocks            :     0,Total size is: 0.000000 MB

这里我们可以清晰的看到每种块的数量,其中注意一个特殊的块

Total file space header blocks及FSP_HDR,这个块是每个space 必须的,

即使SYSTEM SPACE也包含,他总是SPACE的第一个块。

而每个块同样包含了file header.

Space id in fsp header 131225,but in the page header 65

这里的fsp header就是 file space header ,及第一个块的后38到150字节,

而 page header这里实际上是file header 及 FIL header,这个是块固有的。

这里有点绕一个是file header(每个块固有的前38字节)

一个是file space header(space的第一个块的38-150字节)

file  header(FIL header)

包含如下0-37字节

checksum(4) 0-3

offset(4)   4-7

previous page(4) 8-11

next page(4)     12-15

LSN for last page modification(8) 16-23

page type (2)      24-25

FLUSH LSN(8)       26-33

SPACE ID(4)        34-37

其中的每个值的意思有些是自解释的,而有些需要更深入的研究,但是一个块是一个双向指针的节点可以肯定。

并且记录每个块的LSN记录,应该用于块恢复。这部分是每个块都一样的。而这里SPCAE ID在

page header 中说明每个块中都会有个这个值。记录的就是SPACE_ID不用过多解释

接下来我们来看file space header 特有的

38-150字节:file space header(FSP HEADER)

SPACE_ID (4)

unused(4)

highest page number in file(size)(4)

highest page number initialized (free limit)(4)

flags(4)

number of pages uesd in "free_frag" list(4)

list base node for "free" list(16)

list base node for "free_frag" list(16)

list base node for "full_frag" list(16)

nex unused segment id(8)

list base node for "full_nodes" list(16)

list base node for "free_nodes" list(16)

其中很多值还需要深入的研究 但是我们发现在38-41字节就包含了SPACE_ID。

那么我们就找到了

Space id in fsp header 131225,but in the page header 65

中的 fsp header 来自哪里 ,他来自FSP HEADER及ibd 文件的第一个块的第38-41字节

而page header 65,来自每个块的第34-37字节。

既然如此我们可以进行测试模拟这种现象,我们手动修改这4个字节。使用我自己写的工具,由于LINUX下没找到合适工具干脆自己写了两个。

bctool和bcview

bctool 用于修改

bcview 用于查看

主要测试方式

1、修改FSP HEADER的38-41字节查看MYSQL INNODB 报错,然后修改回去后是否能够顺利启动

2、修改第一个块file space header的34-37字节 查看看MYSQL INNODB 报错,然后修改回去后是否能够顺利启动

3、修改任意一个块的file space header的34-37字节 查看看MYSQL INNODB 报错,然后修改回去后是否能够顺利启动

我们依然使用test数据库下的c1 表其innodb 数据文件为c1.ibd

一、修改FSP HEADER的38-41字节查看MYSQL INNODB 报错,然后修改回去后是否能够顺利启动

通过bcview查看块的34-37字节

[root@hadoop1 test]# bcview c1.ibd 16 34 4|more

******************************************************************

This Tool Is Uesed For Find The Data In Binary format(Hexadecimal)

Usage:./bcview file blocksize offset cnt-bytes!

file: Is Your File Will To Find Data!

blocksize: Is N kb Block.Eg: 8 Is 8 Kb Blocksize(Oracle)!

Eg: 16 Is 16 Kb Blocksize(Innodb)!

offset:Is Every Block Offset Your Want Start!

cnt-bytes:Is After Offset,How Bytes Your Want Gets!

Edtor QQ:22389860!

Used gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

******************************************************************

----Current file size is :10.000000 Mb

----Current use set blockszie is 16 Kb

current block:00000000--Offset:00034--cnt bytes:04--data is:00000048

current block:00000001--Offset:00034--cnt bytes:04--data is:00000048

current block:00000002--Offset:00034--cnt bytes:04--data is:00000048

current block:00000003--Offset:00034--cnt bytes:04--data is:00000048

current block:00000004--Offset:00034--cnt bytes:04--data is:00000048

current block:00000005--Offset:00034--cnt bytes:04--data is:00000048

current block:00000006--Offset:00034--cnt bytes:04--data is:00000048

current block:00000007--Offset:00034--cnt bytes:04--data is:00000048

current block:00000008--Offset:00034--cnt bytes:04--data is:00000048

current block:00000009--Offset:00034--cnt bytes:04--data is:00000048

current block:00000010--Offset:00034--cnt bytes:04--data is:00000048

.......

当然后面还有很多块,但是这里bcview c1.ibd 16 34 4 就是16KB大小34字节开始,一共4个字节输出。

我们发现全是00000048,因为每个space_id在page header 都会记录,

那么他的space id 就是0X48 10进制就是72,我们在MYSQL中验证一下:

mysql> select * from INNODB_SYS_TABLESPACES  where space=72;

+-------+---------+------+-------------+----------------------+-----------+---------------+

| SPACE | NAME    | FLAG | FILE_FORMAT | ROW_FORMAT           | PAGE_SIZE | ZIP_PAGE_SIZE |

+-------+---------+------+-------------+----------------------+-----------+---------------+

|    72 | test/c1 |    0 | Antelope    | Compact or Redundant |     16384 |             0 |

+-------+---------+------+-------------+----------------------+-----------+---------------+

1 row in set (0.01 sec)

可以看到没有问题。

那么接下我们来看38到41字节,为了更好的说明我使用 mysqlblock c1.ibd -d|more的d选项查看详细块信息

并且使用bcview c1.ibd 16 38 4|more

current block:00000000--Offset:00038--cnt bytes:04--data is:00000048

current block:00000001--Offset:00038--cnt bytes:04--data is:00000000

current block:00000002--Offset:00038--cnt bytes:04--data is:ffffffff

current block:00000003--Offset:00038--cnt bytes:04--data is:000601c8

current block:00000004--Offset:00038--cnt bytes:04--data is:00343b26

current block:00000005--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000006--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000007--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000008--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000009--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000010--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000011--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000012--Offset:00038--cnt bytes:04--data is:00663b26

current block:00000013--Offset:00038--cnt bytes:04--data is:00663b26

current read blocks is : 0 --This Block is file space header blocks!

current read blocks is : 1 --This Block is insert buffer bitmap  blocks!

current read blocks is : 2 --This Block is index node blocks!

current read blocks is : 3 --This Block is data blocks(Tree leaf node)!

current read blocks is : 4 --This Block is data blocks(Tree leaf node)!

current read blocks is : 5 --This Block is data blocks(Tree leaf node)!

current read blocks is : 6 --This Block is data blocks(Tree leaf node)!

current read blocks is : 7 --This Block is data blocks(Tree leaf node)!

current read blocks is : 8 --This Block is data blocks(Tree leaf node)!

current read blocks is : 9 --This Block is data blocks(Tree leaf node)!

current read blocks is : 10 --This Block is data blocks(Tree leaf node)!

current read blocks is : 11 --This Block is data blocks(Tree leaf node)!

current read blocks is : 12 --This Block is data blocks(Tree leaf node)!

current read blocks is : 13 --This Block is data blocks(Tree leaf node)!

current read blocks is : 14 --This Block is data blocks(Tree leaf node)!

现在我们清楚的看到了38-41这4个字节只有fsp_header块是00000048就是space_id

其他类型的块并不是。

接下来我们使用bctool进行修改FSP HEADER的38-41字节。还是关闭数据库后进行更改

为了安全首先备份一下

[root@hadoop1 test]# cp c1.ibd c1.ibdbak

然后:

[root@hadoop1 test]# bctool c1.ibd 0 38 000000ee

******************************************************************

This tool is uesed to check data ues binary format,no Big-Endian

or Little-Endian diff,this tool is base one byte on byte to change

!block is 16k.if want change other block eg:8k! please set blocks

0 and offset blocks*8192+offset!

usage:./bctool yfile blocks offset yourdata(XX)!

Warings:backup file frist!!!!!!!!!

Editor QQ:22389860

Ues gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

******************************************************************

0-0-0-ee

再次查看:

bcview c1.ibd 16 38 4|more

current block:00000000--Offset:00038--cnt bytes:04--data is:000000ee

current block:00000001--Offset:00038--cnt bytes:04--data is:00000000

current block:00000002--Offset:00038--cnt bytes:04--data is:ffffffff

current block:00000003--Offset:00038--cnt bytes:04--data is:000601c8

已经被我更改为ee了

然后启动MYSQL,虽然数据库起来了但是

mysql> select count(*) from c1;

ERROR 2013 (HY000): Lost connection to MySQL server during query

数据库立即宕机

[root@hadoop1 test]# service mysqldefault start

Starting MySQL..The server quit without updating PID file (/mysql/data/hadoop1.pid).[FAILED]

再次启动已经无用,查看日志:

2015-12-26 01:05:38 5074 [ERROR] InnoDB: Space id in fsp header 238,but in the page header 72

2015-12-26 01:05:38 5074 [ERROR] InnoDB: checksum mismatch in tablespace ./test/c1.ibd (table test/c1)

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size:1024 Pages to analyze:64

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size: 1024, Possible space_id count:0

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size:2048 Pages to analyze:64

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size: 2048, Possible space_id count:0

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size:4096 Pages to analyze:64

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size: 4096, Possible space_id count:0

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size:8192 Pages to analyze:64

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size: 8192, Possible space_id count:0

2015-12-26 01:05:38 5074 [Note] InnoDB: Page size:16384 Pages to analyze:64

.....

我们发现错误重现238 换算为16进制就是我们修改的0XEE.

这种情况也许innodb_force_recovery > 0 有用,但是我没有试验。

接着我来将fsp header 的38-41字节改回0X48,然后启动。

[root@hadoop1 test]# bctool c1.ibd 0 38 00000048

再次查看

[root@hadoop1 test]# bcview c1.ibd 16 38 4|more

current block:00000000--Offset:00038--cnt bytes:04--data is:00000048

启动:

[root@hadoop1 test]# service mysqldefault start

Starting MySQL...[  OK  ]

启动完成。

mysql> select count(*) from c1;

+----------+

| count(*) |

+----------+

|     8192 |

+----------+

1 row in set (0.01 sec)

查询没有问题。

二、修改第一个块file space header的34-37字节 查看看MYSQL INNODB 报错,然后修改回去后是否能够顺利启动

再次关闭数据,

使用bcview查看

[root@hadoop1 test]# bcview c1.ibd 16 34 4|more

current block:00000000--Offset:00034--cnt bytes:04--data is:00000048

修改:

[root@hadoop1 test]# bctool c1.ibd 0 34 00000099

查看

[root@hadoop1 test]# bcview c1.ibd 16 34 4|more

current block:00000000--Offset:00034--cnt bytes:04--data is:00000099

启动数据库,查看数据

mysql> select count(*) from c1;

ERROR 2013 (HY000): Lost connection to MySQL server during query

查看日志:

2015-12-26 01:17:46 6122 [ERROR] InnoDB: Space id in fsp header 72,but in the page header 153

这里的153就是0X99对比刚才的

2015-12-26 01:05:38 5074 [ERROR] InnoDB: Space id in fsp header 238,but in the page header 72

可以从日志中看出这次是fsp header正常,file header 错误。

那么我们同样修改回来:

[root@hadoop1 test]# bctool c1.ibd 0 34 00000048

查看

current block:00000000--Offset:00034--cnt bytes:04--data is:00000048

已经修改回来,接着启动

mysql> select count(*) from c1;

+----------+

| count(*) |

+----------+

|     8192 |

+----------+

1 row in set (0.01 sec)

没有问题可以查询

三、修改任意一个块的file space header的34-37字节 查看看MYSQL INNODB 报错,然后修改回去后是否能够顺利启动

既然每个数据块的file header都包含了space id,那么我们随意更改一个块的

current read blocks is : 0 --This Block is file space header blocks!

current read blocks is : 1 --This Block is insert buffer bitmap  blocks!

current read blocks is : 2 --This Block is index node blocks!

current read blocks is : 3 --This Block is data blocks(Tree leaf node)!

current read blocks is : 4 --This Block is data blocks(Tree leaf node)!

current read blocks is : 5 --This Block is data blocks(Tree leaf node)!

这里就选择5号块(0开始实际是第6个),这个块为数据块。

具体过程不再给出,给出命令

[root@hadoop1 test]# bctool c1.ibd 5 34 00000088

[root@hadoop1 test]# bcview c1.ibd 16 34 4|more

current block:00000005--Offset:00034--cnt bytes:04--data is:00000088

查看数据没有问题,但是日志有报错

2015-12-26 01:25:58 403be940  InnoDB: Error: space id and page n

5b24fae4cde99750994428c024162093.gif stored in the page

InnoDB: read in are 136:5, should be 72:5!

可以看到innodb 说 5号块的space id是136 就是0X88,应该是72,虽然数据还能跑,这个错误到底

影响多大未知但是我们知道原因,修改回去

关闭数据库:

[root@hadoop1 test]# bctool c1.ibd 0 34 00000048

[root@hadoop1 test]# bcview c1.ibd 16 34 4|more

current block:00000005--Offset:00034--cnt bytes:04--data is:00000048

错误消失

总结:

1、我们可以知道什么是space id,space id 就是表空间的唯一标识

2、我们可以知道什么是FSP HEADER BLOCK 及每个space 文件第一个块,

而FSP HEADER 存放在每一个SPACE文件的第一个块的38-150字节,实际这个块还会存放XDS信息就是EXTENTS的信息这里不

再介绍

3、我们可以知道访问表的时候如果第一个块的FIL HEADER的34-37字节的SPCAE_ID和FSP HEADER的38-41字节对应不上数据库会

立即宕机。

报错:

2015-12-26 01:05:38 5074 [ERROR] InnoDB: Space id in fsp header 238,but in the page header 72

4、我们还知道了如果不是第一个块的FIL HEADER 34-37字节 space id出现问题,日志只会报错,但是不影响使用

报错:

2015-12-26 01:25:58 403be940  InnoDB: Error: space id and page n

5b24fae4cde99750994428c024162093.gif stored in the page

InnoDB: read in are 136:5, should be 72:5!

5、为了完成这个实验,我使用了3个工具,均为自己写的,如果没有这3个工具这个实验无法完成,或者很困难

---mysqlblock :用于查看数据文件中块的类型

***************************************************

USEAGE: mysqlblock datafile -t/-d

This small tool used in study and test database,not

uesd on online database!

This tool is used to find how many blocks and types

in specified datafile,Exp:how many undo block in d

ata file!

QQ:22389860

***************************************************

-t Only Total blocks types in ibdata!

-d Blocks types detail  in ibdata!

***************************************************

USEAGE: mysqlblock datafile -t/-d

---bcview:用于查看块的固定字节输出

******************************************************************

This Tool Is Uesed For Find The Data In Binary format(Hexadecimal)

Usage:./bcview file blocksize offset cnt-bytes!

file: Is Your File Will To Find Data!

blocksize: Is N kb Block.Eg: 8 Is 8 Kb Blocksize(Oracle)!

Eg: 16 Is 16 Kb Blocksize(Innodb)!

offset:Is Every Block Offset Your Want Start!

cnt-bytes:Is After Offset,How Bytes Your Want Gets!

Edtor QQ:22389860!

Used gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

******************************************************************

usage:./bcview file blocksize offset cnt-bytes!

---bctool:用于修改某个块的某个字节的数据(现支持16K)

******************************************************************

This tool is uesed to check data ues binary format,no Big-Endian

or Little-Endian diff,this tool is base one byte on byte to change

!block is 16k.if want change other block eg:8k! please set blocks

0 and offset blocks*8192+offset!

usage:./bctool yfile blocks offset yourdata(XX)!

Warings:backup file frist!!!!!!!!!

Editor QQ:22389860

Ues gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

******************************************************************

usage:./bctool file block offset yourdata(XX)!

当然bctool和bcview 可以修改和查看任何文件,不光是INNODB BLOCK。

本三个工具均上传到了百度云盘

http://pan.baidu.com/s/1num76RJ

LINUX下使用,注意给予执行权限

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值