From: Dmitry Lenev Date: April 1 2011 8:00pm Subject: bzr commit into mysql-trunk branch (Dmitry.Lenev:3535) Bug#11746602 List-Archive: http://lists.mysql.com/commits/134502 X-Bug: 11746602 Message-Id: <20110401200043.219CA7405D1@bandersnatch> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1356203172==" --===============1356203172== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/dlenev/src/bzr/mysql-trunk-bug27480-key/ based on revid:dmitry.lenev@stripped 3535 Dmitry Lenev 2011-04-02 Yet another follow-up for the patch for Bug#11746602 27480: Extend CREATE TEMPORARY TABLES privilege to allow temp table operations). This patch tries to eliminate performance overhead which was introduced by one of previous patches for this bug. One of those patches added pre-opening of temporary tables as a separate stage of statement execution, handled by a separate call to open_temporary_tables(). As result we started to construct table definition key twice per statement almost for each table to be open by statement. This patch addresses the issue by changing code to avoid construction of keys and borrowing pre-constructed key from TABLE_LIST::mdl_request::key instead, where it is possible. @ sql/sql_admin.cc Adjusted prepare_for_repair() code to use get_table_def_key() instead of create_table_def_key() to get table definition cache key (the former piggy-backs on pre-constructed TABLE_LIST::mdl_request::key instead of constructing new instance of key like the latter). @ sql/sql_base.cc - Introduced get_table_def_key() function which allows to get table definition cache key for the table list element cheaply, by piggy-backing on pre-constructed TABLE_LIST::mdl_request::key. Adjusted code to use this function instead of create_table_def_key(), which constructs new instance of key, where possible. - Made create_table_def_key() private to sql_base.cc as it is no longer used outside of this file. Also changed it to accept database and table name instead of table list element since now it is only used in cases when table list element is not easily available. Changed some code which specifically constructed temporary TABLE_LIST objects to call create_table_def_key() to not to do this. - Changed find_temporary_table(TABLE_LIST) to use key borrowed from TABLE_LIST::mdl_request::key instead of especially constructed key. This change allows us to save on key construction but adds a small overhead during key comparison. Such a trade-off should be acceptable as overhead during key comparison is only a few instructions. - Signatures of get_table_share/get_table_share_with_discover() and tdc_open_view() were changed to accept constant table definition key to allow them to be used in cases when keys were borrowed from MDL subsystem. @ sql/sql_base.h - Introduced get_table_def_key() function which allows to get table definition cache key for the table list element cheaply, by piggy-backing on pre-constructed TABLE_LIST::mdl_request::key. key, where possible. - Made create_table_def_key() private to sql_base.cc as it is no longer used outside of this file. - Signatures of get_table_share/get_table_share_with_discover() and tdc_open_view() were changed to accept constant table definition key to allow them to be used in cases when keys were borrowed from MDL subsystem. @ sql/sql_show.cc Adjusted fill_schema_table_from_frm() code to use get_table_def_key() instead of create_table_def_key() to get table definition cache key (the former piggy-backs on pre-constructed TABLE_LIST::mdl_request::key instead of constructing new instance of key like the latter). @ sql/sql_table.cc Changed two places in mysql_alter_table() code where we tried to open tables using table list element objects which were not fully/correctly initialized and which, therefore, were impossible to use to get table definition cache key from them. @ sql/sql_view.cc Adjusted fill_defined_view_parts() code to use get_table_def_key() instead of create_table_def_key() to get table definition cache key (the former piggy-backs on pre-constructed TABLE_LIST::mdl_request::key instead of constructing new instance of key like the latter). @ sql/table.cc Changed signature of alloc_table_share() to accept constant table definition key to allow it to be used in cases when key is borrowed from MDL subsystem. @ sql/table.h Changed signature of alloc_table_share() to accept constant table definition key to allow it to be used in cases when key is borrowed from MDL subsystem. modified: sql/sql_admin.cc sql/sql_base.cc sql/sql_base.h sql/sql_show.cc sql/sql_table.cc sql/sql_view.cc sql/table.cc sql/table.h === modified file 'sql/sql_admin.cc' --- a/sql/sql_admin.cc 2011-03-09 12:24:36 +0000 +++ b/sql/sql_admin.cc 2011-04-01 20:00:35 +0000 @@ -65,7 +65,7 @@ static int prepare_for_repair(THD *thd, if (!(table= table_list->table)) { - char key[MAX_DBKEY_LENGTH]; + const char *key; uint key_length; /* If the table didn't exist, we have a shared metadata lock @@ -81,7 +81,6 @@ static int prepare_for_repair(THD *thd, */ my_hash_value_type hash_value; - key_length= create_table_def_key(thd, key, table_list, 0); table_list->mdl_request.init(MDL_key::TABLE, table_list->db, table_list->table_name, MDL_EXCLUSIVE, MDL_TRANSACTION); @@ -91,6 +90,8 @@ static int prepare_for_repair(THD *thd, DBUG_RETURN(0); has_mdl_lock= TRUE; + key_length= get_table_def_key(table_list, &key); + hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); share= get_table_share(thd, table_list, key, key_length, 0, === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2011-04-01 18:08:48 +0000 +++ b/sql/sql_base.cc 2011-04-01 20:00:35 +0000 @@ -222,17 +222,17 @@ static void check_unused(void) #endif -/* +/** Create a table cache key - SYNOPSIS - create_table_def_key() - thd Thread handler - key Create key here (must be of size MAX_DBKEY_LENGTH) - table_list Table definition - tmp_table Set if table is a tmp table + @param thd Thread context + @param key Buffer for the key to be created (must be of + size MAX_DBKEY_LENGTH). + @param db_name Database name. + @param table_name Table name. + @param tmp_table Set if table is a tmp table. - IMPLEMENTATION + @note The table cache_key is created from: db_name + \0 table_name + \0 @@ -243,16 +243,15 @@ static void check_unused(void) 4 bytes for master thread id 4 bytes pseudo thread id - RETURN - Length of key + @return Length of key. */ -uint create_table_def_key(THD *thd, char *key, - const TABLE_LIST *table_list, - bool tmp_table) +static uint create_table_def_key(THD *thd, char *key, + const char *db_name, const char *table_name, + bool tmp_table) { - uint key_length= (uint) (strmov(strmov(key, table_list->db)+1, - table_list->table_name)-key)+1; + uint key_length= (uint) (strmov(strmov(key, db_name) + 1, table_name) - + key) + 1; if (tmp_table) { int4store(key + key_length, thd->server_id); @@ -263,6 +262,41 @@ uint create_table_def_key(THD *thd, char } +/** + Get table cache key for a table list element. + + @param table_list[in] Table list element. + @param key[out] On return points to table cache key for the table. + + @note Unlike create_table_def_key() call this function doesn't construct + key in a buffer provider by caller. Instead it relies on the fact + that table list element for which key is requested has properly + initialized MDL_request object and the fact that table definition + cache key is suffix of key used in MDL subsystem. So to get table + definition key it simply needs to return pointer to appropriate + part of MDL_key object nested in this table list element. + Indeed, this means that lifetime of key produced by this call is + limited by the lifetime of table list element which it got as + parameter. + + @return Length of key. +*/ + +uint get_table_def_key(const TABLE_LIST *table_list, const char **key) +{ + /* + This call relies on the fact that TABLE_LIST::mdl_request::key object + is properly initialized, so table definition cache can be produced + from key used by MDL subsystem. + */ + DBUG_ASSERT(!strcmp(table_list->db, table_list->mdl_request.key.db_name()) && + !strcmp(table_list->table_name, table_list->mdl_request.key.name())); + + *key= (const char*)table_list->mdl_request.key.ptr() + 1; + return table_list->mdl_request.key.length() - 1; +} + + /***************************************************************************** Functions to handle table definition cach (TABLE_SHARE) @@ -494,8 +528,9 @@ static void table_def_unuse_table(TABLE # Share for table */ -TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, - uint key_length, uint db_flags, int *error, +TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, + const char *key, uint key_length, + uint db_flags, int *error, my_hash_value_type hash_value) { TABLE_SHARE *share; @@ -610,7 +645,7 @@ found: static TABLE_SHARE * get_table_share_with_discover(THD *thd, TABLE_LIST *table_list, - char *key, uint key_length, + const char *key, uint key_length, uint db_flags, int *error, my_hash_value_type hash_value) @@ -755,14 +790,11 @@ void release_table_share(TABLE_SHARE *sh TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) { - char key[NAME_LEN*2+2]; - TABLE_LIST table_list; + char key[MAX_DBKEY_LENGTH]; uint key_length; mysql_mutex_assert_owner(&LOCK_open); - table_list.db= (char*) db; - table_list.table_name= (char*) table_name; - key_length= create_table_def_key((THD*) 0, key, &table_list, 0); + key_length= create_table_def_key((THD*) 0, key, db, table_name, 0); return (TABLE_SHARE*) my_hash_search(&table_def_cache, (uchar*) key, key_length); } @@ -1990,12 +2022,9 @@ void update_non_unique_table_error(TABLE TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name) { - TABLE_LIST tl; - - tl.db= (char*) db; - tl.table_name= (char*) table_name; - - return find_temporary_table(thd, &tl); + char key[MAX_DBKEY_LENGTH]; + uint key_length= create_table_def_key(thd, key, db, table_name, 1); + return find_temporary_table(thd, key, key_length); } @@ -2008,10 +2037,26 @@ TABLE *find_temporary_table(THD *thd, co TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl) { - char key[MAX_DBKEY_LENGTH]; - uint key_length= create_table_def_key(thd, key, tl, 1); + const char *key; + uint key_length; + char key_suffix[TMP_TABLE_KEY_EXTRA]; + TABLE *table; - return find_temporary_table(thd, key, key_length); + key_length= get_table_def_key(tl, &key); + + int4store(key_suffix, thd->server_id); + int4store(key_suffix + 4, thd->variables.pseudo_thread_id); + + for (table= thd->temporary_tables; table; table= table->next) + { + if ((table->s->table_cache_key.length == key_length + + TMP_TABLE_KEY_EXTRA) && + !memcmp(table->s->table_cache_key.str, key, key_length) && + !memcmp(table->s->table_cache_key.str + key_length, key_suffix, + TMP_TABLE_KEY_EXTRA)) + return table; + } + return NULL; } @@ -2186,15 +2231,12 @@ bool rename_temporary_table(THD* thd, TA char *key; uint key_length; TABLE_SHARE *share= table->s; - TABLE_LIST table_list; DBUG_ENTER("rename_temporary_table"); if (!(key=(char*) alloc_root(&share->mem_root, MAX_DBKEY_LENGTH))) DBUG_RETURN(1); /* purecov: inspected */ - table_list.db= (char*) db; - table_list.table_name= (char*) table_name; - key_length= create_table_def_key(thd, key, &table_list, 1); + key_length= create_table_def_key(thd, key, db, table_name, 1); share->set_table_cache_key(key, key_length); DBUG_RETURN(0); } @@ -2600,8 +2642,8 @@ bool open_table(THD *thd, TABLE_LIST *ta Open_table_context *ot_ctx) { reg1 TABLE *table; - char key[MAX_DBKEY_LENGTH]; - uint key_length; + const char *key; + uint key_length; char *alias= table_list->alias; uint flags= ot_ctx->get_flags(); MDL_ticket *mdl_ticket; @@ -2625,7 +2667,7 @@ bool open_table(THD *thd, TABLE_LIST *ta if (thd->killed) DBUG_RETURN(TRUE); - key_length= create_table_def_key(thd, key, table_list, 0); + key_length= get_table_def_key(table_list, &key); /* If we're in pre-locked or LOCK TABLES mode, let's try to find the @@ -3664,7 +3706,7 @@ check_and_update_routine_version(THD *th */ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias, - char *cache_key, uint cache_key_length, + const char *cache_key, uint cache_key_length, MEM_ROOT *mem_root, uint flags) { TABLE not_used; @@ -3765,15 +3807,15 @@ static bool open_table_entry_fini(THD *t static bool auto_repair_table(THD *thd, TABLE_LIST *table_list) { - char cache_key[MAX_DBKEY_LENGTH]; - uint cache_key_length; + const char *cache_key; + uint cache_key_length; TABLE_SHARE *share; TABLE *entry; int not_used; bool result= TRUE; my_hash_value_type hash_value; - cache_key_length= create_table_def_key(thd, cache_key, table_list, 0); + cache_key_length= get_table_def_key(table_list, &cache_key); thd->clear_error(); @@ -5883,7 +5925,6 @@ TABLE *open_table_uncached(THD *thd, con TABLE_SHARE *share; char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path; uint key_length; - TABLE_LIST table_list; DBUG_ENTER("open_table_uncached"); DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s' server_id: %u " @@ -5891,10 +5932,8 @@ TABLE *open_table_uncached(THD *thd, con db, table_name, path, (uint) thd->server_id, (ulong) thd->variables.pseudo_thread_id)); - table_list.db= (char*) db; - table_list.table_name= (char*) table_name; /* Create the cache_key for temporary tables */ - key_length= create_table_def_key(thd, cache_key, &table_list, 1); + key_length= create_table_def_key(thd, cache_key, db, table_name, 1); if (!(tmp_table= (TABLE*) my_malloc(sizeof(*tmp_table) + sizeof(*share) + strlen(path)+1 + key_length, === modified file 'sql/sql_base.h' --- a/sql/sql_base.h 2011-03-26 10:56:27 +0000 +++ b/sql/sql_base.h 2011-04-01 20:00:35 +0000 @@ -78,11 +78,10 @@ void table_def_start_shutdown(void); void assign_new_table_id(TABLE_SHARE *share); uint cached_open_tables(void); uint cached_table_definitions(void); -uint create_table_def_key(THD *thd, char *key, - const TABLE_LIST *table_list, - bool tmp_table); -TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, - uint key_length, uint db_flags, int *error, +uint get_table_def_key(const TABLE_LIST *table_list, const char **key); +TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, + const char *key, uint key_length, + uint db_flags, int *error, my_hash_value_type hash_value); void release_table_share(TABLE_SHARE *share); TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name); @@ -294,7 +293,7 @@ void tdc_remove_table(THD *thd, enum_tdc const char *db, const char *table_name, bool has_lock); bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias, - char *cache_key, uint cache_key_length, + const char *cache_key, uint cache_key_length, MEM_ROOT *mem_root, uint flags); void tdc_flush_unused_tables(); TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, === modified file 'sql/sql_show.cc' --- a/sql/sql_show.cc 2011-03-09 12:24:36 +0000 +++ b/sql/sql_show.cc 2011-04-01 20:00:35 +0000 @@ -3272,7 +3272,7 @@ static int fill_schema_table_from_frm(TH uint res= 0; int not_used; my_hash_value_type hash_value; - char key[MAX_DBKEY_LENGTH]; + const char *key; uint key_length; char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1]; @@ -3345,7 +3345,7 @@ static int fill_schema_table_from_frm(TH goto end; } - key_length= create_table_def_key(thd, key, &table_list, 0); + key_length= get_table_def_key(&table_list, &key); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); share= get_table_share(thd, &table_list, key, === modified file 'sql/sql_table.cc' --- a/sql/sql_table.cc 2011-03-26 10:56:27 +0000 +++ b/sql/sql_table.cc 2011-04-01 20:00:35 +0000 @@ -6592,9 +6592,9 @@ bool mysql_alter_table(THD *thd,char *ne if (table->s->tmp_table) { TABLE_LIST tbl; - bzero((void*) &tbl, sizeof(tbl)); - tbl.db= new_db; - tbl.table_name= tbl.alias= tmp_name; + tbl.init_one_table(new_db, strlen(new_db), + tmp_name, strlen(tmp_name), + tmp_name, TL_READ_NO_INSERT); /* Table is in thd->temporary_tables */ (void) open_temporary_table(thd, &tbl); new_table= tbl.table; @@ -6890,15 +6890,15 @@ bool mysql_alter_table(THD *thd,char *ne NO need to tamper with MERGE tables. The real open is done later. */ Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); - TABLE *t_table; + TABLE_LIST temp_table_list; + TABLE_LIST *t_table_list; if (new_name != table_name || new_db != db) { - table_list->alias= new_name; - table_list->table_name= new_name; - table_list->table_name_length= strlen(new_name); - table_list->db= new_db; - table_list->db_length= strlen(new_db); - table_list->mdl_request.ticket= target_mdl_request.ticket; + temp_table_list.init_one_table(new_db, strlen(new_db), + new_name, strlen(new_name), + new_name, TL_READ_NO_INSERT); + temp_table_list.mdl_request.ticket= target_mdl_request.ticket; + t_table_list= &temp_table_list; } else { @@ -6908,20 +6908,21 @@ bool mysql_alter_table(THD *thd,char *ne to request the lock. */ table_list->mdl_request.ticket= mdl_ticket; + t_table_list= table_list; } - if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) + if (open_table(thd, t_table_list, thd->mem_root, &ot_ctx)) { goto err_with_mdl; } - t_table= table_list->table; /* Tell the handler that a new frm file is in place. */ - error= t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG, - create_info); + error= t_table_list->table->file->ha_create_handler_files(path, NULL, + CHF_INDEX_FLAG, + create_info); - DBUG_ASSERT(thd->open_tables == t_table); + DBUG_ASSERT(thd->open_tables == t_table_list->table); close_thread_table(thd, &thd->open_tables); - table_list->table= 0; + t_table_list->table= NULL; if (error) goto err_with_mdl; === modified file 'sql/sql_view.cc' --- a/sql/sql_view.cc 2011-03-09 12:24:36 +0000 +++ b/sql/sql_view.cc 2011-04-01 20:00:35 +0000 @@ -209,13 +209,14 @@ static void make_valid_column_names(List static bool fill_defined_view_parts (THD *thd, TABLE_LIST *view) { - char key[MAX_DBKEY_LENGTH]; + const char *key; uint key_length; LEX *lex= thd->lex; TABLE_LIST decoy; memcpy (&decoy, view, sizeof (TABLE_LIST)); - key_length= create_table_def_key(thd, key, view, 0); + + key_length= get_table_def_key(view, &key); if (tdc_open_view(thd, &decoy, decoy.alias, key, key_length, thd->mem_root, OPEN_VIEW_NO_PARSE)) === modified file 'sql/table.cc' --- a/sql/table.cc 2011-03-01 14:47:01 +0000 +++ b/sql/table.cc 2011-04-01 20:00:35 +0000 @@ -311,7 +311,7 @@ TABLE_CATEGORY get_table_category(const # Share */ -TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, +TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, const char *key, uint key_length) { MEM_ROOT mem_root; === modified file 'sql/table.h' --- a/sql/table.h 2011-02-02 22:02:29 +0000 +++ b/sql/table.h 2011-04-01 20:00:35 +0000 @@ -2150,7 +2150,7 @@ void init_mdl_requests(TABLE_LIST *table int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, bool is_create_table); -TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, +TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, const char *key, uint key_length); void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, uint key_length, --===============1356203172== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.lenev@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.lenev@stripped # target_branch: file:///home/dlenev/src/bzr/mysql-trunk-bug27480-key/ # testament_sha1: b39a9253db0489739be0eb56f0efbe872e296d74 # timestamp: 2011-04-02 00:00:42 +0400 # base_revision_id: dmitry.lenev@stripped\ # 49infno7veu7nupf # # Begin bundle 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 --===============1356203172==--