summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <aivanov@mysql.com>2006-01-31 21:41:48 +0300
committerunknown <aivanov@mysql.com>2006-01-31 21:41:48 +0300
commit6a9a96dc61613ba16e7f87e3681709c2f0e8f580 (patch)
tree9e475e84c7ce72ff8bc4402d9ee012a703984545 /innobase
parent107ad3a03e2b76da117bc05624e807d9936fe73f (diff)
downloadmariadb-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.c44
-rw-r--r--innobase/dict/dict0dict.c3
-rw-r--r--innobase/dict/dict0load.c20
-rw-r--r--innobase/fil/fil0fil.c83
-rw-r--r--innobase/include/univ.i6
-rw-r--r--innobase/os/os0sync.c30
-rw-r--r--innobase/srv/srv0start.c14
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 */