从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); }