diff options
author | unknown <aivanov@mysql.com> | 2006-01-31 21:41:48 +0300 |
---|---|---|
committer | unknown <aivanov@mysql.com> | 2006-01-31 21:41:48 +0300 |
commit | 6a9a96dc61613ba16e7f87e3681709c2f0e8f580 (patch) | |
tree | 9e475e84c7ce72ff8bc4402d9ee012a703984545 /innobase | |
parent | 107ad3a03e2b76da117bc05624e807d9936fe73f (diff) | |
download | mariadb-git-6a9a96dc61613ba16e7f87e3681709c2f0e8f580.tar.gz |
Fixed: BUG#15653, BUG#16157, BUG#16229, BUG#16298, BUG#16387, BUG#16582.
Applied innodb-5.0-ss149/162 snapshots.
innobase/btr/btr0sea.c:
Applied innodb-5.0-149/162 snapshots.
Account for a race condition when dropping the adaptive hash
index for a B-tree page (Bug #16582).
btr_search_drop_page_hash_index(): Retry the operation if a
hash index with different parameters was built meanwhile.
Add diagnostics for the case that hash node pointers to
the page remain. This fix is from Heikki.
btr_search_info-update_hash(), btr_search_info_update_slow():
Document the parameter "info" as in/out.
innobase/dict/dict0dict.c:
Applied innodb-5.0-149/162 snapshots.
Do not mistake TABLENAME_ibfk_0 for auto generated id (Bug #16387).
dict_table_get_highest_foreign_id(): Ignore foreign constraint
identifiers starting with the pattern TABLENAME_ibfk_0.
innobase/dict/dict0load.c:
Applied innodb-5.0-149/162 snapshots.
dict_load_columns(): Set the charset-collation code
DATA_MYSQL_BINARY_CHARSET_COLL for those binary string columns
that lack a charset-collation code, i.e., the tables were created
with an older version of MySQL/InnoDB than 4.1.2 (Bug #16298).
innobase/fil/fil0fil.c:
Applied innodb-5.0-149/162 snapshots.
Keep track on unflushed modifications to file spaces. When there
are tens of thousands of file spaces, flushing all files in
fil_flush_file_spaces() would be very slow (Bug #15653).
fil_flush_file_spaces(): Only flush unflushed file spaces.
fil_space_t, fil_system_t: Add a list of unflushed spaces.
innobase/include/univ.i:
Applied innodb-5.0-149/162 snapshots.
Avoid breaking --with-debug builds on QNS and other systems
whose compiler pretends to be GCC 2.
Outside __WIN__ define UNIV_INLINE as static inline.
innobase/os/os0sync.c:
Applied innodb-5.0-149/162 snapshots.
Replace goto in os_event_wait with a normal loop.
innobase/srv/srv0start.c:
Applied innodb-5.0-149/162 snapshots.
Fix bug #16157, a crash when innodb_log_group_home_dir is set
to an empty string. This patch is from Heikki.
mysql-test/r/innodb.result:
Applied innodb-5.0-149/162 snapshots.
Fixed results for added test cases.
mysql-test/t/innodb.test:
Applied innodb-5.0-149/162 snapshots.
Added test cases.
sql/ha_innodb.cc:
Applied innodb-5.0-149/162 snapshots.
Remove some declarations of unused global variables and member
variables of class ha_innobase.
Added diagnostic code trx_print() to
innobase_query_caching_of_table_permitted() to find reason
why we are holding adaptive search latch.
Fixed bug #16229 MySQL/InnoDB uses full explicit table locks
in trigger processing. Take a InnoDB table lock only if user
has explicitly requested a table lock. Added some additional
comments to store_lock() and external_lock(). Fixed some
code style errors.
Remember to use noninlined versions of the functions on
ha_innodb.cc !
sql/ha_innodb.h:
Applied innodb-5.0-149/162 snapshots.
Remove some declarations of unused global variables and member
variables of class ha_innobase.
Diffstat (limited to 'innobase')
-rw-r--r-- | innobase/btr/btr0sea.c | 44 | ||||
-rw-r--r-- | innobase/dict/dict0dict.c | 3 | ||||
-rw-r--r-- | innobase/dict/dict0load.c | 20 | ||||
-rw-r--r-- | innobase/fil/fil0fil.c | 83 | ||||
-rw-r--r-- | innobase/include/univ.i | 6 | ||||
-rw-r--r-- | innobase/os/os0sync.c | 30 | ||||
-rw-r--r-- | innobase/srv/srv0start.c | 14 |
7 files changed, 166 insertions, 34 deletions
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 81f23cfa99c..32e22aa51bc 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -191,7 +191,7 @@ static void btr_search_info_update_hash( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor) /* in: cursor which was just positioned */ { dict_index_t* index; @@ -452,7 +452,7 @@ Updates the search info. */ void btr_search_info_update_slow( /*========================*/ - btr_search_t* info, /* in: search info */ + btr_search_t* info, /* in/out: search info */ btr_cur_t* cursor) /* in: cursor which was just positioned */ { buf_block_t* block; @@ -912,12 +912,12 @@ btr_search_drop_page_hash_index( ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - +retry: rw_lock_s_lock(&btr_search_latch); block = buf_block_align(page); - if (!block->is_hashed) { + if (UNIV_LIKELY(!block->is_hashed)) { rw_lock_s_unlock(&btr_search_latch); @@ -958,6 +958,8 @@ btr_search_drop_page_hash_index( tree_id = btr_page_get_index_id(page); + ut_a(0 == ut_dulint_cmp(tree_id, index->id)); + prev_fold = 0; heap = NULL; @@ -992,6 +994,26 @@ next_rec: rw_lock_x_lock(&btr_search_latch); + if (UNIV_UNLIKELY(!block->is_hashed)) { + /* Someone else has meanwhile dropped the hash index */ + + goto cleanup; + } + + ut_a(block->index == index); + + if (UNIV_UNLIKELY(block->curr_n_fields != n_fields) + || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) { + + /* Someone else has meanwhile built a new hash index on the + page, with different parameters */ + + rw_lock_x_unlock(&btr_search_latch); + + mem_free(folds); + goto retry; + } + for (i = 0; i < n_cached; i++) { ha_remove_all_nodes_to_page(table, folds[i], page); @@ -999,8 +1021,20 @@ next_rec: block->is_hashed = FALSE; block->index = NULL; +cleanup: + if (UNIV_UNLIKELY(block->n_pointers)) { + /* Corruption */ + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Corruption of adaptive hash index. After dropping\n" +"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n", + index->name, (ulong) block->n_pointers); + rw_lock_x_unlock(&btr_search_latch); - rw_lock_x_unlock(&btr_search_latch); + btr_search_validate(); + } else { + rw_lock_x_unlock(&btr_search_latch); + } mem_free(folds); } diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 8050eebddd8..58c4e3ed6a3 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2803,7 +2803,8 @@ dict_table_get_highest_foreign_id( if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len && 0 == ut_memcmp(foreign->id, table->name, len) && 0 == ut_memcmp(foreign->id + len, - dict_ibfk, (sizeof dict_ibfk) - 1)) { + dict_ibfk, (sizeof dict_ibfk) - 1) + && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') { /* It is of the >= 4.0.18 format */ id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1), diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 3281f9926f9..6415cc56b61 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -385,13 +385,23 @@ dict_load_columns( field = rec_get_nth_field_old(rec, 6, &len); prtype = mach_read_from_4(field); - if (dtype_is_non_binary_string_type(mtype, prtype) - && dtype_get_charset_coll(prtype) == 0) { - /* This is a non-binary string type, and the table - was created with < 4.1.2. Use the default charset. */ + if (dtype_get_charset_coll(prtype) == 0 + && dtype_is_string_type(mtype)) { + /* The table was created with < 4.1.2. */ - prtype = dtype_form_prtype(prtype, + if (dtype_is_binary_string_type(mtype, prtype)) { + /* Use the binary collation for + string columns of binary type. */ + + prtype = dtype_form_prtype(prtype, + DATA_MYSQL_BINARY_CHARSET_COLL); + } else { + /* Use the default charset for + other than binary columns. */ + + prtype = dtype_form_prtype(prtype, data_mysql_default_charset_coll); + } } field = rec_get_nth_field_old(rec, 7, &len); diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 20f522c1a60..69c076d78f3 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -181,6 +181,11 @@ struct fil_space_struct { hash_node_t name_hash;/* hash chain the name_hash table */ rw_lock_t latch; /* latch protecting the file space storage allocation */ + UT_LIST_NODE_T(fil_space_t) unflushed_spaces; + /* list of spaces with at least one unflushed + file we have written to */ + ibool is_in_unflushed_spaces; /* TRUE if this space is + currently in the list above */ UT_LIST_NODE_T(fil_space_t) space_list; /* list of all spaces */ ibuf_data_t* ibuf_data; @@ -213,6 +218,12 @@ struct fil_system_struct { not put to this list: they are opened after the startup, and kept open until shutdown */ + UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces; + /* base node for the list of those + tablespaces whose files contain + unflushed writes; those spaces have + at least one file node where + modification_counter > flush_counter */ ulint n_open; /* number of files currently open */ ulint max_n_open; /* n_open is not allowed to exceed this */ @@ -389,6 +400,36 @@ fil_space_get_ibuf_data( return(space->ibuf_data); } +/************************************************************************** +Checks if all the file nodes in a space are flushed. The caller must hold +the fil_system mutex. */ +static +ibool +fil_space_is_flushed( +/*=================*/ + /* out: TRUE if all are flushed */ + fil_space_t* space) /* in: space */ +{ + fil_node_t* node; + +#ifdef UNIV_SYNC_DEBUG + ut_ad(mutex_own(&(fil_system->mutex))); +#endif /* UNIV_SYNC_DEBUG */ + + node = UT_LIST_GET_FIRST(space->chain); + + while (node) { + if (node->modification_counter > node->flush_counter) { + + return(FALSE); + } + + node = UT_LIST_GET_NEXT(chain, node); + } + + return(TRUE); +} + /*********************************************************************** Appends a new file to the chain of files of a space. File must be closed. */ @@ -841,6 +882,16 @@ fil_node_free( node->modification_counter = node->flush_counter; + if (space->is_in_unflushed_spaces + && fil_space_is_flushed(space)) { + + space->is_in_unflushed_spaces = FALSE; + + UT_LIST_REMOVE(unflushed_spaces, + system->unflushed_spaces, + space); + } + fil_node_close_file(node, system); } @@ -1004,6 +1055,8 @@ try_again: HASH_INSERT(fil_space_t, name_hash, system->name_hash, ut_fold_string(name), space); + space->is_in_unflushed_spaces = FALSE; + UT_LIST_ADD_LAST(space_list, system->space_list, space); mutex_exit(&(system->mutex)); @@ -1099,6 +1152,13 @@ fil_space_free( HASH_DELETE(fil_space_t, name_hash, system->name_hash, ut_fold_string(space->name), space); + if (space->is_in_unflushed_spaces) { + space->is_in_unflushed_spaces = FALSE; + + UT_LIST_REMOVE(unflushed_spaces, system->unflushed_spaces, + space); + } + UT_LIST_REMOVE(space_list, system->space_list, space); ut_a(space->magic_n == FIL_SPACE_MAGIC_N); @@ -1250,6 +1310,7 @@ fil_system_create( system->tablespace_version = 0; + UT_LIST_INIT(system->unflushed_spaces); UT_LIST_INIT(system->space_list); return(system); @@ -3742,6 +3803,14 @@ fil_node_complete_io( if (type == OS_FILE_WRITE) { system->modification_counter++; node->modification_counter = system->modification_counter; + + if (!node->space->is_in_unflushed_spaces) { + + node->space->is_in_unflushed_spaces = TRUE; + UT_LIST_ADD_FIRST(unflushed_spaces, + system->unflushed_spaces, + node->space); + } } if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE @@ -4162,6 +4231,16 @@ retry: skip_flush: if (node->flush_counter < old_mod_counter) { node->flush_counter = old_mod_counter; + + if (space->is_in_unflushed_spaces + && fil_space_is_flushed(space)) { + + space->is_in_unflushed_spaces = FALSE; + + UT_LIST_REMOVE(unflushed_spaces, + system->unflushed_spaces, + space); + } } if (space->purpose == FIL_TABLESPACE) { @@ -4193,7 +4272,7 @@ fil_flush_file_spaces( mutex_enter(&(system->mutex)); - space = UT_LIST_GET_FIRST(system->space_list); + space = UT_LIST_GET_FIRST(system->unflushed_spaces); while (space) { if (space->purpose == purpose && !space->is_being_deleted) { @@ -4209,7 +4288,7 @@ fil_flush_file_spaces( space->n_pending_flushes--; } - space = UT_LIST_GET_NEXT(space_list, space); + space = UT_LIST_GET_NEXT(unflushed_spaces, space); } mutex_exit(&(system->mutex)); diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 15650f22ed8..dd4862b3808 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -126,14 +126,8 @@ by one. */ #ifdef __WIN__ #define UNIV_INLINE __inline #else -/* config.h contains the right def for 'inline' for the current compiler */ -#if (__GNUC__ == 2) -#define UNIV_INLINE extern inline -#else -/* extern inline doesn't work with gcc 3.0.2 */ #define UNIV_INLINE static inline #endif -#endif #else /* If we want to compile a noninlined version we use the following macro diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 487e8f40a39..8bafb73baf8 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -317,28 +317,28 @@ os_event_wait( os_fast_mutex_lock(&(event->os_mutex)); old_signal_count = event->signal_count; -loop: - if (event->is_set == TRUE - || event->signal_count != old_signal_count) { - os_fast_mutex_unlock(&(event->os_mutex)); + for (;;) { + if (event->is_set == TRUE + || event->signal_count != old_signal_count) { - if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + os_fast_mutex_unlock(&(event->os_mutex)); - os_thread_exit(NULL); - } - /* Ok, we may return */ + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { - return; - } + os_thread_exit(NULL); + } + /* Ok, we may return */ - pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); + return; + } - /* Solaris manual said that spurious wakeups may occur: we have to - check if the event really has been signaled after we came here to - wait */ + pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); - goto loop; + /* Solaris manual said that spurious wakeups may occur: we + have to check if the event really has been signaled after + we came here to wait */ + } #endif } diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 4f99f340e1c..b345a27af20 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -233,6 +233,13 @@ srv_parse_data_file_paths_and_sizes( } } + if (i == 0) { + /* If innodb_data_file_path was defined it must contain + at least one data file definition */ + + return(FALSE); + } + *data_file_names = (char**)ut_malloc(i * sizeof(void*)); *data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint)); *data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint)); @@ -379,6 +386,13 @@ srv_parse_log_group_home_dirs( } } + if (i != 1) { + /* If innodb_log_group_home_dir was defined it must + contain exactly one path definition under current MySQL */ + + return(FALSE); + } + *log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*)); /* Then store the actual values to our array */ |