summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc160
1 files changed, 121 insertions, 39 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 424f572deca..13b8625ebe6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2013 Monty Program Ab
+/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -653,6 +653,7 @@ bool close_cached_connection_tables(THD *thd, LEX_STRING *connection)
static void mark_temp_tables_as_free_for_reuse(THD *thd)
{
+ rpl_group_info *rgi_slave;
DBUG_ENTER("mark_temp_tables_as_free_for_reuse");
if (thd->query_id == 0)
@@ -661,20 +662,25 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd)
DBUG_VOID_RETURN;
}
- thd->lock_temporary_tables();
- for (TABLE *table= thd->temporary_tables ; table ; table= table->next)
- {
- if ((table->query_id == thd->query_id) && ! table->open_by_handler)
- mark_tmp_table_for_reuse(table);
- }
- thd->unlock_temporary_tables();
- if (thd->rgi_slave)
+ rgi_slave=thd->rgi_slave;
+ if ((!rgi_slave && thd->temporary_tables) ||
+ (rgi_slave && unlikely(rgi_slave->rli->save_temporary_tables)))
{
- /*
- Temporary tables are shared with other by sql execution threads.
- As a safety messure, clear the pointer to the common area.
- */
- thd->temporary_tables= 0;
+ thd->lock_temporary_tables();
+ for (TABLE *table= thd->temporary_tables ; table ; table= table->next)
+ {
+ if ((table->query_id == thd->query_id) && ! table->open_by_handler)
+ mark_tmp_table_for_reuse(table);
+ }
+ thd->unlock_temporary_tables();
+ if (rgi_slave)
+ {
+ /*
+ Temporary tables are shared with other by sql execution threads.
+ As a safety messure, clear the pointer to the common area.
+ */
+ thd->temporary_tables= 0;
+ }
}
DBUG_VOID_RETURN;
}
@@ -1434,6 +1440,9 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
bool check_alias)
{
TABLE_LIST *dup;
+
+ table= table->find_table_for_update();
+
if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
{
TABLE_LIST *child;
@@ -1544,6 +1553,69 @@ TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl)
}
+static bool
+use_temporary_table(THD *thd, TABLE *table, TABLE **out_table)
+{
+ *out_table= table;
+ if (!table)
+ return false;
+ /*
+ Temporary tables are not safe for parallel replication. They were
+ designed to be visible to one thread only, so have no table locking.
+ Thus there is no protection against two conflicting transactions
+ committing in parallel and things like that.
+
+ So for now, anything that uses temporary tables will be serialised
+ with anything before it, when using parallel replication.
+
+ ToDo: We might be able to introduce a reference count or something
+ on temp tables, and have slave worker threads wait for it to reach
+ zero before being allowed to use the temp table. Might not be worth
+ it though, as statement-based replication using temporary tables is
+ in any case rather fragile.
+ */
+ if (thd->rgi_slave && thd->rgi_slave->is_parallel_exec &&
+ thd->wait_for_prior_commit())
+ return true;
+ /*
+ We need to set the THD as it may be different in case of
+ parallel replication
+ */
+ if (table->in_use != thd)
+ {
+ table->in_use= thd;
+#ifdef REMOVE_AFTER_MERGE_WITH_10
+ if (thd->rgi_slave)
+ {
+ /*
+ We may be stealing an opened temporary tables from one slave
+ thread to another, we need to let the performance schema know that,
+ for aggregates per thread to work properly.
+ */
+ table->file->unbind_psi();
+ table->file->rebind_psi();
+ }
+#endif
+ }
+ return false;
+}
+
+bool
+find_and_use_temporary_table(THD *thd, const char *db, const char *table_name,
+ TABLE **out_table)
+{
+ return use_temporary_table(thd, find_temporary_table(thd, db, table_name),
+ out_table);
+}
+
+
+bool
+find_and_use_temporary_table(THD *thd, const TABLE_LIST *tl, TABLE **out_table)
+{
+ return use_temporary_table(thd, find_temporary_table(thd, tl), out_table);
+}
+
+
/**
Find a temporary table specified by a key in the THD::temporary_tables list.
@@ -1564,26 +1636,6 @@ TABLE *find_temporary_table(THD *thd,
if (table->s->table_cache_key.length == table_key_length &&
!memcmp(table->s->table_cache_key.str, table_key, table_key_length))
{
- /*
- We need to set the THD as it may be different in case of
- parallel replication
- */
- if (table->in_use != thd)
- {
- table->in_use= thd;
-#ifdef REMOVE_AFTER_MERGE_WITH_10
- if (thd->rgi_slave)
- {
- /*
- We may be stealing an opened temporary tables from one slave
- thread to another, we need to let the performance schema know that,
- for aggregates per thread to work properly.
- */
- table->file->unbind_psi();
- table->file->rebind_psi();
- }
-#endif
- }
result= table;
break;
}
@@ -3404,7 +3456,7 @@ request_backoff_action(enum_open_table_action action_arg,
if (action_arg != OT_REOPEN_TABLES && m_has_locks)
{
my_error(ER_LOCK_DEADLOCK, MYF(0));
- mark_transaction_to_rollback(m_thd, true);
+ m_thd->mark_transaction_to_rollback(true);
return TRUE;
}
/*
@@ -5583,6 +5635,14 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton,
(uint) thd->variables.server_id,
(ulong) thd->variables.pseudo_thread_id));
+ if (add_to_temporary_tables_list)
+ {
+ /* Temporary tables are not safe for parallel replication. */
+ if (thd->rgi_slave && thd->rgi_slave->is_parallel_exec &&
+ thd->wait_for_prior_commit())
+ DBUG_RETURN(NULL);
+ }
+
/* Create the cache_key for temporary tables */
key_length= create_tmp_table_def_key(thd, cache_key, db, table_name);
@@ -5808,7 +5868,9 @@ bool open_temporary_table(THD *thd, TABLE_LIST *tl)
DBUG_RETURN(FALSE);
}
- if (!(table= find_temporary_table(thd, tl)))
+ if (find_and_use_temporary_table(thd, tl, &table))
+ DBUG_RETURN(TRUE);
+ if (!table)
{
if (tl->open_type == OT_TEMPORARY_ONLY &&
tl->open_strategy == TABLE_LIST::OPEN_NORMAL)
@@ -5819,6 +5881,25 @@ bool open_temporary_table(THD *thd, TABLE_LIST *tl)
DBUG_RETURN(FALSE);
}
+ /*
+ Temporary tables are not safe for parallel replication. They were
+ designed to be visible to one thread only, so have no table locking.
+ Thus there is no protection against two conflicting transactions
+ committing in parallel and things like that.
+
+ So for now, anything that uses temporary tables will be serialised
+ with anything before it, when using parallel replication.
+
+ ToDo: We might be able to introduce a reference count or something
+ on temp tables, and have slave worker threads wait for it to reach
+ zero before being allowed to use the temp table. Might not be worth
+ it though, as statement-based replication using temporary tables is
+ in any case rather fragile.
+ */
+ if (thd->rgi_slave && thd->rgi_slave->is_parallel_exec &&
+ thd->wait_for_prior_commit())
+ DBUG_RETURN(true);
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (tl->partition_names)
{
@@ -6904,7 +6985,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
Item_field for tables.
*/
Item_ident *item_ref= (Item_ident *) item;
- if (item_ref->name && item_ref->table_name &&
+ if (field_name && item_ref->name && item_ref->table_name &&
!my_strcasecmp(system_charset_info, item_ref->name, field_name) &&
!my_strcasecmp(table_alias_charset, item_ref->table_name,
table_name) &&
@@ -7934,9 +8015,10 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
if (select_lex->first_cond_optimization)
{
leaves.empty();
- if (!select_lex->is_prep_leaf_list_saved)
+ if (select_lex->prep_leaf_list_state != SELECT_LEX::SAVED)
{
make_leaves_list(leaves, tables, full_table_list, first_select_table);
+ select_lex->prep_leaf_list_state= SELECT_LEX::READY;
select_lex->leaf_tables_exec.empty();
}
else