C版本的Mysql存储块格式读取工具源代码如下:
其中mysql块存储采用大端字节,所以需要做一定的转换,C语言指针强力转换方式如下:
#include <stdio.h>
#include <stdlib.h>
int readpage(unsigned char * page_hdr,int page_off,FILE *fd) {
int ret = -1;
if((ret = fseek(fd,page_off,SEEK_SET)) != 0) { //fseek error may not be caught successfully here
printf("fseek failed\n");
exit(-1);
}
printf("now from our calclation page_off is %d\n",page_off);
if(!(ret = fread(page_hdr,62,1,fd))) {
printf("read page failed! ret is %d\n",ret);
return -1;
}
return 1;
}
int main() {
unsigned char page_hdr_tmp[62];
unsigned char * tmp;
unsigned int page_offset = 0;
unsigned short page_type = 0;
unsigned int tab_space_id = 0;
unsigned short page_level = 0;
int ret = -1;
int page_count = 0;
int filesize = 0;
FILE *fd;
if(!freopen("C:\\MinGW\\bin\\log.txt", "w", stdout)) {
printf("log file created failed!\n");
}
if(!(fd = fopen("C:\\MinGW\\bin\\payment.ibd","rb"))) {
printf("fopen failed!\n");
return -1;
}
if((ret = fseek(fd,0,SEEK_END)) != 0) {
printf("fseek failed\n");
exit(-1);
}
filesize = ftell(fd);
printf("filesize is %d\n",filesize);
while (page_count < filesize/1024/16) {
printf("processing the %d [rd] page\n",page_count);
if(ret = readpage(page_hdr_tmp, page_count*16*1024, fd)) {
page_count++;
} else {
printf("readpage failed!\n");
system("pause");
exit -1;
}
//for page_offset
tmp = (unsigned char *)&page_offset;
tmp[0] = page_hdr_tmp[7];
tmp[1] = page_hdr_tmp[6];
tmp[2] = page_hdr_tmp[5];
tmp[3] = page_hdr_tmp[4];
//for page_type
tmp = (unsigned char *)&page_type;
tmp[0] = page_hdr_tmp[25];
tmp[1] = page_hdr_tmp[24];
//for tab_space_id
tmp = (unsigned char *)&tab_space_id;
tmp[0] = page_hdr_tmp[37];
tmp[1] = page_hdr_tmp[36];
tmp[2] = page_hdr_tmp[35];
tmp[3] = page_hdr_tmp[34];
//for page_level
tmp = (unsigned char *)&page_level;
tmp[0] = page_hdr_tmp[61];
tmp[1] = page_hdr_tmp[60];
printf("page_offset is %d\n",page_offset);
printf("page_type is %x\n",page_type);
printf("tab_space_id is %x\n",tab_space_id);
printf("page_level is %x\n\n",page_level);
}
fclose(fd);
system("pause");
return 0;
}
我们打开程序输出的log来看,信息如下:
filesize is 10485760 processing the 0 [rd] page now from our calclation page_off is 0 page_offset is 0 page_type is 8 tab_space_id is 11 page_level is b processing the 1 [rd] page now from our calclation page_off is 16384 page_offset is 1 page_type is 5 tab_space_id is 11 page_level is 0 processing the 2 [rd] page now from our calclation page_off is 32768 page_offset is 2 page_type is 3 tab_space_id is 11 page_level is 0 processing the 3 [rd] page now from our calclation page_off is 49152 page_offset is 3 page_type is 45bf tab_space_id is 11 page_level is 0
其中page_type的45bf代表的是索引节点。而page_level是0,意思是,索引节点的层级为0。
到了第75 [rd]块的时候,所有块都是空白块了。
processing the 74 [rd] page now from our calclation page_off is 1212416 page_offset is 74 page_type is 45bf tab_space_id is 11 page_level is 0 processing the 75 [rd] page now from our calclation page_off is 1228800 page_offset is 0 page_type is 0 tab_space_id is 0 page_level is 0 processing the 76 [rd] page now from our calclation page_off is 1245184 page_offset is 0 page_type is 0 tab_space_id is 0 page_level is 0
测试的ibd文件是mysql 5.6自带的sakila库下的payment.ibd。