Commit aeb502d6 authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

------------------------------------------------------------
revno: 2617.65.6
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-azalea-bg39674
timestamp: Sat 2009-07-25 00:28:43 +0400
message:
  Fix for bug #39674 "On shutdown mdl_destroy() called before
  plugin_shutdown()".

  Attempt to shutdown PBXT engine plugin led to assertion failure
  caused by using already destroyed mutex in metadata locking
  subsystem.

  This problem stemmed from the fact that we MDL subsystem and
  table definition cache were deinitialized before plugin shutdown
  while PBXT plugin during its shutdown process accessed tables and
  therefore expected them to be in working shape.

  This patch solves this problem by moving deinitialization of
  these two subsystems after plugins are shut down.

  No test case is provided since such test case would require
  using PBXT or other plugin which accesses tables during its
  shutdown process.


sql/mysql_priv.h:
  Introduced table_def_start_shutdown() function which informs
  table definition cache that shutdown process has been started
  so it has to keep number of TABLE and TABLE_SHARE objects minimal
  in order to reduce number of references to pluggable engines.
sql/mysqld.cc:
  Destroy table definition cache and meta-data locking subsystem
  after shutting down plugins. This allows plugins to work with
  tables during their shutdown.
  Since table definition cache hold references to storage engine
  plugins we have to remove unused tables from it before shutting
  down plugins and keep number of these references minimal during
  the process (by immediately removing tables opened during this
  process from the table definition cache).
sql/sql_base.cc:
  Introduced table_def_start_shutdown() function which informs
  table definition cache that shutdown process has been started
  so it has to keep number of TABLE and TABLE_SHARE objects
  minimal in order to reduce number of references to pluggable
  engines.
          This allows to smoothly shutdown such plugins without completely
          prohibiting access to tables/table definition cache while
          shutting down other plugins.
parent 47e7df33
...@@ -1047,6 +1047,7 @@ bool compare_record(TABLE *table); ...@@ -1047,6 +1047,7 @@ bool compare_record(TABLE *table);
bool append_file_to_dir(THD *thd, const char **filename_ptr, bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name); const char *table_name);
bool table_def_init(void); bool table_def_init(void);
void table_def_start_shutdown(void);
void table_def_free(void); void table_def_free(void);
void assign_new_table_id(TABLE_SHARE *share); void assign_new_table_id(TABLE_SHARE *share);
uint cached_open_tables(void); uint cached_open_tables(void);
......
...@@ -1294,9 +1294,7 @@ void clean_up(bool print_message) ...@@ -1294,9 +1294,7 @@ void clean_up(bool print_message)
grant_free(); grant_free();
#endif #endif
query_cache_destroy(); query_cache_destroy();
table_def_free();
hostname_cache_free(); hostname_cache_free();
mdl_destroy();
item_user_lock_free(); item_user_lock_free();
lex_free(); /* Free some memory */ lex_free(); /* Free some memory */
item_create_cleanup(); item_create_cleanup();
...@@ -1308,12 +1306,15 @@ void clean_up(bool print_message) ...@@ -1308,12 +1306,15 @@ void clean_up(bool print_message)
udf_free(); udf_free();
#endif #endif
} }
table_def_start_shutdown();
plugin_shutdown(); plugin_shutdown();
ha_end(); ha_end();
if (tc_log) if (tc_log)
tc_log->close(); tc_log->close();
delegates_destroy(); delegates_destroy();
xid_cache_free(); xid_cache_free();
table_def_free();
mdl_destroy();
delete_elements(&key_caches, (void (*)(const char*, uchar*)) free_key_cache); delete_elements(&key_caches, (void (*)(const char*, uchar*)) free_key_cache);
multi_keycache_free(); multi_keycache_free();
free_status_vars(); free_status_vars();
......
...@@ -114,6 +114,7 @@ TABLE *unused_tables; ...@@ -114,6 +114,7 @@ TABLE *unused_tables;
HASH table_def_cache; HASH table_def_cache;
static TABLE_SHARE *oldest_unused_share, end_of_unused_share; static TABLE_SHARE *oldest_unused_share, end_of_unused_share;
static bool table_def_inited= 0; static bool table_def_inited= 0;
static bool table_def_shutdown_in_progress= 0;
static bool check_and_update_table_version(THD *thd, TABLE_LIST *tables, static bool check_and_update_table_version(THD *thd, TABLE_LIST *tables,
TABLE_SHARE *table_share); TABLE_SHARE *table_share);
...@@ -279,13 +280,36 @@ bool table_def_init(void) ...@@ -279,13 +280,36 @@ bool table_def_init(void)
} }
/**
Notify table definition cache that process of shutting down server
has started so it has to keep number of TABLE and TABLE_SHARE objects
minimal in order to reduce number of references to pluggable engines.
*/
void table_def_start_shutdown(void)
{
if (table_def_inited)
{
pthread_mutex_lock(&LOCK_open);
/* Free all cached but unused TABLEs and TABLE_SHAREs first. */
close_cached_tables(NULL, NULL, TRUE, FALSE);
/*
Ensure that TABLE and TABLE_SHARE objects which are created for
tables that are open during process of plugins' shutdown are
immediately released. This keeps number of references to engine
plugins minimal and allows shutdown to proceed smoothly.
*/
table_def_shutdown_in_progress= TRUE;
pthread_mutex_unlock(&LOCK_open);
}
}
void table_def_free(void) void table_def_free(void)
{ {
DBUG_ENTER("table_def_free"); DBUG_ENTER("table_def_free");
if (table_def_inited) if (table_def_inited)
{ {
/* Free all open TABLEs first. */
close_cached_tables(NULL, NULL, FALSE, FALSE);
table_def_inited= 0; table_def_inited= 0;
/* Free table definitions. */ /* Free table definitions. */
my_hash_free(&table_def_cache); my_hash_free(&table_def_cache);
...@@ -646,7 +670,8 @@ void release_table_share(TABLE_SHARE *share) ...@@ -646,7 +670,8 @@ void release_table_share(TABLE_SHARE *share)
DBUG_ASSERT(share->ref_count); DBUG_ASSERT(share->ref_count);
if (!--share->ref_count) if (!--share->ref_count)
{ {
if (share->version != refresh_version) if (share->version != refresh_version ||
table_def_shutdown_in_progress)
to_be_deleted=1; to_be_deleted=1;
else else
{ {
...@@ -1513,7 +1538,8 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) ...@@ -1513,7 +1538,8 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
table->mdl_ticket= NULL; table->mdl_ticket= NULL;
if (table->needs_reopen() || if (table->needs_reopen() ||
thd->version != refresh_version || !table->db_stat) thd->version != refresh_version || !table->db_stat ||
table_def_shutdown_in_progress)
{ {
free_cache_entry(table); free_cache_entry(table);
found_old_table=1; found_old_table=1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment