Commit ce6a63ec authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-4260 Don't create frm files for temporary tables

* Don't write frm for tmp tables
* pass frm image down to open_table_uncached, when possible
* don't use truncate-by-recreate for temp tables - cannot recreate
  without frm, and delete_all_rows is faster anyway
parent cc5b3998
create table t1 select * from information_schema.session_status where variable_name like 'Opened%';
create temporary table t2 (a int) engine=memory;
select variable_name, session_status.variable_value - t1.variable_value
from information_schema.session_status join t1 using (variable_name);
variable_name session_status.variable_value - t1.variable_value
OPENED_FILES 0
OPENED_PLUGIN_LIBRARIES 0
OPENED_TABLE_DEFINITIONS 2
OPENED_TABLES 2
OPENED_VIEWS 0
truncate table t2;
select variable_name, session_status.variable_value - t1.variable_value
from information_schema.session_status join t1 using (variable_name);
variable_name session_status.variable_value - t1.variable_value
OPENED_FILES 0
OPENED_PLUGIN_LIBRARIES 0
OPENED_TABLE_DEFINITIONS 2
OPENED_TABLES 2
OPENED_VIEWS 0
drop table t1;
#
# MDEV-4260 Don't create frm files for temporary tables
#
create table t1 select * from information_schema.session_status where variable_name like 'Opened%';
create temporary table t2 (a int) engine=memory;
select variable_name, session_status.variable_value - t1.variable_value
from information_schema.session_status join t1 using (variable_name);
let $tmpdir= `select @@tmpdir`;
--list_files $tmpdir/
truncate table t2;
select variable_name, session_status.variable_value - t1.variable_value
from information_schema.session_status join t1 using (variable_name);
drop table t1;
...@@ -5508,6 +5508,7 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, ...@@ -5508,6 +5508,7 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
@param thd Thread context. @param thd Thread context.
@param hton Storage engine of the table, if known, @param hton Storage engine of the table, if known,
or NULL otherwise. or NULL otherwise.
@param frm frm image
@param path Path (without .frm) @param path Path (without .frm)
@param db Database name. @param db Database name.
@param table_name Table name. @param table_name Table name.
...@@ -5527,6 +5528,7 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, ...@@ -5527,6 +5528,7 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
*/ */
TABLE *open_table_uncached(THD *thd, handlerton *hton, TABLE *open_table_uncached(THD *thd, handlerton *hton,
LEX_CUSTRING *frm,
const char *path, const char *db, const char *path, const char *db,
const char *table_name, const char *table_name,
bool add_to_temporary_tables_list, bool add_to_temporary_tables_list,
...@@ -5561,7 +5563,17 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton, ...@@ -5561,7 +5563,17 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton,
strend(saved_cache_key)+1, tmp_path); strend(saved_cache_key)+1, tmp_path);
share->db_plugin= ha_lock_engine(thd, hton); share->db_plugin= ha_lock_engine(thd, hton);
if (open_table_def(thd, share, GTS_TABLE | GTS_USE_DISCOVERY)) /*
Use the frm image, if possible, open the file otherwise.
The image might be unavailable in ALTER TABLE, when the discovering
engine took over the ownership (see TABLE::read_frm_image).
*/
int res= frm->str
? share->init_from_binary_frm_image(thd, false, frm->str, frm->length)
: open_table_def(thd, share, GTS_TABLE | GTS_USE_DISCOVERY);
if (res)
{ {
/* No need to lock share->mutex as this is not needed for tmp tables */ /* No need to lock share->mutex as this is not needed for tmp tables */
free_table_share(share); free_table_share(share);
......
...@@ -127,7 +127,8 @@ bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, ...@@ -127,7 +127,8 @@ bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
bool get_key_map_from_key_list(key_map *map, TABLE *table, bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list); List<String> *index_list);
TABLE *open_table_uncached(THD *thd, handlerton *hton, const char *path, TABLE *open_table_uncached(THD *thd, handlerton *hton,
LEX_CUSTRING *frm, const char *path,
const char *db, const char *table_name, const char *db, const char *table_name,
bool add_to_temporary_tables_list, bool add_to_temporary_tables_list,
bool open_in_engine); bool open_in_engine);
......
...@@ -4847,7 +4847,7 @@ int create_table_impl(THD *thd, ...@@ -4847,7 +4847,7 @@ int create_table_impl(THD *thd,
THD::temporary_tables list. THD::temporary_tables list.
*/ */
TABLE *table= open_table_uncached(thd, create_info->db_type, path, TABLE *table= open_table_uncached(thd, create_info->db_type, frm, path,
db, table_name, true, true); db, table_name, true, true);
if (!table) if (!table)
...@@ -8691,7 +8691,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -8691,7 +8691,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
// We assume that the table is non-temporary. // We assume that the table is non-temporary.
DBUG_ASSERT(!table->s->tmp_table); DBUG_ASSERT(!table->s->tmp_table);
if (!(altered_table= open_table_uncached(thd, new_db_type, if (!(altered_table= open_table_uncached(thd, new_db_type, &frm,
alter_ctx.get_tmp_path(), alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.new_db,
alter_ctx.tmp_name, alter_ctx.tmp_name,
...@@ -8845,7 +8845,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -8845,7 +8845,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->tmp_table()) if (create_info->tmp_table())
{ {
if (!open_table_uncached(thd, new_db_type, if (!open_table_uncached(thd, new_db_type, &frm,
alter_ctx.get_tmp_path(), alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.new_db, alter_ctx.tmp_name,
true, true)) true, true))
...@@ -8867,7 +8867,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -8867,7 +8867,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{ {
/* table is a normal table: Create temporary table in same directory */ /* table is a normal table: Create temporary table in same directory */
/* Open our intermediate table. */ /* Open our intermediate table. */
new_table= open_table_uncached(thd, new_db_type, alter_ctx.get_tmp_path(), new_table= open_table_uncached(thd, new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.new_db, alter_ctx.tmp_name,
true, true); true, true);
} }
......
...@@ -261,52 +261,6 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref, ...@@ -261,52 +261,6 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref,
} }
/*
Close and recreate a temporary table. In case of success,
write truncate statement into the binary log if in statement
mode.
@param thd Thread context.
@param table The temporary table.
@retval FALSE Success.
@retval TRUE Error.
*/
static bool recreate_temporary_table(THD *thd, TABLE *table)
{
bool error= TRUE;
TABLE_SHARE *share= table->s;
handlerton *table_type= table->s->db_type();
TABLE *new_table;
DBUG_ENTER("recreate_temporary_table");
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
/* Don't free share. */
close_temporary_table(thd, table, FALSE, FALSE);
dd_recreate_table(thd, share->db.str, share->table_name.str,
share->normalized_path.str);
if ((new_table= open_table_uncached(thd, table_type, share->path.str,
share->db.str,
share->table_name.str, true, true)))
{
error= FALSE;
thd->thread_specific_used= TRUE;
new_table->s->table_creation_was_logged= share->table_creation_was_logged;
}
else
rm_temporary_table(table_type, share->path.str);
free_table_share(share);
my_free(table);
DBUG_RETURN(error);
}
/* /*
Handle locking a base table for truncate. Handle locking a base table for truncate.
...@@ -441,30 +395,10 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) ...@@ -441,30 +395,10 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
/* If it is a temporary table, no need to take locks. */ /* If it is a temporary table, no need to take locks. */
if (is_temporary_table(table_ref)) if (is_temporary_table(table_ref))
{ {
TABLE *tmp_table= table_ref->table;
/* In RBR, the statement is not binlogged if the table is temporary. */ /* In RBR, the statement is not binlogged if the table is temporary. */
binlog_stmt= !thd->is_current_stmt_binlog_format_row(); binlog_stmt= !thd->is_current_stmt_binlog_format_row();
/* Note that a temporary table cannot be partitioned. */ error= handler_truncate(thd, table_ref, TRUE);
if (ha_check_storage_engine_flag(tmp_table->s->db_type(),
HTON_CAN_RECREATE))
{
if ((error= recreate_temporary_table(thd, tmp_table)))
binlog_stmt= FALSE; /* No need to binlog failed truncate-by-recreate. */
DBUG_ASSERT(! thd->transaction.stmt.modified_non_trans_table);
}
else
{
/*
The engine does not support truncate-by-recreate. Open the
table and invoke the handler truncate. In such a manner this
can in fact open several tables if it's a temporary MyISAMMRG
table.
*/
error= handler_truncate(thd, table_ref, TRUE);
}
/* /*
No need to invalidate the query cache, queries with temporary No need to invalidate the query cache, queries with temporary
......
...@@ -354,8 +354,7 @@ int rea_create_table(THD *thd, LEX_CUSTRING *frm, ...@@ -354,8 +354,7 @@ int rea_create_table(THD *thd, LEX_CUSTRING *frm,
{ {
DBUG_ENTER("rea_create_table"); DBUG_ENTER("rea_create_table");
// TODO don't write frm for temp tables if (no_ha_create_table)
if (no_ha_create_table || create_info->tmp_table())
{ {
if (writefrm(path, db, table_name, true, frm->str, frm->length)) if (writefrm(path, db, table_name, true, frm->str, frm->length))
goto err_frm; goto err_frm;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment