mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Fixed close_cached_connection_tables() flushing
Let DROP SERVER and ALTER SERVER perform fair affected tables flushing. That is acquire MDL_EXCLUSIVE and do tdc_remove_table(TDC_RT_REMOVE_ALL). Aim of this patch is elimination of another inconsistent use of TDC_RT_REMOVE_UNUSED. It fixes (to some extent) a problem described in the beginning of sql_server.cc, when close_cached_connection_tables() interferes with concurrent transaction. A better fix should probably introduce proper MDL locks for server objects? Part of MDEV-17882 - Cleanup refresh version
This commit is contained in:
parent
54c03cb4f0
commit
bfdd30d3e9
3 changed files with 73 additions and 88 deletions
|
@ -630,93 +630,6 @@ err:
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
Close all tables which match specified connection string or
|
||||
if specified string is NULL, then any table with a connection string.
|
||||
*/
|
||||
|
||||
struct close_cached_connection_tables_arg
|
||||
{
|
||||
THD *thd;
|
||||
LEX_CSTRING *connection;
|
||||
TABLE_LIST *tables;
|
||||
};
|
||||
|
||||
|
||||
static my_bool close_cached_connection_tables_callback(
|
||||
TDC_element *element, close_cached_connection_tables_arg *arg)
|
||||
{
|
||||
TABLE_LIST *tmp;
|
||||
|
||||
mysql_mutex_lock(&element->LOCK_table_share);
|
||||
/* Ignore if table is not open or does not have a connect_string */
|
||||
if (!element->share || !element->share->connect_string.length ||
|
||||
!element->ref_count)
|
||||
goto end;
|
||||
|
||||
/* Compare the connection string */
|
||||
if (arg->connection &&
|
||||
(arg->connection->length > element->share->connect_string.length ||
|
||||
(arg->connection->length < element->share->connect_string.length &&
|
||||
(element->share->connect_string.str[arg->connection->length] != '/' &&
|
||||
element->share->connect_string.str[arg->connection->length] != '\\')) ||
|
||||
strncasecmp(arg->connection->str, element->share->connect_string.str,
|
||||
arg->connection->length)))
|
||||
goto end;
|
||||
|
||||
/* close_cached_tables() only uses these elements */
|
||||
if (!(tmp= (TABLE_LIST*) alloc_root(arg->thd->mem_root, sizeof(TABLE_LIST))) ||
|
||||
!(arg->thd->make_lex_string(&tmp->db, element->share->db.str, element->share->db.length)) ||
|
||||
!(arg->thd->make_lex_string(&tmp->table_name, element->share->table_name.str,
|
||||
element->share->table_name.length)))
|
||||
{
|
||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tmp->next_local= arg->tables;
|
||||
arg->tables= tmp;
|
||||
|
||||
end:
|
||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Close cached connections
|
||||
|
||||
@return false ok
|
||||
@return true If there was an error from closed_cached_connection_tables or
|
||||
if there was any open connections that we had to force closed
|
||||
*/
|
||||
|
||||
bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
|
||||
{
|
||||
bool res= false;
|
||||
close_cached_connection_tables_arg argument;
|
||||
DBUG_ENTER("close_cached_connections");
|
||||
DBUG_ASSERT(thd);
|
||||
|
||||
argument.thd= thd;
|
||||
argument.connection= connection;
|
||||
argument.tables= NULL;
|
||||
|
||||
if (tdc_iterate(thd,
|
||||
(my_hash_walk_action) close_cached_connection_tables_callback,
|
||||
&argument))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
for (TABLE_LIST *table= argument.tables; table; table= table->next_local)
|
||||
res|= tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||
table->db.str,
|
||||
table->table_name.str);
|
||||
|
||||
/* Return true if we found any open connections */
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Mark all tables in the list which were used by current substatement
|
||||
as free for reuse.
|
||||
|
|
|
@ -306,7 +306,6 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
|
|||
bool wait_for_refresh, ulong timeout);
|
||||
void purge_tables();
|
||||
bool flush_tables(THD *thd, flush_tables_type flag);
|
||||
bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connect_string);
|
||||
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
||||
ha_extra_function extra,
|
||||
TABLE *skip_table);
|
||||
|
|
|
@ -124,6 +124,79 @@ static void init_servers_cache_psi_keys(void)
|
|||
}
|
||||
#endif /* HAVE_PSI_INTERFACE */
|
||||
|
||||
|
||||
struct close_cached_connection_tables_arg
|
||||
{
|
||||
THD *thd;
|
||||
LEX_CSTRING *connection;
|
||||
TABLE_LIST *tables;
|
||||
};
|
||||
|
||||
|
||||
static my_bool close_cached_connection_tables_callback(
|
||||
TDC_element *element, close_cached_connection_tables_arg *arg)
|
||||
{
|
||||
TABLE_LIST *tmp;
|
||||
|
||||
mysql_mutex_lock(&element->LOCK_table_share);
|
||||
/* Ignore if table is not open or does not have a connect_string */
|
||||
if (!element->share || !element->share->connect_string.length ||
|
||||
!element->ref_count)
|
||||
goto end;
|
||||
|
||||
/* Compare the connection string */
|
||||
if (arg->connection &&
|
||||
(arg->connection->length > element->share->connect_string.length ||
|
||||
(arg->connection->length < element->share->connect_string.length &&
|
||||
(element->share->connect_string.str[arg->connection->length] != '/' &&
|
||||
element->share->connect_string.str[arg->connection->length] != '\\')) ||
|
||||
strncasecmp(arg->connection->str, element->share->connect_string.str,
|
||||
arg->connection->length)))
|
||||
goto end;
|
||||
|
||||
/* close_cached_tables() only uses these elements */
|
||||
if (!(tmp= (TABLE_LIST*) alloc_root(arg->thd->mem_root, sizeof(TABLE_LIST))) ||
|
||||
!(arg->thd->make_lex_string(&tmp->db, element->share->db.str, element->share->db.length)) ||
|
||||
!(arg->thd->make_lex_string(&tmp->table_name, element->share->table_name.str,
|
||||
element->share->table_name.length)))
|
||||
{
|
||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tmp->next_local= arg->tables;
|
||||
arg->tables= tmp;
|
||||
|
||||
end:
|
||||
mysql_mutex_unlock(&element->LOCK_table_share);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Close all tables which match specified connection string or
|
||||
if specified string is NULL, then any table with a connection string.
|
||||
|
||||
@return false ok
|
||||
@return true error, some tables may keep using old server info
|
||||
*/
|
||||
|
||||
static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
|
||||
{
|
||||
close_cached_connection_tables_arg argument= { thd, connection, 0 };
|
||||
DBUG_ENTER("close_cached_connections");
|
||||
|
||||
if (tdc_iterate(thd,
|
||||
(my_hash_walk_action) close_cached_connection_tables_callback,
|
||||
&argument))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
DBUG_RETURN(argument.tables ?
|
||||
close_cached_tables(thd, argument.tables, true,
|
||||
thd->variables.lock_wait_timeout) : false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initialize structures responsible for servers used in federated
|
||||
server scheme information for them from the server
|
||||
|
|
Loading…
Reference in a new issue