mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge 10.0.14 into 10.1
This commit is contained in:
119
sql/sql_base.cc
119
sql/sql_base.cc
@ -2085,7 +2085,10 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (!(flags & MYSQL_OPEN_IGNORE_KILLED) && thd->killed)
|
||||
{
|
||||
thd->send_kill_message();
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Check if we're trying to take a write lock in a read only transaction.
|
||||
@ -2923,6 +2926,7 @@ Locked_tables_list::reopen_tables(THD *thd)
|
||||
size_t reopen_count= 0;
|
||||
MYSQL_LOCK *lock;
|
||||
MYSQL_LOCK *merged_lock;
|
||||
DBUG_ENTER("Locked_tables_list::reopen_tables");
|
||||
|
||||
for (TABLE_LIST *table_list= m_locked_tables;
|
||||
table_list; table_list= table_list->next_global)
|
||||
@ -2934,7 +2938,7 @@ Locked_tables_list::reopen_tables(THD *thd)
|
||||
if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
|
||||
{
|
||||
unlink_all_closed_tables(thd, 0, reopen_count);
|
||||
return TRUE;
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
table_list->table->pos_in_locked_tables= table_list;
|
||||
/* See also the comment on lock type in init_locked_tables(). */
|
||||
@ -2966,11 +2970,11 @@ Locked_tables_list::reopen_tables(THD *thd)
|
||||
unlink_all_closed_tables(thd, lock, reopen_count);
|
||||
if (! thd->killed)
|
||||
my_error(ER_LOCK_DEADLOCK, MYF(0));
|
||||
return TRUE;
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
thd->lock= merged_lock;
|
||||
}
|
||||
return FALSE;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3515,9 +3519,12 @@ Open_table_context::recover_from_failed_open()
|
||||
/*
|
||||
Return a appropriate read lock type given a table object.
|
||||
|
||||
@param thd Thread context
|
||||
@param prelocking_ctx Prelocking context.
|
||||
@param table_list Table list element for table to be locked.
|
||||
@param thd Thread context
|
||||
@param prelocking_ctx Prelocking context.
|
||||
@param table_list Table list element for table to be locked.
|
||||
@param routine_modifies_data
|
||||
Some routine that is invoked by statement
|
||||
modifies data.
|
||||
|
||||
@remark Due to a statement-based replication limitation, statements such as
|
||||
INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need
|
||||
@ -3530,9 +3537,13 @@ Open_table_context::recover_from_failed_open()
|
||||
This also applies to SELECT/SET/DO statements which use stored
|
||||
functions. Calls to such functions are going to be logged as a
|
||||
whole and thus should be serialized against concurrent changes
|
||||
to tables used by those functions. This can be avoided if functions
|
||||
only read data but doing so requires more complex analysis than it
|
||||
is done now.
|
||||
to tables used by those functions. This is avoided when functions
|
||||
do not modify data but only read it, since in this case nothing is
|
||||
written to the binary log. Argument routine_modifies_data
|
||||
denotes the same. So effectively, if the statement is not a
|
||||
update query and routine_modifies_data is false, then
|
||||
prelocking_placeholder does not take importance.
|
||||
|
||||
Furthermore, this does not apply to I_S and log tables as it's
|
||||
always unsafe to replicate such tables under statement-based
|
||||
replication as the table on the slave might contain other data
|
||||
@ -3547,7 +3558,8 @@ Open_table_context::recover_from_failed_open()
|
||||
|
||||
thr_lock_type read_lock_type_for_table(THD *thd,
|
||||
Query_tables_list *prelocking_ctx,
|
||||
TABLE_LIST *table_list)
|
||||
TABLE_LIST *table_list,
|
||||
bool routine_modifies_data)
|
||||
{
|
||||
/*
|
||||
In cases when this function is called for a sub-statement executed in
|
||||
@ -3561,7 +3573,7 @@ thr_lock_type read_lock_type_for_table(THD *thd,
|
||||
(table_list->table->s->table_category == TABLE_CATEGORY_LOG) ||
|
||||
(table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) ||
|
||||
!(is_update_query(prelocking_ctx->sql_command) ||
|
||||
table_list->prelocking_placeholder ||
|
||||
(routine_modifies_data && table_list->prelocking_placeholder) ||
|
||||
(thd->locked_tables_mode > LTM_LOCK_TABLES)))
|
||||
return TL_READ;
|
||||
else
|
||||
@ -3574,19 +3586,21 @@ thr_lock_type read_lock_type_for_table(THD *thd,
|
||||
and, if prelocking strategy prescribes so, extend the prelocking set
|
||||
with tables and routines used by it.
|
||||
|
||||
@param[in] thd Thread context.
|
||||
@param[in] prelocking_ctx Prelocking context.
|
||||
@param[in] rt Element of prelocking set to be processed.
|
||||
@param[in] prelocking_strategy Strategy which specifies how the
|
||||
prelocking set should be extended when
|
||||
one of its elements is processed.
|
||||
@param[in] has_prelocking_list Indicates that prelocking set/list for
|
||||
this statement has already been built.
|
||||
@param[in] ot_ctx Context of open_table used to recover from
|
||||
locking failures.
|
||||
@param[out] need_prelocking Set to TRUE if it was detected that this
|
||||
statement will require prelocked mode for
|
||||
its execution, not touched otherwise.
|
||||
@param[in] thd Thread context.
|
||||
@param[in] prelocking_ctx Prelocking context.
|
||||
@param[in] rt Element of prelocking set to be processed.
|
||||
@param[in] prelocking_strategy Strategy which specifies how the
|
||||
prelocking set should be extended when
|
||||
one of its elements is processed.
|
||||
@param[in] has_prelocking_list Indicates that prelocking set/list for
|
||||
this statement has already been built.
|
||||
@param[in] ot_ctx Context of open_table used to recover from
|
||||
locking failures.
|
||||
@param[out] need_prelocking Set to TRUE if it was detected that this
|
||||
statement will require prelocked mode for
|
||||
its execution, not touched otherwise.
|
||||
@param[out] routine_modifies_data Set to TRUE if it was detected that this
|
||||
routine does modify table data.
|
||||
|
||||
@retval FALSE Success.
|
||||
@retval TRUE Failure (Conflicting metadata lock, OOM, other errors).
|
||||
@ -3598,11 +3612,13 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
Prelocking_strategy *prelocking_strategy,
|
||||
bool has_prelocking_list,
|
||||
Open_table_context *ot_ctx,
|
||||
bool *need_prelocking)
|
||||
bool *need_prelocking, bool *routine_modifies_data)
|
||||
{
|
||||
MDL_key::enum_mdl_namespace mdl_type= rt->mdl_request.key.mdl_namespace();
|
||||
DBUG_ENTER("open_and_process_routine");
|
||||
|
||||
*routine_modifies_data= false;
|
||||
|
||||
switch (mdl_type)
|
||||
{
|
||||
case MDL_key::FUNCTION:
|
||||
@ -3655,10 +3671,13 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/* 'sp' is NULL when there is no such routine. */
|
||||
if (sp && !has_prelocking_list)
|
||||
if (sp)
|
||||
{
|
||||
prelocking_strategy->handle_routine(thd, prelocking_ctx, rt, sp,
|
||||
need_prelocking);
|
||||
*routine_modifies_data= sp->modifies_data();
|
||||
|
||||
if (!has_prelocking_list)
|
||||
prelocking_strategy->handle_routine(thd, prelocking_ctx, rt, sp,
|
||||
need_prelocking);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4003,16 +4022,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables_mode)
|
||||
{
|
||||
if (tables->lock_type == TL_WRITE_DEFAULT)
|
||||
tables->table->reginfo.lock_type= thd->update_lock_default;
|
||||
else if (tables->lock_type == TL_READ_DEFAULT)
|
||||
tables->table->reginfo.lock_type=
|
||||
read_lock_type_for_table(thd, lex, tables);
|
||||
else
|
||||
tables->table->reginfo.lock_type= tables->lock_type;
|
||||
}
|
||||
/* Copy grant information from TABLE_LIST instance to TABLE one. */
|
||||
tables->table->grant= tables->grant;
|
||||
|
||||
/* Check and update metadata version of a base table. */
|
||||
@ -4351,6 +4361,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
|
||||
Open_table_context ot_ctx(thd, flags);
|
||||
bool error= FALSE;
|
||||
MEM_ROOT new_frm_mem;
|
||||
bool some_routine_modifies_data= FALSE;
|
||||
bool has_prelocking_list;
|
||||
DBUG_ENTER("open_tables");
|
||||
|
||||
@ -4523,11 +4534,16 @@ restart:
|
||||
sroutine_to_open= &rt->next, rt= rt->next)
|
||||
{
|
||||
bool need_prelocking= false;
|
||||
bool routine_modifies_data;
|
||||
TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
|
||||
|
||||
error= open_and_process_routine(thd, thd->lex, rt, prelocking_strategy,
|
||||
has_prelocking_list, &ot_ctx,
|
||||
&need_prelocking);
|
||||
&need_prelocking,
|
||||
&routine_modifies_data);
|
||||
|
||||
// Remember if any of SF modifies data.
|
||||
some_routine_modifies_data|= routine_modifies_data;
|
||||
|
||||
if (need_prelocking && ! thd->lex->requires_prelocking())
|
||||
thd->lex->mark_as_requiring_prelocking(save_query_tables_last);
|
||||
@ -4568,6 +4584,10 @@ restart:
|
||||
the children are detached. Attaching and detaching are always done,
|
||||
even under LOCK TABLES.
|
||||
|
||||
We also convert all TL_WRITE_DEFAULT and TL_READ_DEFAULT locks to
|
||||
appropriate "real" lock types to be used for locking and to be passed
|
||||
to storage engine.
|
||||
|
||||
And start wsrep TOI if needed.
|
||||
*/
|
||||
for (tables= *start; tables; tables= tables->next_global)
|
||||
@ -4595,6 +4615,19 @@ restart:
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set appropriate TABLE::lock_type. */
|
||||
if (tbl && tables->lock_type != TL_UNLOCK && !thd->locked_tables_mode)
|
||||
{
|
||||
if (tables->lock_type == TL_WRITE_DEFAULT)
|
||||
tbl->reginfo.lock_type= thd->update_lock_default;
|
||||
else if (tables->lock_type == TL_READ_DEFAULT)
|
||||
tbl->reginfo.lock_type=
|
||||
read_lock_type_for_table(thd, thd->lex, tables,
|
||||
some_routine_modifies_data);
|
||||
else
|
||||
tbl->reginfo.lock_type= tables->lock_type;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
@ -4858,11 +4891,15 @@ static bool check_lock_and_start_stmt(THD *thd,
|
||||
engine is important as, for example, InnoDB uses it to determine
|
||||
what kind of row locks should be acquired when executing statement
|
||||
in prelocked mode or under LOCK TABLES with @@innodb_table_locks = 0.
|
||||
|
||||
Last argument routine_modifies_data for read_lock_type_for_table()
|
||||
is ignored, as prelocking placeholder will never be set here.
|
||||
*/
|
||||
DBUG_ASSERT(table_list->prelocking_placeholder == false);
|
||||
if (table_list->lock_type == TL_WRITE_DEFAULT)
|
||||
lock_type= thd->update_lock_default;
|
||||
else if (table_list->lock_type == TL_READ_DEFAULT)
|
||||
lock_type= read_lock_type_for_table(thd, prelocking_ctx, table_list);
|
||||
lock_type= read_lock_type_for_table(thd, prelocking_ctx, table_list, true);
|
||||
else
|
||||
lock_type= table_list->lock_type;
|
||||
|
||||
@ -5283,6 +5320,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST);
|
||||
}
|
||||
|
||||
#ifdef NOT_USED_IN_MARIADB
|
||||
/*
|
||||
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
|
||||
can be unsafe.
|
||||
@ -5308,6 +5346,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
|
||||
thd->lex->duplicates == DUP_UPDATE)
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We have to emulate LOCK TABLES if we are statement needs prelocking. */
|
||||
if (thd->lex->requires_prelocking())
|
||||
|
Reference in New Issue
Block a user