List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:May 25 2012 8:43pm
Subject:bzr push into mysql-trunk branch (mattias.jonsson:3901 to 3902) Bug#13838761
WL#4305
View as plain text  
 3902 Mattias Jonsson	2012-05-24
      bug#13838761
      Reverting InnoDB part of WL#4305, which caused the regression.
      
      rb 1089 approved by Jimmy
      
      No easy/small test case have yet been found,
      but I have verified that it does not crash after 30 min of sysqa
      test as it does without this patch.

    modified:
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/ha_innodb.h
 3901 Mayank Prasad	2012-05-25
      Bug #14117145     SPURIOUS TEST FAILURES, TEST PERFORMANCE_SCHEMA.CONNECTION
      
      Details:
       - There were continuous disconnect statements one after another,
         without synchronization. That was causing race conditions.
      
      Fix:
       - Wait for each disconnect to finish explicitly and then do
         further disconnect.

    modified:
      mysql-test/suite/perfschema/include/connection_load.inc
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	revid:mayank.prasad@stripped
+++ b/storage/innobase/handler/ha_innodb.cc	revid:mattias.jonsson@stripped
@@ -96,6 +96,9 @@ this program; if not, write to the Free 
 # ifndef MYSQL_PLUGIN_IMPORT
 #  define MYSQL_PLUGIN_IMPORT /* nothing */
 # endif /* MYSQL_PLUGIN_IMPORT */
+
+/** to protect innobase_open_files */
+static mysql_mutex_t innobase_share_mutex;
 /** to force correct commit order in binlog */
 static ulong commit_threads = 0;
 static mysql_mutex_t commit_threads_m;
@@ -231,6 +234,8 @@ it every INNOBASE_WAKE_INTERVAL'th step.
 #define INNOBASE_WAKE_INTERVAL	32
 static ulong	innobase_active_counter	= 0;
 
+static hash_table_t*	innobase_open_tables;
+
 /** Allowed values of innodb_change_buffering */
 static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
 	"none",		/* IBUF_USE_NONE */
@@ -257,6 +262,7 @@ const struct _ft_vft_ext ft_vft_ext_resu
 #ifdef HAVE_PSI_INTERFACE
 /* Keys to register pthread mutexes/cond in the current file with
 performance schema */
+static mysql_pfs_key_t	innobase_share_mutex_key;
 static mysql_pfs_key_t	commit_threads_m_key;
 static mysql_pfs_key_t	commit_cond_mutex_key;
 static mysql_pfs_key_t	commit_cond_key;
@@ -264,6 +270,7 @@ static mysql_pfs_key_t	commit_cond_key;
 static PSI_mutex_info	all_pthread_mutexes[] = {
 	{&commit_threads_m_key, "commit_threads_m", 0},
 	{&commit_cond_mutex_key, "commit_cond_mutex", 0},
+	{&innobase_share_mutex_key, "innobase_share_mutex", 0}
 };
 
 static PSI_cond_info	all_innodb_conds[] = {
@@ -620,6 +627,23 @@ static SHOW_VAR innodb_status_variables[
   {NullS, NullS, SHOW_LONG}
 };
 
+/************************************************************************//**
+Handling the shared INNOBASE_SHARE structure that is needed to provide table
+locking. Register the table name if it doesn't exist in the hash table. */
+static
+INNOBASE_SHARE*
+get_share(
+/*======*/
+	const char*	table_name);	/*!< in: table to lookup */
+
+/************************************************************************//**
+Free the shared object that was registered with get_share(). */
+static
+void
+free_share(
+/*=======*/
+	INNOBASE_SHARE*	share);		/*!< in/own: share to free */
+
 /*****************************************************************//**
 Frees a possible InnoDB trx object associated with the current THD.
 @return	0 or error number */
@@ -3088,6 +3112,10 @@ innobase_change_buffering_inited_ok:
 
 	ibuf_max_size_update(innobase_change_buffer_max_size);
 
+	innobase_open_tables = hash_create(200);
+	mysql_mutex_init(innobase_share_mutex_key,
+			 &innobase_share_mutex,
+			 MY_MUTEX_INIT_FAST);
 	mysql_mutex_init(commit_threads_m_key,
 			 &commit_threads_m, MY_MUTEX_INIT_FAST);
 	mysql_mutex_init(commit_cond_mutex_key,
@@ -3146,11 +3174,14 @@ innobase_end(
 		srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 
 		innodb_inited = 0;
+		hash_table_free(innobase_open_tables);
+		innobase_open_tables = NULL;
 		if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 			err = 1;
 		}
 		srv_free_paths_and_sizes();
 		my_free(internal_innobase_data_file_path);
+		mysql_mutex_destroy(&innobase_share_mutex);
 		mysql_mutex_destroy(&commit_threads_m);
 		mysql_mutex_destroy(&commit_cond_m);
 		mysql_cond_destroy(&commit_cond);
@@ -4173,8 +4204,8 @@ innobase_match_index_columns(
 }
 
 /*******************************************************************//**
-This function builds a translation table in Innobase_share
-object for fast index location with mysql array number from its
+This function builds a translation table in INNOBASE_SHARE
+structure for fast index location with mysql array number from its
 table->key_info structure. This also provides the necessary translation
 between the key order in mysql key_info and Innodb ib_table->indexes if
 they are not fully matched with each other.
@@ -4191,7 +4222,7 @@ innobase_build_index_translation(
 					dictionary */
 	dict_table_t*		ib_table,/*!< in: table in Innodb data
 					dictionary */
-	Innobase_share*		share)	/*!< in/out: share object
+	INNOBASE_SHARE*		share)	/*!< in/out: share structure
 					where index translation table
 					will be constructed in. */
 {
@@ -4311,7 +4342,7 @@ static
 dict_index_t*
 innobase_index_lookup(
 /*==================*/
-	Innobase_share*	share,	/*!< in: share object for index
+	INNOBASE_SHARE*	share,	/*!< in: share structure for index
 				translation table. */
 	uint		keynr)	/*!< in: index number for the requested
 				index */
@@ -4466,7 +4497,7 @@ ha_innobase::open(
 
 	user_thd = NULL;
 
-	if (!(share=get_share())) {
+	if (!(share=get_share(name))) {
 
 		DBUG_RETURN(1);
 	}
@@ -4579,6 +4610,7 @@ retry:
 			REFMAN "innodb-troubleshooting.html for how "
 			"you can resolve the problem.", norm_name);
 
+		free_share(share);
 		my_errno = ENOENT;
 
 		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
@@ -4623,6 +4655,7 @@ table_opened:
 	}
 
 	if (!thd_tablespace_op(thd) && no_tablespace) {
+		free_share(share);
 		my_errno = ENOENT;
 
 		dict_table_close(ib_table, FALSE, FALSE);
@@ -4858,6 +4891,8 @@ ha_innobase::close()
 		upd_buf_size = 0;
 	}
 
+	free_share(share);
+
 	MONITOR_INC(MONITOR_TABLE_CLOSE);
 
 	/* Tell InnoDB server that there might be work for
@@ -10163,7 +10198,7 @@ static
 int
 innobase_get_mysql_key_number_for_index(
 /*====================================*/
-	Innobase_share*		share,	/*!< in: share object for index
+	INNOBASE_SHARE*		share,	/*!< in: share structure for index
 					translation table. */
 	const TABLE*		table,	/*!< in: table in MySQL data
 					dictionary */
@@ -12143,31 +12178,94 @@ innobase_show_status(
 }
 
 /************************************************************************//**
-Handling the shared Innobase_share object that is needed to provide table
-locking. */
-Innobase_share*
-ha_innobase::get_share(void)
-/*========================*/
+Handling the shared INNOBASE_SHARE structure that is needed to provide table
+locking. Register the table name if it doesn't exist in the hash table. */
+static
+INNOBASE_SHARE*
+get_share(
+/*======*/
+	const char*	table_name)
 {
-	Innobase_share *tmp_share;
+	INNOBASE_SHARE*	share;
 
-	lock_shared_ha_data();
-	tmp_share= static_cast<Innobase_share*>(get_ha_share_ptr());
+	mysql_mutex_lock(&innobase_share_mutex);
 
-	if (!tmp_share)
-	{
-		tmp_share= new Innobase_share;
-		if (!tmp_share)
-		{
-			unlock_shared_ha_data();
-			return(NULL);
-		}
+	ulint	fold = ut_fold_string(table_name);
+
+	HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
+		    INNOBASE_SHARE*, share,
+		    ut_ad(share->use_count > 0),
+		    !strcmp(share->table_name, table_name));
+
+	if (!share) {
+
+		uint length = (uint) strlen(table_name);
+
+		/* TODO: invoke HASH_MIGRATE if innobase_open_tables
+		grows too big */
+
+		share = (INNOBASE_SHARE*) my_malloc(sizeof(*share)+length+1,
+			MYF(MY_FAE | MY_ZEROFILL));
+
+		share->table_name = (char*) memcpy(share + 1,
+						   table_name, length + 1);
+
+		HASH_INSERT(INNOBASE_SHARE, table_name_hash,
+			    innobase_open_tables, fold, share);
 
-		set_ha_share_ptr(static_cast<Handler_share*>(tmp_share));
+		thr_lock_init(&share->lock);
+
+		/* Index translation table initialization */
+		share->idx_trans_tbl.index_mapping = NULL;
+		share->idx_trans_tbl.index_count = 0;
+		share->idx_trans_tbl.array_size = 0;
+	}
+
+	share->use_count++;
+	mysql_mutex_unlock(&innobase_share_mutex);
+
+	return(share);
+}
+
+/************************************************************************//**
+Free the shared object that was registered with get_share(). */
+static
+void
+free_share(
+/*=======*/
+	INNOBASE_SHARE*	share)	/*!< in/own: table share to free */
+{
+	mysql_mutex_lock(&innobase_share_mutex);
+
+#ifdef UNIV_DEBUG
+	INNOBASE_SHARE* share2;
+	ulint	fold = ut_fold_string(share->table_name);
+
+	HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
+		    INNOBASE_SHARE*, share2,
+		    ut_ad(share->use_count > 0),
+		    !strcmp(share->table_name, share2->table_name));
+
+	ut_a(share2 == share);
+#endif /* UNIV_DEBUG */
+
+	if (!--share->use_count) {
+		ulint	fold = ut_fold_string(share->table_name);
+
+		HASH_DELETE(INNOBASE_SHARE, table_name_hash,
+			    innobase_open_tables, fold, share);
+		thr_lock_delete(&share->lock);
+
+		/* Free any memory from index translation table */
+		my_free(share->idx_trans_tbl.index_mapping);
+
+		my_free(share);
+
+		/* TODO: invoke HASH_MIGRATE if innobase_open_tables
+		shrinks too much */
 	}
-	unlock_shared_ha_data();
-	ut_ad(tmp_share);
-	return(tmp_share);
+
+	mysql_mutex_unlock(&innobase_share_mutex);
 }
 
 /*****************************************************************//**

=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h	revid:mayank.prasad@stripped
+++ b/storage/innobase/handler/ha_innodb.h	revid:mattias.jonsson@stripped
@@ -38,29 +38,19 @@ typedef struct innodb_idx_translate_stru
 
 
 /** InnoDB table share */
-class Innobase_share : public Handler_share
-{
-public:
+typedef struct st_innobase_share {
 	THR_LOCK		lock;		/*!< MySQL lock protecting
 						this structure */
+	const char*		table_name;	/*!< InnoDB table name */
+	uint			use_count;	/*!< reference count,
+						incremented in get_share()
+						and decremented in
+						free_share() */
+	void*			table_name_hash;/*!< hash table chain node */
 	innodb_idx_translate_t	idx_trans_tbl;	/*!< index translation
 						table between MySQL and
 						Innodb */
-	Innobase_share()
-	{
-		thr_lock_init(&lock);
-		idx_trans_tbl.index_mapping = NULL;
-		idx_trans_tbl.index_count = 0;
-		idx_trans_tbl.array_size = 0;
-	}
-	~Innobase_share()
-	{
-		thr_lock_delete(&lock);
-
-		/* Free any memory from index translation table */
-		my_free(idx_trans_tbl.index_mapping);
-	}
-};
+} INNOBASE_SHARE;
 
 
 /** InnoDB B-tree index */
@@ -83,7 +73,7 @@ class ha_innobase: public handler
 					currently using the handle; this is
 					set in external_lock function */
 	THR_LOCK_DATA	lock;
-	Innobase_share*	share;		/*!< information for MySQL
+	INNOBASE_SHARE*	share;		/*!< information for MySQL
 					table locking */
 
 	uchar*		upd_buf;	/*!< buffer used in updates */
@@ -361,8 +351,6 @@ public:
 private:
 	/** The multi range read session object */
 	DsMrr_impl ds_mrr;
-	/** Connects/gets Innobase_share in TABLE_SHARE */
-	Innobase_share* get_share();
 	/* @} */
 };
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (mattias.jonsson:3901 to 3902) Bug#13838761WL#4305Mattias Jonsson27 May