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,
@param thd Thread context.
@param hton Storage engine of the table, if known,
or NULL otherwise.
@param frm frm image
@param path Path (without .frm)
@param db Database name.
@param table_name Table name.
......@@ -5527,6 +5528,7 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
*/
TABLE *open_table_uncached(THD *thd, handlerton *hton,
LEX_CUSTRING *frm,
const char *path, const char *db,
const char *table_name,
bool add_to_temporary_tables_list,
......@@ -5561,7 +5563,17 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton,
strend(saved_cache_key)+1, tmp_path);
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 */
free_table_share(share);
......
......@@ -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,
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,
bool add_to_temporary_tables_list,
bool open_in_engine);
......
......@@ -4847,7 +4847,7 @@ int create_table_impl(THD *thd,
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);
if (!table)
......@@ -8691,7 +8691,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
// We assume that the table is non-temporary.
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.new_db,
alter_ctx.tmp_name,
......@@ -8845,7 +8845,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
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.new_db, alter_ctx.tmp_name,
true, true))
......@@ -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 */
/* 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,
true, true);
}
......
......@@ -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.
......@@ -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 (is_temporary_table(table_ref))
{
TABLE *tmp_table= table_ref->table;
/* In RBR, the statement is not binlogged if the table is temporary. */
binlog_stmt= !thd->is_current_stmt_binlog_format_row();
/* Note that a temporary table cannot be partitioned. */
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);
}
error= handler_truncate(thd, table_ref, TRUE);
/*
No need to invalidate the query cache, queries with temporary
......
......@@ -354,8 +354,7 @@ int rea_create_table(THD *thd, LEX_CUSTRING *frm,
{
DBUG_ENTER("rea_create_table");
// TODO don't write frm for temp tables
if (no_ha_create_table || create_info->tmp_table())
if (no_ha_create_table)
{
if (writefrm(path, db, table_name, true, frm->str, frm->length))
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