| Bug #19727 | InnoDB crashed server and crashed tables are not recoverable | ||
|---|---|---|---|
| Submitted: | 11 May 2006 16:17 | Modified: | 22 Jun 2006 17:48 |
| Reporter: | Gabriel Barazer | ||
| Status: | Closed | ||
| Category: | Server: InnoDB | Severity: | S1 (Critical) |
| Version: | 4.1, 5.0, 5.1 | OS: | Linux (Linux 2.6) |
| Assigned to: | Bugs System | Target Version: | |
[11 May 2006 16:17]
Gabriel Barazer
[11 May 2006 16:27]
Heikki Tuuri
Gabriel, please attach the complete .err log, maybe gzipped, to this bug report. Regards, Heikki
[11 May 2006 16:40]
Heikki Tuuri
There is a bug in 5 functions in row0mysql.c. We should commit the trx BEFORE calling
unlock_data_dictionary(), since we assume in InnoDB's internal SQL interpreter that
transactional lock waits can never happen. The whole data dict operation just be
protected then by the dictionary semaphore.
Assigning Osku to fix this in 4.1, 5.0, 5.1.
row0mysql.c:
/*************************************************************************
Discards the tablespace of a table which stored in an .ibd file. Discarding
means that this function deletes the .ibd file and assigns a new table id for
the table. Also the flag table->ibd_file_missing is set TRUE. */
int
row_discard_tablespace_for_mysql(
/*=============================*/
/* out: error code or DB_SUCCESS */
const char* name, /* in: table name */
trx_t* trx) /* in: transaction handle */
{
...
funct_exit:
row_mysql_unlock_data_dictionary(trx);
if (graph) {
que_graph_free(graph);
}
trx_commit_for_mysql(trx);
trx->op_info = "";
return((int) err);
}
/*********************************************************************
Imports a tablespace. The space id in the .ibd file must match the space id
of the table in the data dictionary. */
int
row_import_tablespace_for_mysql(
/*============================*/
/* out: error code or DB_SUCCESS */
const char* name, /* in: table name */
trx_t* trx) /* in: transaction handle */
{
...
funct_exit:
row_mysql_unlock_data_dictionary(trx);
trx_commit_for_mysql(trx);
trx->op_info = "";
return((int) err);
}
/*************************************************************************
Drops a table for MySQL. If the name of the table to be dropped is equal
with one of the predefined magic table names, then this also stops printing
the corresponding monitor output by the master thread. */
int
row_drop_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
const char* name, /* in: table name */
trx_t* trx, /* in: transaction handle */
ibool drop_db)/* in: TRUE=dropping whole database */
{
...
funct_exit:
if (locked_dictionary) {
row_mysql_unlock_data_dictionary(trx);
}
if (dir_path_of_temp_table) {
mem_free(dir_path_of_temp_table);
}
que_graph_free(graph);
trx_commit_for_mysql(trx);
trx->op_info = "";
#ifndef UNIV_HOTBACKUP
srv_wake_master_thread();
#endif /* !UNIV_HOTBACKUP */
return((int) err);
}
/*************************************************************************
Drops a database for MySQL. */
int
row_drop_database_for_mysql(
/*========================*/
/* out: error code or DB_SUCCESS */
const char* name, /* in: database name which ends to '/' */
trx_t* trx) /* in: transaction handle */
{
...
row_mysql_unlock_data_dictionary(trx);
trx_commit_for_mysql(trx);
trx->op_info = "";
return(err);
}
/*************************************************************************
Renames a table for MySQL. */
int
row_rename_table_for_mysql(
/*=======================*/
/* out: error code or DB_SUCCESS */
const char* old_name, /* in: old table name */
const char* new_name, /* in: new table name */
trx_t* trx) /* in: transaction handle */
{
...
funct_exit:
if (!recovering_temp_table) {
row_mysql_unlock_data_dictionary(trx);
}
if (graph) {
que_graph_free(graph);
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
trx_commit_for_mysql(trx);
trx->op_info = "";
return((int) err);
}
[11 May 2006 16:43]
Gabriel Barazer
.err Log sent. This log begins at the time I upgraded my 4.1 server to 5.0.21 (cleared the old 4.1 log (.err before starting the 5.0.21 server) As I said in the previous comment, I run a cron job which "rotates" the tables every minute (CREATE LIKE, double RENAME) When repairing the server (I remarked the bug only today), I had to remove some .frm manually, and create a table in another database , then copy the .frm then DROP TABLE (on one hand data wasn't in the internal log but had .frm, on the other hand , data was in the internal log but without .frm) I think the out of sync is done if the server crashed during rename. There must be a problem with anything done on the .frm _before_ the innodb internal is updated/commited.
[11 May 2006 16:43]
Heikki Tuuri
Gabriel, since mysqld probably crashed in a RENAME, the .frm files and the tables inside InnoDB's internal data dictionary are not in sync. To access the table you need to fix this sync problem. Please see http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting-datadict.html Regards, Heikki
[11 May 2006 16:46]
Gabriel Barazer
Sorry for the previous comment, you posted faster than me :) I think this bug can be closed now. Thanks !
[11 May 2006 16:48]
Heikki Tuuri
Gabriel, we cannot close the bug since Osku really has to fix the 5 bugs in row0mysql.c. The lock wait and crash is improbable. That is why no one has reported this timing problem before. Thank you! Heikki
[12 May 2006 14:14]
Osku Salerma
Fixed in 4.1, 5.0 and 5.1 in InnoDB's Subversion repositories.
[31 May 2006 22:57]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/7116
[1 Jun 2006 12:16]
Alexander Ivanov
Pushed to 5.1.11
[6 Jun 2006 10:37]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/7312
[6 Jun 2006 11:10]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/7314
[6 Jun 2006 11:49]
Alexander Ivanov
Pushed to 4.1.20, 5.0.22.
[20 Jun 2006 4:29]
Lars Thalmann
Pushed into 4.1.21
[21 Jun 2006 16:21]
Lars Thalmann
Pushed into 5.1.12
[22 Jun 2006 17:48]
Paul DuBois
Noted in 4.1.21, 5.0.23, 5.1.12. InnoDB unlocked its data directory before committing a transaction, potentially resulting in non-recoverable tables if a server crash occurred before the commit.
