从ibd文件获取表空间id

xtrabackup恢复过程中出现如下错误 

InnoDB: Doing recovery: scanned up to log sequence number 1024370417664 (62 %)

InnoDB: Doing recovery: scanned up to log sequence number 1024375660544 (75 %)

140810 13:53:42  InnoDB: Starting an apply batch of log records to the database...

InnoDB: Progress in percents: 140810 13:53:42  InnoDB: Error: space id and page n:o stored in the page

InnoDB: read in are 1571195158:1995475462, should be 51:8406774!

InnoDB: Database page corruption on disk or a failed

InnoDB: file read of page 8406774.

InnoDB: You may have to recover from a backup.

140810 13:53:42  InnoDB: Page dump in ascii and hex (16384 bytes):

从错误信息中可以看出,有页损坏了,并给出了space id和page no (51,8406774). 

在非共享表空间(即innodb_file_per_table=on)时,每个表对应一个表空间。那么我们怎么通过表空间id(即space id)得到对应的表呢?

在mysql 5.6以上版本中,可通过查询information_schema.INNODB_SYS_DATAFILES得到表空间id和表的对应关系,

http://dev.mysql.com/doc/refman/5.6/en/innodb-sys-datafiles-table.html 

mysql> select * from information_schema.INNODB_SYS_DATAFILES where space=287;

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

| SPACE | PATH          |

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

|   287 | .\test\t2.ibd |

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

然而出现此问题的mysql版本为5.1.那么我们怎么得到5.6以下版本表空间id和表的对应关系呢。

从源码中可以看到,每个表空间第一个页的偏移38字节处,用4个字节存储了表空间id信息。参看函数fsp_header_init_fields

于是写了个小工具直接从idb文件读取表空间id信息。

例如获取表t1的表空间为795 

$ sudo ./test /u01/mysql/data/test/t1.ibd

spaceid:795 , file:/u01/mysql/data/test/t1.ibd 

工具源码如下:

#include "stdlib.h"

#include "stdio.h"



#ifdef _WIN64

typedef unsigned __int64     ulint;

#else

typedef unsigned long int     ulint;



#endif /* _WIN64 */



typedef unsigned char byte;



ulint

mach_read_from_4(

     byte*     b)     /*!< in: pointer to four bytes */

{

     return( ((ulint)(b[0]) << 24)

          | ((ulint)(b[1]) << 16)

          | ((ulint)(b[2]) << 8)

          | (ulint)(b[3])

          );

}



void main(int argc,char *argv[])

{

        FILE *fp;

        byte ret[5];

        int  offset;

        ulint spaceid;



        if ((fp=fopen(argv[1],"r"))==NULL)

        {

                printf("cannot open this file\n");

                exit(0);

        }



        offset=38;

        if (fseek(fp,offset,0)!=0)

        {

                printf("cannot move pointer there.\n");

                exit(0);

        }



        fread(ret,sizeof(byte),4,fp);

        spaceid = mach_read_from_4(ret);



        printf("spaceid:%lu , file:%s\n",spaceid,argv[1]);



        fclose(fp);

}

 

你可能感兴趣的:(表空间)