My favorites | Sign in
Project Logo
                
Search
for
Updated Jul 01 (2 days ago) by shlomi.noach
Labels: Featured, Phase-Deploy, Howto
InnodbRecoveryHowto  
Innodb Recovery Howto.

Introduction

InnoDB is pretty stable and reliable storage engine, but even it could be corrupted in case of hardware failure or human mistakes. For example, you could have a failures in your RAID controller (duet to cabling) or memory errors or someone could do “DELETE FROM some_table” and you’ll lose your data.

In many cases innodb’s internal recovery code could not handle such problems and the only way to recover data is to work with innodb tablespaces directly. This is what you can do with our Data Recovery Toolkit for InnoDB (toolkit later in this document).

Other interesting reading:

Tools Overview

Described toolkit consists of a set of useful tools for innodb recovery such as:

Pre-recovery Tablespace Processing

Before you'd start recovering your data you'd definitely like to make a small research on your tablespace. So far we have no tools for innodb global data dictionary view, but you could use innodb's internal tools for this. One of the most useful is table_monitor. To use it you need to be able to at least start your mysql on your corrupted tablespace (see innodb_force_recovery option of mysqld). When you have your mysql up and running, just connect to any database (like mysql or test) and perform a following command:

    CREATE TABLE innodb_table_monitor(x int) engine=innodb;

This will force innodb engine to start table monitor and dump some useful data regarding your tablespaces in mysql's error log (log-error option).

Most interesting information here is a mapping between your tables' primary indexes and table ids. For example you can get an output like this:

    TABLE: name test/site_folders, id 0 119, columns 9, indexes 1, appr.rows 1
      COLUMNS: id: DATA_INT len 4 prec 0; name: type 12 len 765 prec 0; sites_count: DATA_INT len 4 prec 0;
	 		   created_at: DATA_INT len 8 prec 0; updated_at: DATA_INT len 8 prec 0; 
	           DB_ROW_ID: DATA_SYS prtype 256 len 6 prec 0; DB_TRX_ID: DATA_SYS prtype 257 len 6 prec 0; 
	           DB_ROLL_PTR: DATA_SYS prtype 258 len 7 prec 0; 
	  INDEX: name PRIMARY, id 0 254, fields 1/7, type 3
	   root page 271, appr.key vals 1, leaf pages 1, size pages 1
	   FIELDS:  id DB_TRX_ID DB_ROLL_PTR name sites_count created_at updated_at

Here you can see a list of fields in your table and, most interesting - you can see that the PRIMARY index for your table is mapped to index_id="0 254". Read below to see how to use this information.

Working With a Part of InnoDB Tablespace

heuristics_parser tool works fine with any tablespace types (single and file-per-table), but in some cases you'd like to work with a smaller part of your data: huge tablespace files (10Gb+), tablespaces with many tables that have an identical structure or just for testing your table descriptions.

At this moment we have a page_parser tool which takes some tablespace and slices it to a set of pages grouped by table_id. Next steps you could make are:

When you run page_parser your pages are placed in pages-NNNNNNNN/HHHH-LLLL directories where NNNNNNNN is timespamp of the second when you started the tool, HHHH and LLLL are high and low words for index_id of a page. Every page would be placed in III-NNNNN.page files where III is a page number (offset / page size) and NNNNN is page_id of a page.

To concatenate some table pages in one files, you can use a following command:

    $ cat *.page > page

Preparing a Tables Description File

First of all, what are these table definitions? The answer is simple: table definition is a simple, but really powerful set of rules which describe your table structure and help our tools recover your data. One table definition consists of a set of fields, each of which consists of:

As of version 0.1 constraints_parser could work with compiled-in table definitions only. This mean that you need to write your table definitions and then compile your own version of tool binary. In next versions we're going to add some external config file support to be able to ship binary versions of our toolset.

At this moment you have two options how to create your table definitions:

After an automatic table definitions generation you'll need to check fields limits, etc and fix defaults of they do not match your own data limits.

Here is an example of table_def.h file with some table definition made by create_defs.pl script and adjusted to match real table constraints:

#ifndef table_defs_h
#define table_defs_h

// Table definitions
table_def_t table_definitions[] = {
	{
		name: "some_table",
		{
			{ /* int(11) */
				name: "id",
				type: FT_INT,
				fixed_length: 4,

				has_limits: TRUE,
				limits: {
					int_min_val: 1,
					int_max_val: 10000
				},

				can_be_null: FALSE
			},
			{ /* Innodb's internally used field */
				name: "DB_TRX_ID",
				type: FT_INTERNAL,
				fixed_length: 6,

				can_be_null: FALSE
			},
			{ /* Innodb's internally used field */
				name: "DB_ROLL_PTR",
				type: FT_INTERNAL,
				fixed_length: 7,

				can_be_null: FALSE
			},
			{ /* enum('yes','no') */
				name: "auto_restart",
				type: FT_ENUM,
				fixed_length: 1,

				has_limits: TRUE,
				limits: {
					enum_values_count: 2,
					enum_values: { "yes", "no" }
				},

				can_be_null: FALSE
			},
			{ /* int(11) */
				name: "num_created_today",
				type: FT_INT,
				fixed_length: 4,

				can_be_null: FALSE
			},
			{ /* bigint(20) */
				name: "time_yesterday",
				type: FT_INT,
				fixed_length: 8,

				can_be_null: FALSE
			},
			{ /* varchar(20) */
				name: "from_username",
				type: FT_CHAR,
				min_length: 0,
				max_length: 20,

				has_limits: TRUE,
				limits: {
					char_min_len: 0,
					char_max_len: 15,
					char_ascii_only: TRUE
				},

				can_be_null: FALSE
			},
			{ /* tinyint(1) */
				name: "affiliate_admin",
				type: FT_INT,
				fixed_length: 1,

				has_limits: TRUE,
				limits: {
					int_min_value: 0,
					int_max_value: 1,
					can_be_null: FALSE
				},

				can_be_null: TRUE
			},				
			{ type: FT_NONE }
		}
	}
};

#endif

I'd like to bring your attention to two fields here (actually, tree, but in a definition above we see only two):

These two (or three) fields should be in your table definition (at least in v.0.1) to let constraints_parser to find your data in a tablespace.

When table_defs.h file is ready, you can proceed with the toolset compilation to get a set of binaries specific for your own database (we'll try to avoid this compilation step in future releases).

Toolset Compilation Procedure

As mentioned before, in release 0.1 of the toolkit you need to compile your own binaries to use our toolkit. Internally our toolset uses some low-level InnoDB code pieces to work with pages and fields in tablespaces. That is why we ship trimmed down version of mysql sources with our project (mysql-source directory).

We tried to make build process as simple as possible so after you have table_defs.h file created you can just run make and you should be done with building. If you'll get any problems, most possible they would be in mysql-sources building process. In this case you can just download mysql sources from site(http://www.mysql.com), configure and build mysql as following:

    $ ./configure
    $ make

and copy MYSQL_SOURCES/innobase/ut/libut.a file to toolkit build directory and try to run make again.

If you'd like to build static versions of binaries, uncomment CFLAGS line in the Makefile.

Data Recovery Process Explained

Now, let's get to data recovery process. Recommended (really detailed) sequence of a actions for data recovery is a following:

  1. Split your tablespace to pages with page_parser
  2. Find your index_id values of a primary indexes for your pages.
  3. Take one page from your most valuable table directory.
  4. Create table definition for this table (automatically with create_defs.pl or manually).
  5. Try to recover some data from this one page file in debug mode.
  6. If no data was recovered, check your table_defs.h file and try again.
  7. If everything worked fine, try to run constraints_parser in normal (non-debug) mode and check your data.
  8. If data looks ok, then get all pages from your table's directory, concatenate them (cat *.page > pages) and try to recover all your table's data.
  9. Repeat steps 3-8 for all tables you need.

If you have no tables with an identical structure and you're pretty confident about your table definitions, you can recover your data from your tablespace data directly.

If you are getting a lot of junk records in your constraints_parser output, try to set more limits in your definitions file so parser would know how to filter out these false positives.

Hints

Using filters

The tool scans a page with a byte step. With each iteration it checks whether a row is valid. There are two tests:

If the tests are not passed the seek position is shifted on one byte. If the tests are OK the position is shifted on the size of record. It should be noted if junk record is found that means a good one is lost.

Use as narrow filters as possible. For example, PRIMARY KEY is declared as int(11) signed, however the key starts from 1. So instead of

                        { /* int(11) */
                                name: "id",
                                type: FT_INT,
                                fixed_length: 4,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        int_min_val: -2147483648LL,
                                        int_max_val: 2147483647LL
                                },

                                can_be_null: FALSE
                        },

Use

			{ /* int(11) */
                                name: "id",
                                type: FT_INT,
                                fixed_length: 4,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        int_min_val: 1,
                                        int_max_val: 2147483647LL
                                },

                                can_be_null: FALSE
                        },

Try to play around with maximum varchar lenght. If you know your string doesn't exceed 20 symbols set this as the char_max_len.

Compilation

create_defs.pl generates code appicable to >5.0.3 , so sorrect the table_defs.h :

                        { /* decimal(4,2) unsigned */
                                name: "working_hours",
                                type: FT_CHAR,
                                fixed_length: 6,

                                has_limits: FALSE,
                                limits: {
                                        can_be_null: TRUE,
                                        char_min_len: 0,
                                        char_max_len: 2,
                                        char_ascii_only: TRUE
                                },

                                can_be_null: TRUE
                        },

On Linux you may get comilation error saying there is no isnumber() function in check_data.c The matter is isnumber() comes from BSD world however C standard defines isdigit() function. Just change the name. BLOBs are not supported. But if your blob fields have no binary data and one record fits in a page (16k), you can try a trick:

create_defs.pl:

  sub FindFieldByName($$) {
  	my $fields = shift;
  	my $name = shift;
@@ -333,7 +346,7 @@
  		return { type => 'FT_TEXT', min_len => 0, max_len => 255 };
  	}

-	if ($type =~ /^TEXT$/i) {
+	if ($type =~ /^TEXT|BLOB$/i) {
  		return { type => 'FT_TEXT', min_len => 0, max_len => 65535 };
  	}

Using the tool

- The tool knows itself :) Run constraints_parser in debug mode (-V) and if your guess was wrong it will tell you: "Page is in COMPACT format while we're looking for REDUNDANT - skipping" or "Page is in REDUNDANT format while we're looking for COMPACT - skipping" - Run

dc -e "2o hexdump –C d pagefile | grep 00000020 | awk '{ print $12}' p" | sed 's/./& /g' | awk '{ print $1}'
0 stands for version 4, 1 - for 5

  • Although in the table_defs.h can be defined all tables from you database it is better if you use own table_defs.h per table.
  • If the tool finds nothing but you see your data it is useful to run it in debug mode.

Let's say you have found a string "abcd" in a page. Your table_defs.h is:

                      { /* int(11) */
                                name: "id",
                                type: FT_INT,
                                fixed_length: 4,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        int_min_val: 1,
                                        int_max_val: 100000
                                },

                                can_be_null: FALSE
                        },
                        { /*  */
                                name: "DB_TRX_ID",
                                type: FT_INTERNAL,
                                fixed_length: 6,

                                can_be_null: FALSE
                        },
                        { /*  */
                                name: "DB_ROLL_PTR",
                                type: FT_INTERNAL,
                                fixed_length: 7,

                                can_be_null: FALSE
                        },
                        { /* varchar(100) */
                                name: "name",
                                type: FT_CHAR,
                                min_length: 0,
                                max_length: 100,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: TRUE,
                                        char_min_len: 0,
                                        char_max_len: 100,
                                        char_ascii_only: TRUE
                                },

                                can_be_null: TRUE
                        },

Before your "abcd" there are 4+6+7 = 17 bytes. The place where data begin is called ORIGIN. You find the origin in hex editor. Then looking for the offset equal to the origin in the debug output. Then you'll see why your record isn't found.

  • Of course you don't know index id when you recover data. There are way how to find out.
- A table is identified by index id. So all pages of the same table are in one directory - If there are VARCHARS or CHARS in the table and you know possible values you can grep all tablespace to find your index id:

# grep -r "XXX-yyyy-ZzZz" pages-1217332715/
Binary file pages-1217332715/0-276/1116-00001116.page matches
Binary file pages-1217332715/0-276/596-00000596.page matches
Binary file pages-1217332715/0-276/715-00000715.page matches
Binary file pages-1217332715/0-276/1119-00001119.page matches
Binary file pages-1217332715/0-276/1237-00001237.page matches
Binary file pages-1217332715/0-276/1101-00001101.page matches
Binary file pages-1217332715/0-276/709-00000709.page matches
#

Try different strings if there are more than 1 directory is found.

  • If you are you completely unaware what inside the table is or there are only INTs or DATE it is more difficult to find, but possible.

You compile sources with the respective table_defs.h. Make sure it defines only one table. Run the script below. The idea behind is: If the page is good, constraints_parser will return >0 records.

Please do appropriate changes for your case.

#!/bin/sh

f=`find pages-1217332715 -name *.page`

for i in $f
do
        n=`./constraints_parser -4f $i | wc -l`
        if [ $n -gt 0 ]
        then
                echo $i
        fi
done

It shows the pages which may have records of your table.

  • If there are many table to recover this script may help you
  • #!/bin/sh
    
    db=epic
    
    tables=`mysql -u root -e "SHOW TABLES" -s $db`
    
    for i in $tables
    do
            #Check how many rows has a table
            rows=`mysql -u root -e "SELECT COUNT(*) FROM $i" -s $db`
            if [ $rows -ne 0 ]
            then
                    # Prepare environment
                    echo "Restoring table $i"
                    table=$i
                    cd include && rm -f table_defs.h && ln -s table_defs.h.$table table_defs.h
                    cd ..
                    make clean all
                    # Restoring rows
                    found=0
                    while [ $found -lt 1 ]
                    do
                            echo ""
                            read -p "Enter the path to directory where data of table $i might be: " dir
                            cat $dir/*.page > p
                            ./constraints_parser -4 -f p >> out.$i
                            found=`cat out.$i | wc -l`
                    done
    
            fi
    done
  • If you are lucky you'll get only one index id grepping a tablespace beased on known string. What if not. It is clear the longer string the better match. Let's say you have a table ordner:
  • mysql> desc ordner;
    +------------+--------------+------+-----+---------+-------+
    | Field      | Type         | Null | Key | Default | Extra |
    +------------+--------------+------+-----+---------+-------+
    | id         | int(11)      | NO   | PRI |         |       |
    | first_name | varchar(255) | YES  |     | NULL    |       |
    | last_name  | varchar(255) | YES  |     | NULL    |       |
    +------------+--------------+------+-----+---------+-------+

If you know there is John Smith in the table you can try two strings grep -r JohnSmith pages-*. This will work because there is no \0 after John.

SYS_TABLES and SYS_INDEXES

SYS_INDEXES lays in the index id 0-3

CREATE TABLE `SYS_INDEXES` (
  `TABLE_ID` bigint(20) unsigned NOT NULL default '0',
  `ID` bigint(20) unsigned NOT NULL default '0',
  `NAME` varchar(120) default NULL,
  `N_FIELDS` int(10) unsigned default NULL,
  `TYPE` int(10) unsigned default NULL,
  `SPACE` int(10) unsigned default NULL,
  `PAGE_NO` int(10) unsigned default NULL,
  PRIMARY KEY  (`TABLE_ID`,`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

table_defs.h.SYS_INDEXES

#ifndef table_defs_h
#define table_defs_h

// Table definitions
table_def_t table_definitions[] = {
        {
                name: "SYS_INDEXES",
                {
                        { /* bigint(20) unsigned */
                                name: "TABLE_ID",
                                type: FT_UINT,
                                fixed_length: 8,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        uint_min_val: 0,
                                        uint_max_val: 18446744073709551615ULL
                                },

                                can_be_null: FALSE
                        },
                        { /* bigint(20) unsigned */
                                name: "ID",
                                type: FT_UINT,
                                fixed_length: 8,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        uint_min_val: 0,
                                        uint_max_val: 18446744073709551615ULL
                                },

                                can_be_null: FALSE
                        },
                        { /*  */
                                name: "DB_TRX_ID",
                                type: FT_INTERNAL,
                                fixed_length: 6,

                                can_be_null: FALSE
                        },
                        { /*  */
                                name: "DB_ROLL_PTR",
                                type: FT_INTERNAL,
                                fixed_length: 7,

                                can_be_null: FALSE
                        },
                        { /* varchar(120) */
                                name: "NAME",
                                type: FT_CHAR,
                                min_length: 0,
                                max_length: 120,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: TRUE,
                                        char_min_len: 0,
                                        char_max_len: 120,
                                        char_ascii_only: TRUE
                                },

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "N_FIELDS",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "TYPE",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "SPACE",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "PAGE_NO",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { type: FT_NONE }
                }
        },
};

#endif

SYS_TABLES lays in the index_id 0-1

CREATE TABLE `SYS_TABLES` (
  `NAME` varchar(255) NOT NULL default '',
  `ID` bigint(20) unsigned NOT NULL default '0',
  `N_COLS` int(10) unsigned default NULL,
  `TYPE` int(10) unsigned default NULL,
  `MIX_ID` bigint(20) unsigned default NULL,
  `MIX_LEN` int(10) unsigned default NULL,
  `CLUSTER_NAME` varchar(255) default NULL,
  `SPACE` int(10) unsigned default NULL,
  PRIMARY KEY  (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

table_defs.h.SYS_TABLES

#ifndef table_defs_h
#define table_defs_h

// Table definitions
table_def_t table_definitions[] = {
        {
                name: "SYS_TABLES",
                {
                        { /* varchar(255) */
                                name: "NAME",
                                type: FT_CHAR,
                                min_length: 0,
                                max_length: 255,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        char_min_len: 0,
                                        char_max_len: 255,
                                        char_ascii_only: TRUE
                                },

                                can_be_null: FALSE
                        },
                        { /*  */
                                name: "DB_TRX_ID",
                                type: FT_INTERNAL,
                                fixed_length: 6,

                                can_be_null: FALSE
                        },
                        { /*  */
                                name: "DB_ROLL_PTR",
                                type: FT_INTERNAL,
                                fixed_length: 7,

                                can_be_null: FALSE
                        },
                        { /* bigint(20) unsigned */
                                name: "ID",
                                type: FT_UINT,
                                fixed_length: 8,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        uint_min_val: 0,
                                        uint_max_val: 18446744073709551615ULL
                                },

                                can_be_null: FALSE
                        },
                        { /* int(10) unsigned */
                                name: "N_COLS",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "TYPE",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { /* bigint(20) unsigned */
                                name: "MIX_ID",
                                type: FT_UINT,
                                fixed_length: 8,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: TRUE,
                                        uint_min_val: 0,
                                        uint_max_val: 18446744073709551615ULL
                                },

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "MIX_LEN",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { /* varchar(255) */
                                name: "CLUSTER_NAME",
                                type: FT_CHAR,
                                min_length: 0,
                                max_length: 255,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: TRUE,
                                        char_min_len: 0,
                                        char_max_len: 255,
                                        char_ascii_only: TRUE
                                },

                                can_be_null: TRUE
                        },
                        { /* int(10) unsigned */
                                name: "SPACE",
                                type: FT_UINT,
                                fixed_length: 4,

                                can_be_null: TRUE
                        },
                        { type: FT_NONE }
                }
        },
};

#endif

Both tables are in redundant format

How to get CREATE info from .frm files

As you know the innodb recovery tool requires table definitions file table_def.h. Tho most convenient way to generate it is to use the respective perl script create_defs.pl . For this you need a live , possibly empty database of tables you want to recover.

If a customer can't give CREATE SQL files it's possible to get them from customer's .frm files.

How to recover NON Primary Key

Usually you need the primary key only. Indeed, if there are other keys in a table you can rebuild them when you have data. I case you can't recover PK(pages lost, overwritten...) some information which may be usefull can be restored from non-primary key. An InnoDB page is the same format whether this is primary key or not. The non-PK page contains tuples (key, PK). Its index_id can be found in SYS_TABLES/SYS_INDEXES.

So all you have to do is to prepare table_defs.h in respect to index structure.

Here is an example.

The table:

CREATE TABLE `message_comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `message_id` int(11) NOT NULL DEFAULT '0',
  `author_id` int(11) NOT NULL DEFAULT '0',
  `body` text,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `attachments_count` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `index_message_comments_on_message_id_and_created_at` (`message_id`,`created_at`)
) ENGINE=InnoDB AUTO_INCREMENT=33133 DEFAULT CHARSET=latin1

The table_defs.h

#ifndef table_defs_h
#define table_defs_h

// Table definitions
table_def_t table_definitions[] = {
        {
                name: "index_message_comments_on_message_id_and_created_at",
                {
                        { /* int(11) */
                                name: "message_id",
                                type: FT_INT,
                                fixed_length: 4,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        int_min_val: -2147483648LL,
                                        int_max_val: 2147483647LL
                                },

                                can_be_null: FALSE
                        },
                        { /* datetime */
                                name: "created_at",
                                type: FT_DATETIME,
                                fixed_length: 8,

                                can_be_null: TRUE
                        },
                        { /* int(11) */
                                name: "id",
                                type: FT_INT,
                                fixed_length: 4,

                                has_limits: TRUE,
                                limits: {
                                        can_be_null: FALSE,
                                        int_min_val: -2147483648LL,
                                        int_max_val: 2147483647LL
                                },

                                can_be_null: FALSE
                        },
                        { type: FT_NONE }
                }
        },
};

#endif

Loading data to mysql

This example can be useful when you need to do conversion during data loading for example

LOAD DATA INFILE '/path/to/datafile'
REPLACE INTO TABLE <table_name>
FIELDS TERMINATED BY '\t'
OPTIONALLY ENCLOSED BY '"'
LINES STARTING BY '<table_name>\t'
(id,sessionid,uniqueid,username,nasipaddress,@var1,@var2,etc)
SET
  datefield1 = FROM_UNIXTIME(@var1),
  datefield2 = FROM_UNIXTIME(@var2,'%Y %D %M %h:%i:%s %x');

Comment by rainofkayos, May 15, 2008

whoever wrote this u ROCK!!!!! lol

Comment by noahspurrier, Aug 01, 2008

In the line you have in the article:

Here is an example of table_def.h file with some table definition made by create_defs.pl script and adjusted to match real table constraints:

It should probably read:

Here is an example of table_defs.h file with some table definition made by create_defs.pl script and adjusted to match real table constraints:

Note "table_defs.h" instead of the original "table_def.h" because "table_defs.h" is what you actually include in the source code.

Comment by GreatGomboo, Aug 12, 2008

This has proven to be a very much appreciated solution. Given that you are trying desperately to get as much of your data back as possible this is a god send. It works best when you can really nail down the limits of acceptable values in the table fields.

Thanks for making this.

Comment by soa.adept, Sep 11, 2008

I haven't managed to get split_dump.pl to work... I'm a self-confessed noob to MySql? and I can't seem to follow the cat .page > page step. In particular the "try to recover all your table's data" bit is somewhat elusive for me. Can anyone give me a hint what to do next?

Comment by santurelli, Jan 03, 2009

Hi, I'm not have been able, in any mammer, to install your tool. I tried to install MYSQL as you have suggested but the problem remaining. In any case, I obtained error: No curses/termcap library found. Have you any suggestion, please?

Thanks, Pietro

Comment by chavocarlos, Jan 07, 2009

Hi, i don't speak english very well... What files should i concatenate? in the filenames, where are the page_id? Thanks a lot. I hope a lot from this tools.

Comment by chavocarlos, Jan 08, 2009

Hi again, I run page_parser on all .ibd files, and I concatenate all page files in "0-932" folders (files with the same table_id 932? right?). Now I see mysqld.log and.. Should I find some table with "0 932" id? I didn't found anything :( please, I appreciate some help.

Comment by speedmcu, Jan 18, 2009

5)Try to recover some data from this one page file in debug mode.


I have got the single table page file. but how to recover this single table page file? and what is "heuristics_parser tool " ,I can't get anything from google. thanks , mingo

Comment by chriscalender, Apr 15, 2009

I've posted some step-by-step instructions on how to recover data using the InnoDB Recovery Tool here:

http://www.chriscalender.com/?p=49

Hope it helps.


Sign in to add a comment
Hosted by Google Code