mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Implementation of Monty's idea: Now we can open mysql.proc table for lookup
of stored routines definitions even if we already have some tables open and locked. To avoid deadlocks in this case we have to put certain restrictions on locking of mysql.proc table. This allows to use stored routines safely under LOCK TABLES without explicitly mentioning mysql.proc in the list of locked tables. It also fixes bug #11554 "Server crashes on statement indirectly using non-cached function".
This commit is contained in:
@@ -542,10 +542,9 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived,
|
||||
|
||||
bool close_thread_table(THD *thd, TABLE **table_ptr)
|
||||
{
|
||||
DBUG_ENTER("close_thread_table");
|
||||
|
||||
bool found_old_table= 0;
|
||||
TABLE *table= *table_ptr;
|
||||
DBUG_ENTER("close_thread_table");
|
||||
DBUG_ASSERT(table->key_read == 0);
|
||||
DBUG_ASSERT(table->file->inited == handler::NONE);
|
||||
|
||||
@@ -972,18 +971,34 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
** open a table
|
||||
** Uses a cache of open tables to find a table not in use.
|
||||
** If refresh is a NULL pointer, then the is no version number checking and
|
||||
** the table is not put in the thread-open-list
|
||||
** If the return value is NULL and refresh is set then one must close
|
||||
** all tables and retry the open
|
||||
******************************************************************************/
|
||||
/*
|
||||
Open a table.
|
||||
|
||||
SYNOPSIS
|
||||
open_table()
|
||||
thd Thread context
|
||||
table_list Open first table in list
|
||||
refresh Pointer to memory that will be set to 1 if
|
||||
we need to close all tables and reopen them
|
||||
If this is a NULL pointer, then the is no version
|
||||
number checking and the table is not put in the
|
||||
thread-open-list
|
||||
flags Bitmap of flags to modify how open works:
|
||||
MYSQL_LOCK_IGNORE_FLUSH - Open table even if someone
|
||||
has done a flush or namelock on it.
|
||||
|
||||
IMPLEMENTATION
|
||||
Uses a cache of open tables to find a table not in use.
|
||||
|
||||
RETURN
|
||||
NULL Open failed. If refresh is set then one should close
|
||||
all other tables and retry the open
|
||||
# Success. Pointer to TABLE object for open table.
|
||||
*/
|
||||
|
||||
|
||||
TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
bool *refresh)
|
||||
bool *refresh, uint flags)
|
||||
{
|
||||
reg1 TABLE *table;
|
||||
char key[MAX_DBKEY_LENGTH];
|
||||
@@ -1096,9 +1111,16 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
{
|
||||
if (table->s->version != refresh_version)
|
||||
{
|
||||
if (flags & MYSQL_LOCK_IGNORE_FLUSH)
|
||||
{
|
||||
/* Force close at once after usage */
|
||||
thd->version= table->s->version;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** There is a refresh in progress for this table
|
||||
** Wait until the table is freed or the thread is killed.
|
||||
There is a refresh in progress for this table
|
||||
Wait until the table is freed or the thread is killed.
|
||||
*/
|
||||
close_old_data_files(thd,thd->open_tables,0,0);
|
||||
if (table->in_use != thd)
|
||||
@@ -1681,6 +1703,15 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
if (error == 5)
|
||||
DBUG_RETURN(0); // we have just opened VIEW
|
||||
|
||||
/*
|
||||
We can't mark all tables in 'mysql' database as system since we don't
|
||||
allow to lock such tables for writing with any other tables (even with
|
||||
other system tables) and some privilege tables need this.
|
||||
*/
|
||||
if (!my_strcasecmp(system_charset_info, db, "mysql") &&
|
||||
!my_strcasecmp(system_charset_info, name, "proc"))
|
||||
entry->s->system_table= 1;
|
||||
|
||||
if (Table_triggers_list::check_n_load(thd, db, name, entry))
|
||||
goto err;
|
||||
|
||||
@@ -1835,7 +1866,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter)
|
||||
}
|
||||
(*counter)++;
|
||||
if (!tables->table &&
|
||||
!(tables->table= open_table(thd, tables, &new_frm_mem, &refresh)))
|
||||
!(tables->table= open_table(thd, tables, &new_frm_mem, &refresh, 0)))
|
||||
{
|
||||
free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC));
|
||||
if (tables->view)
|
||||
@@ -2010,7 +2041,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
thd->current_tablenr= 0;
|
||||
/* open_ltable can be used only for BASIC TABLEs */
|
||||
table_list->required_type= FRMTYPE_TABLE;
|
||||
while (!(table= open_table(thd, table_list, thd->mem_root, &refresh)) &&
|
||||
while (!(table= open_table(thd, table_list, thd->mem_root, &refresh, 0)) &&
|
||||
refresh)
|
||||
;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user