From: Date: January 30 2006 8:33pm Subject: bk commit into 4.1 tree (aivanov:1.2454) BUG#16582 List-Archive: http://lists.mysql.com/commits/1889 X-Bug: 16582 Message-Id: Below is the list of changes that have just been committed into a local 4.1 repository of alexi. When alexi does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2454 06/01/30 22:33:02 aivanov@stripped +3 -0 Fixed BUG#15653, BUG#16582. Applied innodb-4.1-ss20 snapshot. innobase/include/btr0sea.ic 1.3 06/01/30 22:32:59 aivanov@stripped +1 -1 Applied innodb-4.1-ss20 snapshot. btr_search_info_update_hash(), btr_search_info_update_slow(): Document the parameter "info" as in/out. innobase/fil/fil0fil.c 1.54 06/01/30 22:32:59 aivanov@stripped +91 -12 Applied innodb-4.1-ss20 snapshot. Keep track on unflushed modifications to file spaces. When there are tens of thousnads of file spaces, flushing all files in fil_flush_file_spaces() would be very slow (Bug #16582). fil_flush_file_spaces(): Only flush unflushed file spaces. fil_space_t, fil_system_t: Add a list of unflushed spaces. innobase/btr/btr0sea.c 1.23 06/01/30 22:32:59 aivanov@stripped +37 -4 Applied innodb-4.1-ss20 snapshot. 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. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: aivanov # Host: mysqld.creware.com # Root: /home/alexi/innodb/mysql-4.1-ss20 --- 1.22/innobase/btr/btr0sea.c 2004-05-14 17:06:15 +04:00 +++ 1.23/innobase/btr/btr0sea.c 2006-01-30 22:32:59 +03:00 @@ -191,7 +191,7 @@ 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; @@ -443,7 +443,7 @@ 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; @@ -931,7 +931,7 @@ 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); @@ -1007,6 +1007,24 @@ rw_lock_x_lock(&btr_search_latch); + if (!block->is_hashed) { + /* Someone else has meanwhile dropped the hash index */ + + goto cleanup; + } + + if (block->curr_n_fields != n_fields + || 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); @@ -1014,7 +1032,22 @@ block->is_hashed = FALSE; - rw_lock_x_unlock(&btr_search_latch); +cleanup: + if (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 %lu %lu, still %lu hash nodes remain.\n", + (ulong) ut_dulint_get_high(tree_id), + (ulong) ut_dulint_get_low(tree_id), + (ulong) block->n_pointers); + rw_lock_x_unlock(&btr_search_latch); + + btr_search_validate(); + } else { + rw_lock_x_unlock(&btr_search_latch); + } mem_free(folds); } --- 1.53/innobase/fil/fil0fil.c 2005-06-27 18:04:51 +04:00 +++ 1.54/innobase/fil/fil0fil.c 2006-01-30 22:32:59 +03:00 @@ -179,6 +179,11 @@ 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; @@ -211,6 +216,12 @@ 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 */ @@ -387,6 +398,36 @@ 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. */ @@ -517,7 +558,7 @@ 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, +"InnoDB: is only %lu %lu, should be at least %lu!\n", node->name, (ulong) size_high, (ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE)); @@ -687,8 +728,8 @@ ut_print_filename(stderr, node->name); fprintf(stderr, ", because mod_count %ld != fl_count %ld\n", - (ulong) node->modification_counter, - (ulong) node->flush_counter); + (long) node->modification_counter, + (long) node->flush_counter); } node = UT_LIST_GET_PREV(LRU, node); @@ -839,6 +880,16 @@ 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); } @@ -1002,6 +1053,8 @@ 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)); @@ -1097,6 +1150,13 @@ 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); @@ -1248,6 +1308,7 @@ system->tablespace_version = 0; + UT_LIST_INIT(system->unflushed_spaces); UT_LIST_INIT(system->space_list); return(system); @@ -2612,12 +2673,12 @@ fputs("!\n" "InnoDB: Have you moved InnoDB .ibd files around without using the\n" "InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n" -"InnoDB: It is also possible that this is a table created with\n" -"InnoDB: CREATE TEMPORARY TABLE, and MySQL removed the .ibd file for this.\n" +"InnoDB: It is also possible that this is a temporary table #sql...,\n" +"InnoDB: and MySQL removed the .ibd file for this.\n" "InnoDB: Please refer to\n" "InnoDB:" " http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n" -"InnoDB: how to resolve the issue.\n", stderr); +"InnoDB: for how to resolve the issue.\n", stderr); mem_free(filepath); @@ -2657,7 +2718,7 @@ "InnoDB: Please refer to\n" "InnoDB:" " http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n" -"InnoDB: how to resolve the issue.\n", (ulong) space_id, (ulong) id); +"InnoDB: for how to resolve the issue.\n", (ulong) space_id, (ulong) id); ret = FALSE; @@ -3292,7 +3353,7 @@ ut_print_filename(stderr, name); fprintf(stderr, "\n" "InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" -"InnoDB: but tablespace with that id does not exist. There is\n" +"InnoDB: but a tablespace with that id does not exist. There is\n" "InnoDB: a tablespace of name %s and id %lu, though. Have\n" "InnoDB: you deleted or moved .ibd files?\n", (ulong) id, namespace->name, @@ -3303,7 +3364,7 @@ "InnoDB: Please refer to\n" "InnoDB:" " http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n" -"InnoDB: how to resolve the issue.\n", stderr); +"InnoDB: for how to resolve the issue.\n", stderr); mem_free(path); mutex_exit(&(system->mutex)); @@ -3317,7 +3378,7 @@ ut_print_filename(stderr, name); fprintf(stderr, "\n" "InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" -"InnoDB: but tablespace with that id has name %s.\n" +"InnoDB: but the tablespace with that id has name %s.\n" "InnoDB: Have you deleted or moved .ibd files?\n", (ulong) id, space->name); if (namespace != NULL) { @@ -3732,6 +3793,14 @@ 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 @@ -4145,6 +4214,16 @@ 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) { @@ -4176,7 +4255,7 @@ 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) { @@ -4192,7 +4271,7 @@ space->n_pending_flushes--; } - space = UT_LIST_GET_NEXT(space_list, space); + space = UT_LIST_GET_NEXT(unflushed_spaces, space); } mutex_exit(&(system->mutex)); --- 1.2/innobase/include/btr0sea.ic 2004-03-12 18:13:10 +03:00 +++ 1.3/innobase/include/btr0sea.ic 2006-01-30 22:32:59 +03:00 @@ -16,7 +16,7 @@ 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 */ /************************************************************************