Commit 31143f1c authored by Sergey Vojtovich's avatar Sergey Vojtovich

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::flags: 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.
parent c29c9d93
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 @@ dict_check_tablespaces_and_store_max_id(
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 */
fil_space_for_table_exists_in_mem(space_id, name,
FALSE, TRUE, TRUE);
}
exists; print a warning to the .err log if not.
Do not print warnings for temporary tables. */
ibool is_temp;
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,43 +914,72 @@ dict_load_table(
(ulong) flags);
goto err_exit;
}
} else {
flags = 0;
}
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_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
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.
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 %s,\n"
" 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",
name, (ulong)space);
(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 */
TRUE, space,
flags & ~(~0 << DICT_TF_BITS), name)) {
/* We failed to find a sensible
tablespace file */
ibd_file_missing = TRUE;
}
}
} else {
flags = 0;
}
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
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. */
if (n_cols & 0x80000000UL) {
flags |= DICT_TF_COMPACT;
}
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 @@ row_drop_table_for_mysql(
ut_error;
} else {
ibool is_path;
ibool is_temp;
const char* name_or_path;
mem_heap_t* heap;
......@@ -3277,12 +3277,13 @@ row_drop_table_for_mysql(
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 @@ row_drop_table_for_mysql(
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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment