From: vasil.dimov Date: June 23 2010 7:20am Subject: bzr commit into mysql-trunk-innodb branch (vasil.dimov:3114) Bug#47991 List-Archive: http://lists.mysql.com/commits/111858 X-Bug: 47991 Message-Id: <20100623072045.2941A2E0AC@mail.v5d.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============4471230506267084292==" --===============4471230506267084292== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///usr/local/devel/bzrroot/server/mysql-trunk-innodb/ based on revid:marko.makela@stripped 3114 Vasil Dimov 2010-06-23 Merge Bug#47991 fix from mysql-5.1-innodb ------------------------------------------------------------ revno: 3517 revision-id: vasil.dimov@stripped parent: marko.makela@stripped committer: Vasil Dimov branch nick: mysql-5.1-innodb timestamp: Tue 2010-06-22 19:30:43 +0300 message: Fix Bug#47991 InnoDB Dictionary Cache memory usage increases indefinitely when renaming tables Allocate the table name using ut_malloc() instead of table->heap because the latter cannot be freed. Adjust dict_sys->size calculations all over the code. Change dict_table_t::name from const char* to char* because we need to ut_malloc()/ut_free() it. Reviewed by: Inaam, Marko, Heikki (rb://384) Approved by: Heikki (rb://384) ------------------------------------------------------------ modified: storage/innobase/dict/dict0dict.c storage/innobase/dict/dict0mem.c storage/innobase/include/dict0mem.h storage/innobase/include/univ.i storage/innobase/page/page0zip.c storage/innobase/row/row0merge.c === modified file 'storage/innobase/dict/dict0dict.c' --- a/storage/innobase/dict/dict0dict.c revid:marko.makela@stripped +++ b/storage/innobase/dict/dict0dict.c revid:vasil.dimov@stripped @@ -864,7 +864,8 @@ dict_table_add_to_cache( /* Add table to LRU list of tables */ UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table); - dict_sys->size += mem_heap_get_size(table->heap); + dict_sys->size += mem_heap_get_size(table->heap) + + strlen(table->name) + 1; } /**********************************************************************//** @@ -918,14 +919,21 @@ dict_table_rename_in_cache( dict_foreign_t* foreign; dict_index_t* index; ulint fold; - ulint old_size; - const char* old_name; + char old_name[MAX_TABLE_NAME_LEN + 1]; ut_ad(table); ut_ad(mutex_own(&(dict_sys->mutex))); - old_size = mem_heap_get_size(table->heap); - old_name = table->name; + /* store the old/current name to an automatic variable */ + if (strlen(table->name) + 1 <= sizeof(old_name)) { + memcpy(old_name, table->name, strlen(table->name) + 1); + } else { + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: too long table name: '%s', " + "max length is %d\n", table->name, + MAX_TABLE_NAME_LEN); + ut_error; + } fold = ut_fold_string(new_name); @@ -971,12 +979,22 @@ dict_table_rename_in_cache( /* Remove table from the hash tables of tables */ HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash, ut_fold_string(old_name), table); - table->name = mem_heap_strdup(table->heap, new_name); + + if (strlen(new_name) > strlen(table->name)) { + /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid + memory fragmentation, we assume a repeated calls of + ut_realloc() with the same size do not cause fragmentation */ + ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN); + table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1); + } + memcpy(table->name, new_name, strlen(new_name) + 1); /* Add table to hash table of tables */ HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, table); - dict_sys->size += (mem_heap_get_size(table->heap) - old_size); + + dict_sys->size += strlen(new_name) - strlen(old_name); + ut_a(dict_sys->size > 0); /* Update the table_name field in indexes */ index = dict_table_get_first_index(table); @@ -1201,7 +1219,7 @@ dict_table_remove_from_cache( /* Remove table from LRU list of tables */ UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table); - size = mem_heap_get_size(table->heap); + size = mem_heap_get_size(table->heap) + strlen(table->name) + 1; ut_ad(dict_sys->size >= size); === modified file 'storage/innobase/dict/dict0mem.c' --- a/storage/innobase/dict/dict0mem.c revid:marko.makela@stripped +++ b/storage/innobase/dict/dict0mem.c revid:vasil.dimov@stripped @@ -73,7 +73,8 @@ dict_mem_table_create( table->heap = heap; table->flags = (unsigned int) flags; - table->name = mem_heap_strdup(heap, name); + table->name = ut_malloc(strlen(name) + 1); + memcpy(table->name, name, strlen(name) + 1); table->space = (unsigned int) space; table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS); @@ -112,6 +113,7 @@ dict_mem_table_free( #ifndef UNIV_HOTBACKUP mutex_free(&(table->autoinc_mutex)); #endif /* UNIV_HOTBACKUP */ + ut_free(table->name); mem_heap_free(table->heap); } === modified file 'storage/innobase/include/dict0mem.h' --- a/storage/innobase/include/dict0mem.h revid:marko.makela@stripped +++ b/storage/innobase/include/dict0mem.h revid:vasil.dimov@stripped @@ -416,7 +416,7 @@ initialized to 0, NULL or FALSE in dict_ struct dict_table_struct{ dulint id; /*!< id of the table */ mem_heap_t* heap; /*!< memory heap */ - const char* name; /*!< table name */ + char* name; /*!< table name */ const char* dir_path_of_temp_table;/*!< NULL or the directory path where a TEMPORARY table that was explicitly created by a user should be placed if === modified file 'storage/innobase/include/univ.i' --- a/storage/innobase/include/univ.i revid:marko.makela@stripped +++ b/storage/innobase/include/univ.i revid:vasil.dimov@stripped @@ -310,6 +310,12 @@ management to ensure correct alignment f /* Maximum number of parallel threads in a parallelized operation */ #define UNIV_MAX_PARALLELISM 32 +/* The maximum length of a table name. This is the MySQL limit and is +defined in mysql_com.h like NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN, the +number does not include a terminating '\0'. InnoDB probably can handle +longer names internally */ +#define MAX_TABLE_NAME_LEN 192 + /* UNIVERSAL TYPE DEFINITIONS ========================== === modified file 'storage/innobase/page/page0zip.c' --- a/storage/innobase/page/page0zip.c revid:marko.makela@stripped +++ b/storage/innobase/page/page0zip.c revid:vasil.dimov@stripped @@ -1464,6 +1464,7 @@ page_zip_fields_free( dict_table_t* table = index->table; mem_heap_free(index->heap); mutex_free(&(table->autoinc_mutex)); + ut_free(table->name); mem_heap_free(table->heap); } } === modified file 'storage/innobase/row/row0merge.c' --- a/storage/innobase/row/row0merge.c revid:marko.makela@stripped +++ b/storage/innobase/row/row0merge.c revid:vasil.dimov@stripped @@ -2357,7 +2357,7 @@ row_merge_rename_tables( { ulint err = DB_ERROR; pars_info_t* info; - const char* old_name= old_table->name; + char old_name[MAX_TABLE_NAME_LEN + 1]; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(old_table != new_table); @@ -2365,6 +2365,17 @@ row_merge_rename_tables( ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); + /* store the old/current name to an automatic variable */ + if (strlen(old_table->name) + 1 <= sizeof(old_name)) { + memcpy(old_name, old_table->name, strlen(old_table->name) + 1); + } else { + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: too long table name: '%s', " + "max length is %d\n", old_table->name, + MAX_TABLE_NAME_LEN); + ut_error; + } + trx->op_info = "renaming tables"; /* We use the private SQL parser of Innobase to generate the query --===============4471230506267084292== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/vasil.dimov@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: vasil.dimov@stripped # target_branch: file:///usr/local/devel/bzrroot/server/mysql-trunk-\ # innodb/ # testament_sha1: 1c8eee47f93e1ba6e0e216503d793dd265e4d03e # timestamp: 2010-06-23 10:20:45 +0300 # source_branch: file:///usr/local/devel/bzrroot/server/mysql-trunk-\ # bugfixing/ # base_revision_id: marko.makela@stripped\ # yki7l4uo5kw0fu6e # # Begin bundle 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 u5IpwoSHlFEb+A== --===============4471230506267084292==--