mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
Applying InnoDB snapshot, fixes BUG#41609.
Detailed revision comments: r6252 | marko | 2009-11-30 12:50:11 +0200 (Mon, 30 Nov 2009) | 23 lines branches/zip: Suppress errors about non-found temporary tables. Write the is_temp flag to SYS_TABLES.MIX_LEN. dict_table_t:🎏 Add a flag for is_temporary, DICT_TF2_TEMPORARY. Unlike other flags, this will not be written to the tablespace flags or SYS_TABLES.TYPE, but only to SYS_TABLES.MIX_LEN. dict_build_table_def_step(): Only pass DICT_TF_BITS to tablespaces. dict_check_tablespaces_and_store_max_id(), dict_load_table(): Suppress errors about temporary tables not being found. dict_create_sys_tables_tuple(): Write the DICT_TF2_TEMPORARY flag to SYS_TABLES.MIX_LEN. fil_space_create(), fil_create_new_single_table_tablespace(): Add assertions about space->flags. row_drop_table_for_mysql(): Do not complain about non-found temporary tables. rb://160 approved by Heikki Tuuri. This addresses the second part of Bug #41609 Crash recovery does not work for InnoDB temporary tables.
This commit is contained in:
parent
7946d6ca45
commit
91111174ee
9 changed files with 143 additions and 50 deletions
|
@ -1,3 +1,13 @@
|
|||
2009-11-30 The InnoDB Team
|
||||
|
||||
* dict/dict0crea.c, dict/dict0mem.c, dict/dict0load.c,
|
||||
dict/dict0boot.c, fil/fil0fil.c, handler/ha_innodb.cc,
|
||||
include/dict0mem.h, row/row0mysql.c:
|
||||
Fix the bogus warning messages for non-existing temporary
|
||||
tables that were reported in
|
||||
Bug#41609 Crash recovery does not work for InnoDB temporary tables.
|
||||
The actual crash recovery bug was corrected on 2009-04-29.
|
||||
|
||||
2009-11-20 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
|
|
|
@ -274,6 +274,9 @@ dict_boot(void)
|
|||
and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
|
||||
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
|
||||
/* MIX_LEN may contain additional table flags when
|
||||
ROW_FORMAT!=REDUNDANT. Currently, these flags include
|
||||
DICT_TF2_TEMPORARY. */
|
||||
dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
|
||||
|
|
|
@ -94,13 +94,13 @@ dict_create_sys_tables_tuple(
|
|||
dfield = dtuple_get_nth_field(entry, 3);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
if (table->flags & ~DICT_TF_COMPACT) {
|
||||
if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
|
||||
ut_a(table->flags & DICT_TF_COMPACT);
|
||||
ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
|
||||
ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
|
||||
<= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
|
||||
ut_a(!(table->flags & (~0 << DICT_TF_BITS)));
|
||||
mach_write_to_4(ptr, table->flags);
|
||||
ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
|
||||
mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
|
||||
} else {
|
||||
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
|
||||
}
|
||||
|
@ -112,11 +112,12 @@ dict_create_sys_tables_tuple(
|
|||
ptr = mem_heap_zalloc(heap, 8);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
/* 7: MIX_LEN (obsolete) --------------------------*/
|
||||
/* 7: MIX_LEN (additional flags) --------------------------*/
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, 5);
|
||||
|
||||
ptr = mem_heap_zalloc(heap, 4);
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 8: CLUSTER_NAME ---------------------*/
|
||||
|
@ -230,6 +231,7 @@ dict_build_table_def_step(
|
|||
dict_table_t* table;
|
||||
dtuple_t* row;
|
||||
ulint error;
|
||||
ulint flags;
|
||||
const char* path_or_name;
|
||||
ibool is_path;
|
||||
mtr_t mtr;
|
||||
|
@ -268,9 +270,10 @@ dict_build_table_def_step(
|
|||
ut_ad(!dict_table_zip_size(table)
|
||||
|| dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
|
||||
|
||||
flags = table->flags & ~(~0 << DICT_TF_BITS);
|
||||
error = fil_create_new_single_table_tablespace(
|
||||
&space, path_or_name, is_path,
|
||||
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
|
||||
flags == DICT_TF_COMPACT ? 0 : flags,
|
||||
FIL_IBD_FILE_INITIAL_SIZE);
|
||||
table->space = (unsigned int) space;
|
||||
|
||||
|
@ -286,7 +289,7 @@ dict_build_table_def_step(
|
|||
mtr_commit(&mtr);
|
||||
} else {
|
||||
/* Create in the system tablespace: disallow new features */
|
||||
table->flags &= DICT_TF_COMPACT;
|
||||
table->flags &= (~0 << DICT_TF_BITS) | DICT_TF_COMPACT;
|
||||
}
|
||||
|
||||
row = dict_create_sys_tables_tuple(table, node->heap);
|
||||
|
|
|
@ -390,15 +390,35 @@ loop:
|
|||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (space_id != 0 && in_crash_recovery) {
|
||||
if (space_id == 0) {
|
||||
/* The system tablespace always exists. */
|
||||
} else if (in_crash_recovery) {
|
||||
/* Check that the tablespace (the .ibd file) really
|
||||
exists; print a warning to the .err log if not */
|
||||
exists; print a warning to the .err log if not.
|
||||
Do not print warnings for temporary tables. */
|
||||
ibool is_temp;
|
||||
|
||||
fil_space_for_table_exists_in_mem(space_id, name,
|
||||
FALSE, TRUE, TRUE);
|
||||
field = rec_get_nth_field_old(rec, 4, &len);
|
||||
if (0x80000000UL & mach_read_from_4(field)) {
|
||||
/* ROW_FORMAT=COMPACT: read the is_temp
|
||||
flag from SYS_TABLES.MIX_LEN. */
|
||||
field = rec_get_nth_field_old(rec, 7, &len);
|
||||
is_temp = mach_read_from_4(field)
|
||||
& DICT_TF2_TEMPORARY;
|
||||
} else {
|
||||
/* For tables created with old versions
|
||||
of InnoDB, SYS_TABLES.MIX_LEN may contain
|
||||
garbage. Such tables would always be
|
||||
in ROW_FORMAT=REDUNDANT. Pretend that
|
||||
all such tables are non-temporary. That is,
|
||||
do not suppress error printouts about
|
||||
temporary tables not being found. */
|
||||
is_temp = FALSE;
|
||||
}
|
||||
|
||||
if (space_id != 0 && !in_crash_recovery) {
|
||||
fil_space_for_table_exists_in_mem(
|
||||
space_id, name, is_temp, TRUE, !is_temp);
|
||||
} else {
|
||||
/* It is a normal database startup: create the space
|
||||
object and check that the .ibd file exists. */
|
||||
|
||||
|
@ -894,31 +914,6 @@ err_exit:
|
|||
(ulong) flags);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
|
||||
FALSE, FALSE)) {
|
||||
/* 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(
|
||||
TRUE, space, flags, name)) {
|
||||
/* We failed to find a sensible tablespace
|
||||
file */
|
||||
|
||||
ibd_file_missing = TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
flags = 0;
|
||||
}
|
||||
|
@ -928,9 +923,63 @@ err_exit:
|
|||
field = rec_get_nth_field_old(rec, 4, &len);
|
||||
n_cols = mach_read_from_4(field);
|
||||
|
||||
/* The high-order bit of N_COLS is the "compact format" flag. */
|
||||
/* The high-order bit of N_COLS is the "compact format" flag.
|
||||
For tables in that format, MIX_LEN may hold additional flags. */
|
||||
if (n_cols & 0x80000000UL) {
|
||||
ulint flags2;
|
||||
|
||||
flags |= DICT_TF_COMPACT;
|
||||
|
||||
ut_a(name_of_col_is(sys_tables, sys_index, 7, "MIX_LEN"));
|
||||
field = rec_get_nth_field_old(rec, 7, &len);
|
||||
|
||||
flags2 = mach_read_from_4(field);
|
||||
|
||||
if (flags2 & (~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Warning: table ", stderr);
|
||||
ut_print_filename(stderr, name);
|
||||
fprintf(stderr, "\n"
|
||||
"InnoDB: in InnoDB data dictionary"
|
||||
" has unknown flags %lx.\n",
|
||||
(ulong) flags2);
|
||||
|
||||
flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
|
||||
}
|
||||
|
||||
flags |= flags2 << DICT_TF2_SHIFT;
|
||||
}
|
||||
|
||||
/* See if the tablespace is available. */
|
||||
if (space == 0) {
|
||||
/* The system tablespace is always available. */
|
||||
} else if (!fil_space_for_table_exists_in_mem(
|
||||
space, name,
|
||||
(flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY,
|
||||
FALSE, FALSE)) {
|
||||
|
||||
if ((flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY) {
|
||||
/* Do not bother to retry opening temporary tables. */
|
||||
ibd_file_missing = TRUE;
|
||||
} else {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: error: space object of table");
|
||||
ut_print_filename(stderr, name);
|
||||
fprintf(stderr, ",\n"
|
||||
"InnoDB: space id %lu did not exist in memory."
|
||||
" Retrying an open.\n",
|
||||
(ulong) space);
|
||||
/* Try to open the tablespace */
|
||||
if (!fil_open_single_table_tablespace(
|
||||
TRUE, space,
|
||||
flags & ~(~0 << DICT_TF_BITS), name)) {
|
||||
/* We failed to find a sensible
|
||||
tablespace file */
|
||||
|
||||
ibd_file_missing = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
|
||||
|
|
|
@ -59,7 +59,7 @@ dict_mem_table_create(
|
|||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(name);
|
||||
ut_a(!(flags & (~0 << DICT_TF_BITS)));
|
||||
ut_a(!(flags & (~0 << DICT_TF2_BITS)));
|
||||
|
||||
heap = mem_heap_create(DICT_HEAP_SIZE);
|
||||
|
||||
|
|
|
@ -1101,6 +1101,7 @@ fil_space_create(
|
|||
ROW_FORMAT=REDUNDANT (table->flags == 0). For any other
|
||||
format, the tablespace flags should equal table->flags. */
|
||||
ut_a(flags != DICT_TF_COMPACT);
|
||||
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
|
||||
|
||||
try_again:
|
||||
/*printf(
|
||||
|
@ -2586,6 +2587,7 @@ fil_create_new_single_table_tablespace(
|
|||
ROW_FORMAT=REDUNDANT (table->flags == 0). For any other
|
||||
format, the tablespace flags should equal table->flags. */
|
||||
ut_a(flags != DICT_TF_COMPACT);
|
||||
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
|
||||
|
||||
path = fil_make_ibd_name(tablename, is_temp);
|
||||
|
||||
|
@ -2958,8 +2960,10 @@ fil_open_single_table_tablespace(
|
|||
/* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
|
||||
ROW_FORMAT=COMPACT (table->flags == DICT_TF_COMPACT) and
|
||||
ROW_FORMAT=REDUNDANT (table->flags == 0). For any other
|
||||
format, the tablespace flags should equal table->flags. */
|
||||
format, the tablespace flags should be equal to
|
||||
table->flags & ~(~0 << DICT_TF_BITS). */
|
||||
ut_a(flags != DICT_TF_COMPACT);
|
||||
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
|
||||
|
||||
file = os_file_create_simple_no_error_handling(
|
||||
filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
|
||||
|
@ -3011,7 +3015,8 @@ fil_open_single_table_tablespace(
|
|||
|
||||
ut_free(buf2);
|
||||
|
||||
if (UNIV_UNLIKELY(space_id != id || space_flags != flags)) {
|
||||
if (UNIV_UNLIKELY(space_id != id
|
||||
|| space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fputs(" InnoDB: Error: tablespace id and flags in file ",
|
||||
|
|
|
@ -6333,6 +6333,10 @@ ha_innobase::create(
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
|
||||
flags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
|
||||
}
|
||||
|
||||
error = create_table_def(trx, form, norm_name,
|
||||
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
|
||||
flags);
|
||||
|
|
|
@ -80,21 +80,39 @@ combination of types */
|
|||
/** File format */
|
||||
/* @{ */
|
||||
#define DICT_TF_FORMAT_SHIFT 5 /* file format */
|
||||
#define DICT_TF_FORMAT_MASK (127 << DICT_TF_FORMAT_SHIFT)
|
||||
#define DICT_TF_FORMAT_MASK \
|
||||
((~(~0 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT))) << DICT_TF_FORMAT_SHIFT)
|
||||
#define DICT_TF_FORMAT_51 0 /*!< InnoDB/MySQL up to 5.1 */
|
||||
#define DICT_TF_FORMAT_ZIP 1 /*!< InnoDB plugin for 5.1:
|
||||
compressed tables,
|
||||
new BLOB treatment */
|
||||
/** Maximum supported file format */
|
||||
#define DICT_TF_FORMAT_MAX DICT_TF_FORMAT_ZIP
|
||||
|
||||
/* @} */
|
||||
#define DICT_TF_BITS 6 /*!< number of flag bits */
|
||||
#if (1 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT)) <= DICT_TF_FORMAT_MAX
|
||||
# error "DICT_TF_BITS is insufficient for DICT_TF_FORMAT_MAX"
|
||||
#endif
|
||||
/* @} */
|
||||
|
||||
/** @brief Additional table flags.
|
||||
|
||||
These flags will be stored in SYS_TABLES.MIX_LEN. All unused flags
|
||||
will be written as 0. The column may contain garbage for tables
|
||||
created with old versions of InnoDB that only implemented
|
||||
ROW_FORMAT=REDUNDANT. */
|
||||
/* @{ */
|
||||
#define DICT_TF2_SHIFT DICT_TF_BITS
|
||||
/*!< Shift value for
|
||||
table->flags. */
|
||||
#define DICT_TF2_TEMPORARY 1 /*!< TRUE for tables from
|
||||
CREATE TEMPORARY TABLE. */
|
||||
#define DICT_TF2_BITS (DICT_TF2_SHIFT + 1)
|
||||
/*!< Total number of bits
|
||||
in table->flags. */
|
||||
/* @} */
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates a table memory object.
|
||||
@return own: table object */
|
||||
|
@ -374,7 +392,7 @@ struct dict_table_struct{
|
|||
unsigned space:32;
|
||||
/*!< space where the clustered index of the
|
||||
table is placed */
|
||||
unsigned flags:DICT_TF_BITS;/*!< DICT_TF_COMPACT, ... */
|
||||
unsigned flags:DICT_TF2_BITS;/*!< DICT_TF_COMPACT, ... */
|
||||
unsigned ibd_file_missing:1;
|
||||
/*!< TRUE if this is in a single-table
|
||||
tablespace and the .ibd file is missing; then
|
||||
|
|
|
@ -3264,7 +3264,7 @@ check_next_foreign:
|
|||
|
||||
ut_error;
|
||||
} else {
|
||||
ibool is_path;
|
||||
ibool is_temp;
|
||||
const char* name_or_path;
|
||||
mem_heap_t* heap;
|
||||
|
||||
|
@ -3277,12 +3277,13 @@ check_next_foreign:
|
|||
space_id = table->space;
|
||||
|
||||
if (table->dir_path_of_temp_table != NULL) {
|
||||
is_path = TRUE;
|
||||
name_or_path = mem_heap_strdup(
|
||||
heap, table->dir_path_of_temp_table);
|
||||
is_temp = TRUE;
|
||||
} else {
|
||||
is_path = FALSE;
|
||||
name_or_path = name;
|
||||
is_temp = (table->flags >> DICT_TF2_SHIFT)
|
||||
& DICT_TF2_TEMPORARY;
|
||||
}
|
||||
|
||||
dict_table_remove_from_cache(table);
|
||||
|
@ -3302,8 +3303,8 @@ check_next_foreign:
|
|||
if (err == DB_SUCCESS && space_id > 0) {
|
||||
if (!fil_space_for_table_exists_in_mem(space_id,
|
||||
name_or_path,
|
||||
is_path,
|
||||
FALSE, TRUE)) {
|
||||
is_temp, FALSE,
|
||||
!is_temp)) {
|
||||
err = DB_SUCCESS;
|
||||
|
||||
fprintf(stderr,
|
||||
|
|
Loading…
Add table
Reference in a new issue