summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--innobase/buf/buf0rea.c2
-rw-r--r--innobase/dict/dict0load.c30
-rw-r--r--innobase/fil/fil0fil.c93
-rw-r--r--innobase/include/dict0load.h10
-rw-r--r--innobase/include/fil0fil.h28
-rw-r--r--innobase/include/row0mysql.h20
-rw-r--r--innobase/include/trx0trx.h13
-rw-r--r--innobase/row/row0ins.c4
-rw-r--r--innobase/row/row0mysql.c141
-rw-r--r--innobase/row/row0sel.c18
-rw-r--r--innobase/srv/srv0start.c43
-rw-r--r--innobase/trx/trx0trx.c8
-rw-r--r--sql/ha_innodb.cc15
13 files changed, 321 insertions, 104 deletions
diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c
index 11107d777c8..58287d37387 100644
--- a/innobase/buf/buf0rea.c
+++ b/innobase/buf/buf0rea.c
@@ -326,7 +326,7 @@ buf_read_page(
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: error: trying to access tablespace %lu page no. %lu,\n"
+" InnoDB: Error: trying to access tablespace %lu page no. %lu,\n"
"InnoDB: but the tablespace does not exist or is just being dropped.\n",
(ulong) space, (ulong) offset);
}
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 7890ebd2b47..61facc8818d 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -205,12 +205,14 @@ loop:
In a crash recovery we already have all the tablespace objects created.
This function compares the space id information in the InnoDB data dictionary
to what we already read with fil_load_single_table_tablespaces().
-In a normal startup we just scan the biggest space id, and store it to
-fil_system. */
+
+In a normal startup, we create the tablespace objects for every table in
+InnoDB's data dictionary, if the corresponding .ibd file exists.
+We also scan the biggest space id, and store it to fil_system. */
void
-dict_check_tablespaces_or_store_max_id(
-/*===================================*/
+dict_check_tablespaces_and_store_max_id(
+/*====================================*/
ibool in_crash_recovery) /* in: are we doing a crash recovery */
{
dict_table_t* sys_tables;
@@ -280,6 +282,14 @@ loop:
FALSE, TRUE, TRUE);
}
+ if (space_id != 0 && !in_crash_recovery) {
+ /* It is a normal database startup: create the space
+ object and check that the .ibd file exists. */
+
+ fil_open_single_table_tablespace(FALSE, space_id,
+ name);
+ }
+
mem_free(name);
if (space_id > max_space_id) {
@@ -796,8 +806,18 @@ dict_load_table(
/* Ok; (if we did a crash recovery then the tablespace
can already be in the memory cache) */
} else {
+ /* In >= 4.1.9, InnoDB scans the data dictionary also
+ at a normal mysqld startup. It is an error if the
+ space object does not exist in memory. */
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: error: space object of table %s,\n"
+"InnoDB: space id %lu did not exist in memory. Retrying an open.\n",
+ name, (ulong)space);
/* Try to open the tablespace */
- if (!fil_open_single_table_tablespace(space, name)) {
+ if (!fil_open_single_table_tablespace(TRUE,
+ space, name)) {
/* We failed to find a sensible tablespace
file */
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index de528355182..89648b3feca 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -466,6 +466,10 @@ fil_node_open_file(
ulint size_low;
ulint size_high;
ibool ret;
+ byte* buf2;
+ byte* page;
+ ibool success;
+ ulint space_id;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
@@ -494,6 +498,8 @@ fil_node_open_file(
system->n_open++;
if (node->size == 0) {
+ ut_a(space->purpose != FIL_LOG);
+
os_file_get_size(node->handle, &size_low, &size_high);
size_bytes = (((ib_longlong)size_high) << 32)
@@ -507,6 +513,46 @@ fil_node_open_file(
ut_a(space->id != 0);
+ if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
+ fprintf(stderr,
+"InnoDB: Error: the size of single-table tablespace file %s\n"
+"InnoDB: is only %lu %lu, should be at least %lu!", node->name,
+ (ulong) size_high,
+ (ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
+
+ ut_a(0);
+ }
+
+ /* Read the first page of the tablespace */
+
+ buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
+ /* Align the memory for file i/o if we might have O_DIRECT
+ set */
+ page = ut_align(buf2, UNIV_PAGE_SIZE);
+
+ success = os_file_read(node->handle, page, 0, 0,
+ UNIV_PAGE_SIZE);
+ space_id = fsp_header_get_space_id(page);
+
+ ut_free(buf2);
+
+ if (space_id == ULINT_UNDEFINED || space_id == 0) {
+ fprintf(stderr,
+"InnoDB: Error: tablespace id %lu in file %s is not sensible\n",
+ (ulong) space_id,
+ node->name);
+
+ ut_a(0);
+ }
+
+ if (space_id != space->id) {
+ fprintf(stderr,
+"InnoDB: Error: tablespace id is %lu in the data dictionary\n"
+"InnoDB: but in file %s it is %lu!\n", space->id, node->name, space_id);
+
+ ut_a(0);
+ }
+
if (size_bytes >= FSP_EXTENT_SIZE * UNIV_PAGE_SIZE) {
node->size = (ulint) ((size_bytes / (1024 * 1024))
* ((1024 * 1024) / UNIV_PAGE_SIZE));
@@ -2487,21 +2533,29 @@ func_exit:
}
/************************************************************************
-Tries to open a single-table tablespace and checks the space id is right in
-it. If does not succeed, prints an error message to the .err log. This
-function is used to open the tablespace when we load a table definition
-to the dictionary cache. NOTE that we assume this operation is used under the
-protection of the dictionary mutex, so that two users cannot race here. This
-operation does not leave the file associated with the tablespace open, but
-closes it after we have looked at the space id in it. */
+Tries to open a single-table tablespace and optionally checks the space id is
+right in it. If does not succeed, prints an error message to the .err log. This
+function is used to open a tablespace when we start up mysqld, and also in
+IMPORT TABLESPACE.
+NOTE that we assume this operation is used either at the database startup
+or under the protection of the dictionary mutex, so that two users cannot
+race here. This operation does not leave the file associated with the
+tablespace open, but closes it after we have looked at the space id in it. */
ibool
fil_open_single_table_tablespace(
/*=============================*/
- /* out: TRUE if success */
- ulint id, /* in: space id */
- const char* name) /* in: table name in the
- databasename/tablename format */
+ /* out: TRUE if success */
+ ibool check_space_id, /* in: should we check that the space
+ id in the file is right; we assume
+ that this function runs much faster
+ if no check is made, since accessing
+ the file inode probably is much
+ faster (the OS caches them) than
+ accessing the first page of the file */
+ ulint id, /* in: space id */
+ const char* name) /* in: table name in the
+ databasename/tablename format */
{
os_file_t file;
char* filepath;
@@ -2540,6 +2594,12 @@ fil_open_single_table_tablespace(
return(FALSE);
}
+ if (!check_space_id) {
+ space_id = id;
+
+ goto skip_check;
+ }
+
/* Read the first page of the tablespace */
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
@@ -2552,6 +2612,8 @@ fil_open_single_table_tablespace(
space_id = fsp_header_get_space_id(page);
+ ut_free(buf2);
+
if (space_id != id) {
ut_print_timestamp(stderr);
@@ -2572,6 +2634,7 @@ fil_open_single_table_tablespace(
goto func_exit;
}
+skip_check:
success = fil_space_create(filepath, space_id, FIL_TABLESPACE);
if (!success) {
@@ -2584,7 +2647,6 @@ fil_open_single_table_tablespace(
fil_node_create(filepath, 0, space_id, FALSE);
func_exit:
os_file_close(file);
- ut_free(buf2);
mem_free(filepath);
return(ret);
@@ -2651,7 +2713,7 @@ fil_load_single_table_tablespace(
fprintf(stderr,
"InnoDB: Error: could not open single-table tablespace file\n"
"InnoDB: %s!\n"
-"InnoDB: We do not continue crash recovery, because the table will become\n"
+"InnoDB: We do not continue the crash recovery, because the table may become\n"
"InnoDB: corrupt if we cannot apply the log records in the InnoDB log to it.\n"
"InnoDB: To fix the problem and start mysqld:\n"
"InnoDB: 1) If there is a permission problem in the file and mysqld cannot\n"
@@ -2822,8 +2884,9 @@ fil_load_single_table_tablespace(
goto func_exit;
}
- /* We do not measure the size of the file, that is why we pass the 0
- below */
+ /* We do not use the size information we have about the file, because
+ the rounding formulat for extents and pages is somewhat complex; we
+ let fil_node_open() do that task. */
fil_node_create(filepath, 0, space_id, FALSE);
func_exit:
diff --git a/innobase/include/dict0load.h b/innobase/include/dict0load.h
index d4dccb33373..1f0a5407140 100644
--- a/innobase/include/dict0load.h
+++ b/innobase/include/dict0load.h
@@ -18,12 +18,14 @@ Created 4/24/1996 Heikki Tuuri
In a crash recovery we already have all the tablespace objects created.
This function compares the space id information in the InnoDB data dictionary
to what we already read with fil_load_single_table_tablespaces().
-In a normal startup we just scan the biggest space id, and store it to
-fil_system. */
+
+In a normal startup, we create the tablespace objects for every table in
+InnoDB's data dictionary, if the corresponding .ibd file exists.
+We also scan the biggest space id, and store it to fil_system. */
void
-dict_check_tablespaces_or_store_max_id(
-/*===================================*/
+dict_check_tablespaces_and_store_max_id(
+/*====================================*/
ibool in_crash_recovery); /* in: are we doing a crash recovery */
/************************************************************************
Finds the first table name in the given database. */
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index 43327aab9d2..c1a127aadca 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -364,19 +364,29 @@ fil_create_new_single_table_tablespace(
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
/************************************************************************
-Tries to open a single-table tablespace and checks the space id is right in
-it. If does not succeed, prints an error message to the .err log. This
-function is used to open the tablespace when we load a table definition
-to the dictionary cache. NOTE that we assume this operation is used under the
-protection of the dictionary mutex, so that two users cannot race here. */
+Tries to open a single-table tablespace and optionally checks the space id is
+right in it. If does not succeed, prints an error message to the .err log. This
+function is used to open a tablespace when we start up mysqld, and also in
+IMPORT TABLESPACE.
+NOTE that we assume this operation is used either at the database startup
+or under the protection of the dictionary mutex, so that two users cannot
+race here. This operation does not leave the file associated with the
+tablespace open, but closes it after we have looked at the space id in it. */
ibool
fil_open_single_table_tablespace(
/*=============================*/
- /* out: TRUE if success */
- ulint id, /* in: space id */
- const char* name); /* in: table name in the
- databasename/tablename format */
+ /* out: TRUE if success */
+ ibool check_space_id, /* in: should we check that the space
+ id in the file is right; we assume
+ that this function runs much faster
+ if no check is made, since accessing
+ the file inode probably is much
+ faster (the OS caches them) than
+ accessing the first page of the file */
+ ulint id, /* in: space id */
+ const char* name); /* in: table name in the
+ databasename/tablename format */
/************************************************************************
It is possible, though very improbable, that the lsn's in the tablespace to be
imported have risen above the current system lsn, if a lengthy purge, ibuf
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index f47ce74ce37..19007069e28 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -367,25 +367,7 @@ row_drop_table_for_mysql(
/*************************************************************************
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.
-
-How do we prevent crashes caused by ongoing operations on the table? Old
-operations could try to access non-existent pages.
-
-1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock
-on the table before we can do DISCARD TABLESPACE. Then there are no running
-queries on the table.
-2) Purge and rollback: we assign a new table id for the table. Since purge and
-rollback look for the table based on the table id, they see the table as
-'dropped' and discard their operations.
-3) Insert buffer: we remove all entries for the tablespace in the insert
-buffer tree; as long as the tablespace mem object does not exist, ongoing
-insert buffer page merges are discarded in buf0rea.c. If we recreate the
-tablespace mem object with IMPORT TABLESPACE later, then the tablespace will
-have the same id, but the tablespace_version field in the mem object is
-different, and ongoing old insert buffer page merges get discarded.
-4) Linear readahead and random readahead: we use the same method as in 3) to
-discard ongoing operations. */
+the table. Also the flag table->ibd_file_missing is set TRUE. */
int
row_discard_tablespace_for_mysql(
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 7eb91048684..8336e05bdb0 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -378,6 +378,19 @@ struct trx_struct{
replication slave, this is the
position in the log file up to which
replication has processed */
+ /* A MySQL variable mysql_thd->synchronous_repl tells if we have
+ to use synchronous replication. See ha_innodb.cc. */
+ char* repl_wait_binlog_name;/* NULL, or if synchronous MySQL
+ replication is used, the binlog name
+ up to which we must communicate the
+ binlog to the slave, before returning
+ from a commit; this is the same as
+ mysql_log_file_name, but we allocate
+ and copy the name to a separate buffer
+ here */
+ ib_longlong repl_wait_binlog_pos;/* see above at
+ repl_wait_binlog_name */
+
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
with this transaction object */
ulint mysql_process_no;/* since in Linux, 'top' reports
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 6d1482b6720..f596bd3d473 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -1173,7 +1173,7 @@ run_again:
check_index = foreign->foreign_index;
}
- if (check_table == NULL) {
+ if (check_table == NULL || check_table->ibd_file_missing) {
if (check_ref) {
FILE* ef = dict_foreign_err_file;
mutex_enter(&dict_foreign_err_mutex);
@@ -1192,7 +1192,7 @@ run_again:
dtuple_print(ef, entry);
fputs("\nBut the parent table ", ef);
ut_print_name(ef, trx, foreign->referenced_table_name);
- fputs(" does not currently exist!\n", ef);
+ fputs("\nor its .ind file does not currently exist!\n", ef);
mutex_exit(&dict_foreign_err_mutex);
return(DB_NO_REFERENCED_ROW);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index dec2b19559c..3be3d3e6396 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -869,7 +869,21 @@ row_insert_for_mysql(
ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
-
+
+ if (prebuilt->table->ibd_file_missing) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error:\n"
+"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
+"InnoDB: table %s does not exist.\n"
+"InnoDB: Have you deleted the .ibd file from the database directory under\n"
+"InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
+"InnoDB: Look from\n"
+"http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
+"InnoDB: how you can resolve the problem.\n",
+ prebuilt->table->name);
+ return(DB_ERROR);
+ }
+
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
@@ -1087,6 +1101,20 @@ row_update_for_mysql(
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
UT_NOT_USED(mysql_rec);
+ if (prebuilt->table->ibd_file_missing) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error:\n"
+"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
+"InnoDB: table %s does not exist.\n"
+"InnoDB: Have you deleted the .ibd file from the database directory under\n"
+"InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
+"InnoDB: Look from\n"
+"http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
+"InnoDB: how you can resolve the problem.\n",
+ prebuilt->table->name);
+ return(DB_ERROR);
+ }
+
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
@@ -1966,9 +1994,25 @@ row_add_table_to_background_drop_list(
/*************************************************************************
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.
+the table. Also the flag table->ibd_file_missing is set TRUE. */
-How do we prevent crashes caused by ongoing operations on the table? Old
+int
+row_discard_tablespace_for_mysql(
+/*=============================*/
+ /* out: error code or DB_SUCCESS */
+ const char* name, /* in: table name */
+ trx_t* trx) /* in: transaction handle */
+{
+ dict_foreign_t* foreign;
+ dulint new_id;
+ dict_table_t* table;
+ que_thr_t* thr;
+ que_t* graph = NULL;
+ ibool success;
+ ulint err;
+ char* buf;
+
+/* How do we prevent crashes caused by ongoing operations on the table? Old
operations could try to access non-existent pages.
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock
@@ -1984,22 +2028,9 @@ tablespace mem object with IMPORT TABLESPACE later, then the tablespace will
have the same id, but the tablespace_version field in the mem object is
different, and ongoing old insert buffer page merges get discarded.
4) Linear readahead and random readahead: we use the same method as in 3) to
-discard ongoing operations. */
-
-int
-row_discard_tablespace_for_mysql(
-/*=============================*/
- /* out: error code or DB_SUCCESS */
- const char* name, /* in: table name */
- trx_t* trx) /* in: transaction handle */
-{
- dulint new_id;
- dict_table_t* table;
- que_thr_t* thr;
- que_t* graph = NULL;
- ibool success;
- ulint err;
- char* buf;
+discard ongoing operations.
+5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we
+do not allow the discard. We also reserve the data dictionary latch. */
static const char discard_tablespace_proc1[] =
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
@@ -2060,6 +2091,54 @@ row_discard_tablespace_for_mysql(
goto funct_exit;
}
+ if (table->n_foreign_key_checks_running > 0) {
+
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: You are trying to DISCARD table ", stderr);
+ ut_print_name(stderr, trx, table->name);
+ fputs("\n"
+ "InnoDB: though there is a foreign key check running on it.\n"
+ "InnoDB: Cannot discard the table.\n",
+ stderr);
+
+ err = DB_ERROR;
+
+ goto funct_exit;
+ }
+
+ /* Check if the table is referenced by foreign key constraints from
+ some other table (not the table itself) */
+
+ foreign = UT_LIST_GET_FIRST(table->referenced_list);
+
+ while (foreign && foreign->foreign_table == table) {
+ foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
+ }
+
+ if (foreign && trx->check_foreigns) {
+
+ FILE* ef = dict_foreign_err_file;
+
+ /* We only allow discarding a referenced table if
+ FOREIGN_KEY_CHECKS is set to 0 */
+
+ err = DB_CANNOT_DROP_CONSTRAINT;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ rewind(ef);
+ ut_print_timestamp(ef);
+
+ fputs(" Cannot drop table ", ef);
+ ut_print_name(ef, trx, name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(ef, trx, foreign->foreign_table_name);
+ putc('\n', ef);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ goto funct_exit;
+ }
+
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
buf = mem_alloc((sizeof discard_tablespace_proc1) +
@@ -2077,6 +2156,10 @@ row_discard_tablespace_for_mysql(
ut_a(graph);
+ /* Remove any locks there are on the table or its records */
+
+ lock_reset_all_on_table(table);
+
graph->trx = trx;
trx->graph = NULL;
@@ -2227,8 +2310,8 @@ row_import_tablespace_for_mysql(
ibuf_delete_for_discarded_space(table->space);
- success = fil_open_single_table_tablespace(table->space, table->name);
-
+ success = fil_open_single_table_tablespace(TRUE, table->space,
+ table->name);
if (success) {
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
@@ -2236,7 +2319,7 @@ row_import_tablespace_for_mysql(
if (table->ibd_file_missing) {
ut_print_timestamp(stderr);
fputs(
-" InnoDB: cannot find of open in the database directory the .ibd file of\n"
+" InnoDB: cannot find or open in the database directory the .ibd file of\n"
"InnoDB: table ", stderr);
ut_print_name(stderr, trx, name);
fputs("\n"
@@ -3284,6 +3367,20 @@ row_check_table_for_mysql(
ulint ret = DB_SUCCESS;
ulint old_isolation_level;
+ if (prebuilt->table->ibd_file_missing) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error:\n"
+"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
+"InnoDB: table %s does not exist.\n"
+"InnoDB: Have you deleted the .ibd file from the database directory under\n"
+"InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
+"InnoDB: Look from\n"
+"http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
+"InnoDB: how you can resolve the problem.\n",
+ prebuilt->table->name);
+ return(DB_ERROR);
+ }
+
prebuilt->trx->op_info = "checking table";
old_isolation_level = prebuilt->trx->isolation_level;
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index ce76f48e7a7..8cdcdd569ac 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2776,7 +2776,7 @@ row_search_for_mysql(
/* out: DB_SUCCESS,
DB_RECORD_NOT_FOUND,
DB_END_OF_INDEX, DB_DEADLOCK,
- DB_LOCK_TABLE_FULL,
+ DB_LOCK_TABLE_FULL, DB_CORRUPTION,
or DB_TOO_BIG_RECORD */
byte* buf, /* in/out: buffer for the fetched
row in the MySQL format */
@@ -2828,7 +2828,21 @@ row_search_for_mysql(
ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
-
+
+ if (prebuilt->table->ibd_file_missing) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error:\n"
+"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
+"InnoDB: table %s does not exist.\n"
+"InnoDB: Have you deleted the .ibd file from the database directory under\n"
+"InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
+"InnoDB: Look from\n"
+"http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
+"InnoDB: how you can resolve the problem.\n",
+ prebuilt->table->name);
+ return(DB_ERROR);
+ }
+
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 69341a1d7d1..c91db1f0dcc 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1378,14 +1378,39 @@ NetWare. */
return(DB_ERROR);
}
- /* Since ibuf init is in dict_boot, and ibuf is needed
- in any disk i/o, first call dict_boot */
+ /* Since the insert buffer init is in dict_boot, and the
+ insert buffer is needed in any disk i/o, first we call
+ dict_boot(). Note that trx_sys_init_at_db_start() only needs
+ to access space 0, and the insert buffer at this stage already
+ works for space 0. */
dict_boot();
trx_sys_init_at_db_start();
- /* The following needs trx lists which are initialized in
- trx_sys_init_at_db_start */
+ if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) {
+ /* The following call is necessary for the insert
+ buffer to work with multiple tablespaces. We must
+ know the mapping between space id's and .ibd file
+ names.
+
+ In a crash recovery, we check that the info in data
+ dictionary is consistent with what we already know
+ about space id's from the call of
+ fil_load_single_table_tablespaces().
+
+ In a normal startup, we create the space objects for
+ every table in the InnoDB data dictionary that has
+ an .ibd file.
+
+ We also determine the maximum tablespace id used.
+
+ TODO: We may have incomplete transactions in the
+ data dictionary tables. Does that harm the scanning of
+ the data dictionary below? */
+
+ dict_check_tablespaces_and_store_max_id(
+ recv_needed_recovery);
+ }
srv_startup_is_before_trx_rollback_phase = FALSE;
@@ -1393,6 +1418,9 @@ NetWare. */
system */
fsp_header_get_free_limit(0);
+ /* recv_recovery_from_checkpoint_finish needs trx lists which
+ are initialized in trx_sys_init_at_db_start(). */
+
recv_recovery_from_checkpoint_finish();
}
@@ -1433,13 +1461,6 @@ NetWare. */
}
}
#endif /* UNIV_LOG_ARCHIVE */
- if (!create_new_db && srv_force_recovery == 0) {
- /* After a crash recovery we only check that the info in data
- dictionary is consistent with what we already know about space
- id's from the call of fil_load_single_table_tablespaces(). */
-
- dict_check_tablespaces_or_store_max_id(recv_needed_recovery);
- }
if (srv_measure_contention) {
/* os_thread_create(&test_measure_cont, NULL, thread_ids +
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index f7497ac4090..af4f1979858 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -109,6 +109,9 @@ trx_create(
trx->mysql_log_offset = 0;
trx->mysql_master_log_file_name = "";
trx->mysql_master_log_pos = 0;
+
+ trx->repl_wait_binlog_name = NULL;
+ trx->repl_wait_binlog_pos = 0;
mutex_create(&(trx->undo_mutex));
mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO);
@@ -271,6 +274,11 @@ trx_free(
trx_undo_arr_free(trx->undo_no_arr);
}
+ if (trx->repl_wait_binlog_name != NULL) {
+
+ mem_free(trx->repl_wait_binlog_name);
+ }
+
ut_a(UT_LIST_GET_LEN(trx->signals) == 0);
ut_a(UT_LIST_GET_LEN(trx->reply_signals) == 0);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 552f2676bdd..b8ac40cee92 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4977,7 +4977,7 @@ the SQL statement in case of an error. */
int
ha_innobase::external_lock(
/*=======================*/
- /* out: 0 */
+ /* out: 0 or HA_ERR_CRASHED */
THD* thd, /* in: handle to the user thread */
int lock_type) /* in: lock type */
{
@@ -4989,19 +4989,6 @@ ha_innobase::external_lock(
update_thd(thd);
- if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB error:\n"
-"MySQL is trying to use a table handle but the .ibd file for\n"
-"table %s does not exist.\n"
-"Have you deleted the .ibd file from the database directory under\n"
-"the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
-"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
-"how you can resolve the problem.\n",
- prebuilt->table->name);
- DBUG_RETURN(HA_ERR_CRASHED);
- }
-
trx = prebuilt->trx;
prebuilt->sql_stat_start = TRUE;