Skip to content

Commit bfdd30d

Browse files
committed
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
1 parent 54c03cb commit bfdd30d

File tree

3 files changed

+73
-88
lines changed

3 files changed

+73
-88
lines changed

sql/sql_base.cc

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -630,93 +630,6 @@ bool flush_tables(THD *thd, flush_tables_type flag)
630630
}
631631

632632

633-
/**
634-
Close all tables which match specified connection string or
635-
if specified string is NULL, then any table with a connection string.
636-
*/
637-
638-
struct close_cached_connection_tables_arg
639-
{
640-
THD *thd;
641-
LEX_CSTRING *connection;
642-
TABLE_LIST *tables;
643-
};
644-
645-
646-
static my_bool close_cached_connection_tables_callback(
647-
TDC_element *element, close_cached_connection_tables_arg *arg)
648-
{
649-
TABLE_LIST *tmp;
650-
651-
mysql_mutex_lock(&element->LOCK_table_share);
652-
/* Ignore if table is not open or does not have a connect_string */
653-
if (!element->share || !element->share->connect_string.length ||
654-
!element->ref_count)
655-
goto end;
656-
657-
/* Compare the connection string */
658-
if (arg->connection &&
659-
(arg->connection->length > element->share->connect_string.length ||
660-
(arg->connection->length < element->share->connect_string.length &&
661-
(element->share->connect_string.str[arg->connection->length] != '/' &&
662-
element->share->connect_string.str[arg->connection->length] != '\\')) ||
663-
strncasecmp(arg->connection->str, element->share->connect_string.str,
664-
arg->connection->length)))
665-
goto end;
666-
667-
/* close_cached_tables() only uses these elements */
668-
if (!(tmp= (TABLE_LIST*) alloc_root(arg->thd->mem_root, sizeof(TABLE_LIST))) ||
669-
!(arg->thd->make_lex_string(&tmp->db, element->share->db.str, element->share->db.length)) ||
670-
!(arg->thd->make_lex_string(&tmp->table_name, element->share->table_name.str,
671-
element->share->table_name.length)))
672-
{
673-
mysql_mutex_unlock(&element->LOCK_table_share);
674-
return TRUE;
675-
}
676-
677-
tmp->next_local= arg->tables;
678-
arg->tables= tmp;
679-
680-
end:
681-
mysql_mutex_unlock(&element->LOCK_table_share);
682-
return FALSE;
683-
}
684-
685-
686-
/**
687-
Close cached connections
688-
689-
@return false ok
690-
@return true If there was an error from closed_cached_connection_tables or
691-
if there was any open connections that we had to force closed
692-
*/
693-
694-
bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
695-
{
696-
bool res= false;
697-
close_cached_connection_tables_arg argument;
698-
DBUG_ENTER("close_cached_connections");
699-
DBUG_ASSERT(thd);
700-
701-
argument.thd= thd;
702-
argument.connection= connection;
703-
argument.tables= NULL;
704-
705-
if (tdc_iterate(thd,
706-
(my_hash_walk_action) close_cached_connection_tables_callback,
707-
&argument))
708-
DBUG_RETURN(true);
709-
710-
for (TABLE_LIST *table= argument.tables; table; table= table->next_local)
711-
res|= tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
712-
table->db.str,
713-
table->table_name.str);
714-
715-
/* Return true if we found any open connections */
716-
DBUG_RETURN(res);
717-
}
718-
719-
720633
/*
721634
Mark all tables in the list which were used by current substatement
722635
as free for reuse.

sql/sql_base.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
306306
bool wait_for_refresh, ulong timeout);
307307
void purge_tables();
308308
bool flush_tables(THD *thd, flush_tables_type flag);
309-
bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connect_string);
310309
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
311310
ha_extra_function extra,
312311
TABLE *skip_table);

sql/sql_servers.cc

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,79 @@ static void init_servers_cache_psi_keys(void)
124124
}
125125
#endif /* HAVE_PSI_INTERFACE */
126126

127+
128+
struct close_cached_connection_tables_arg
129+
{
130+
THD *thd;
131+
LEX_CSTRING *connection;
132+
TABLE_LIST *tables;
133+
};
134+
135+
136+
static my_bool close_cached_connection_tables_callback(
137+
TDC_element *element, close_cached_connection_tables_arg *arg)
138+
{
139+
TABLE_LIST *tmp;
140+
141+
mysql_mutex_lock(&element->LOCK_table_share);
142+
/* Ignore if table is not open or does not have a connect_string */
143+
if (!element->share || !element->share->connect_string.length ||
144+
!element->ref_count)
145+
goto end;
146+
147+
/* Compare the connection string */
148+
if (arg->connection &&
149+
(arg->connection->length > element->share->connect_string.length ||
150+
(arg->connection->length < element->share->connect_string.length &&
151+
(element->share->connect_string.str[arg->connection->length] != '/' &&
152+
element->share->connect_string.str[arg->connection->length] != '\\')) ||
153+
strncasecmp(arg->connection->str, element->share->connect_string.str,
154+
arg->connection->length)))
155+
goto end;
156+
157+
/* close_cached_tables() only uses these elements */
158+
if (!(tmp= (TABLE_LIST*) alloc_root(arg->thd->mem_root, sizeof(TABLE_LIST))) ||
159+
!(arg->thd->make_lex_string(&tmp->db, element->share->db.str, element->share->db.length)) ||
160+
!(arg->thd->make_lex_string(&tmp->table_name, element->share->table_name.str,
161+
element->share->table_name.length)))
162+
{
163+
mysql_mutex_unlock(&element->LOCK_table_share);
164+
return TRUE;
165+
}
166+
167+
tmp->next_local= arg->tables;
168+
arg->tables= tmp;
169+
170+
end:
171+
mysql_mutex_unlock(&element->LOCK_table_share);
172+
return FALSE;
173+
}
174+
175+
176+
/**
177+
Close all tables which match specified connection string or
178+
if specified string is NULL, then any table with a connection string.
179+
180+
@return false ok
181+
@return true error, some tables may keep using old server info
182+
*/
183+
184+
static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
185+
{
186+
close_cached_connection_tables_arg argument= { thd, connection, 0 };
187+
DBUG_ENTER("close_cached_connections");
188+
189+
if (tdc_iterate(thd,
190+
(my_hash_walk_action) close_cached_connection_tables_callback,
191+
&argument))
192+
DBUG_RETURN(true);
193+
194+
DBUG_RETURN(argument.tables ?
195+
close_cached_tables(thd, argument.tables, true,
196+
thd->variables.lock_wait_timeout) : false);
197+
}
198+
199+
127200
/*
128201
Initialize structures responsible for servers used in federated
129202
server scheme information for them from the server

0 commit comments

Comments
 (0)