List:Commits« Previous MessageNext Message »
From:vasil.dimov Date:May 25 2012 11:39am
Subject:bzr push into mysql-trunk branch (vasil.dimov:3896 to 3898)
View as plain text  
 3898 Vasil Dimov	2012-05-25
      In dict_stats_analyze_index_for_n_prefix() we could try to dive below
      the supremum in an edge case where the tree has changed in such a way
      that dive_below_idx is the index of the supremum record.
      
      Treat this as if the tree has shrunk a bit more - just quite the scan.

    modified:
      storage/innobase/dict/dict0stats.cc
 3897 Vasil Dimov	2012-05-25
      Use a dedicated trx in dict_stats_drop_index() instead of prebuilt->trx
      because prebuilt->trx is not committed and the following scenario causes
      a lock wait timeout:
      
      SET GLOBAL innodb_stats_persistent=1;
      
      CREATE TABLE t1 (i INT PRIMARY KEY) ENGINE=InnoDB;
      CREATE TABLE t2 (i INT, FOREIGN KEY (i) REFERENCES t1 (i)) ENGINE=InnoDB;
      CREATE INDEX ind2 ON t2(i);
      
      The CREATE INDEX command drops the implicitly added index "i" on t2 and
      tries to add a new index before committing the trx. So we end up with
      DELETE FROM mysql.innodb_index_stats dangling uncommitted and later
      INSERT/UPDATE in another trx by dict_stats_save() which causes lock wait
      timeout.
      
      With this change all code that deals with mysql.innodb_table_stats or
      mysql.innodb_index_stats creates a dedicated trx locally and commits it.

    modified:
      storage/innobase/dict/dict0stats.cc
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/dict0stats.h
 3896 Mayank Prasad	2012-05-25 [merge]
      NUll merge: 5.5->trunk

=== modified file 'storage/innobase/dict/dict0stats.cc'
--- a/storage/innobase/dict/dict0stats.cc	revid:mayank.prasad@stripped
+++ b/storage/innobase/dict/dict0stats.cc	revid:vasil.dimov@stripped
@@ -1249,6 +1249,14 @@ dict_stats_analyze_index_for_n_prefix(
 			break;
 		}
 
+		/* it could be that the tree has changed in such a way that
+		the record under dive_below_idx is the supremum record, in
+		this case rec_idx == dive_below_idx and pcur is positioned
+		on the supremum, we do not want to dive below it */
+		if (!btr_pcur_is_on_user_rec(&pcur)) {
+			break;
+		}
+
 		ut_a(rec_idx == dive_below_idx);
 
 		ib_uint64_t	n_diff_on_leaf_page;
@@ -2706,10 +2714,7 @@ transient:
 /*********************************************************************//**
 Removes the information for a particular index's stats from the persistent
 storage if it exists and if there is data stored for this index.
-The transaction is not committed, it must not be committed in this
-function because this is the user trx that is running DROP INDEX.
-The transaction will be committed at the very end when dropping an
-index.
+This function creates its own trx and commits it.
 A note from Marko why we cannot edit user and sys_* tables in one trx:
 marko: The problem is that ibuf merges should be disabled while we are
 rolling back dict transactions.
@@ -2724,7 +2729,6 @@ dict_stats_drop_index(
 /*==================*/
 	const char*	tname,	/*!< in: table name, e.g. 'db/table' */
 	const char*	iname,	/*!< in: index name */
-	trx_t*		trx,	/*!< in/out: user transaction */
 	char*		errstr, /*!< out: error message if != DB_SUCCESS
 				is returned */
 	ulint		errstr_sz)/*!< in: size of the errstr buffer */
@@ -2734,7 +2738,6 @@ dict_stats_drop_index(
 	pars_info_t*	pinfo;
 	dberr_t		ret;
 	dict_stats_t*	dict_stats;
-	THD*		mysql_thd;
 
 	ut_ad(!mutex_own(&dict_sys->mutex));
 
@@ -2769,11 +2772,10 @@ dict_stats_drop_index(
 
 	pars_info_add_str_literal(pinfo, "index_name", iname);
 
-	/* Force lock wait timeout to be instantaneous because the incoming
-	transaction was created via MySQL. */
+	trx_t*	trx;
 
-	mysql_thd = trx->mysql_thd;
-	trx->mysql_thd = NULL;
+	trx = trx_allocate_for_background();
+	trx_start_if_not_started(trx);
 
 	mutex_enter(&dict_sys->mutex);
 
@@ -2791,11 +2793,13 @@ dict_stats_drop_index(
 
 	mutex_exit(&dict_sys->mutex);
 
-	trx->mysql_thd = mysql_thd;
-
-	/* do not to commit here, see the function's comment */
-
-	if (ret != DB_SUCCESS) {
+	if (ret == DB_SUCCESS) {
+		trx_commit_for_mysql(trx);
+	} else {
+		trx->op_info = "rollback of internal trx on stats tables";
+		trx_rollback_to_savepoint(trx, NULL);
+		trx->op_info = "";
+		ut_a(trx->error_state == DB_SUCCESS);
 
 		ut_snprintf(errstr, errstr_sz,
 			    "Unable to delete statistics for index %s "
@@ -2817,9 +2821,8 @@ dict_stats_drop_index(
 
 		ut_print_timestamp(stderr);
 		fprintf(stderr, " InnoDB: %s\n", errstr);
-
-		trx->error_state = DB_SUCCESS;
 	}
+	trx_free_for_background(trx);
 
 	dict_stats_close(dict_stats);
 

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	revid:mayank.prasad@stripped
+++ b/storage/innobase/handler/handler0alter.cc	revid:vasil.dimov@stripped
@@ -3145,7 +3145,6 @@ trx_commit:
 
 			ret = dict_stats_drop_index(
 				prebuilt->table->name, key->name,
-				prebuilt->trx,
 				errstr, sizeof(errstr));
 
 			if (ret != DB_SUCCESS) {

=== modified file 'storage/innobase/include/dict0stats.h'
--- a/storage/innobase/include/dict0stats.h	revid:mayank.prasad@stripped
+++ b/storage/innobase/include/dict0stats.h	revid:vasil.dimov@stripped
@@ -120,10 +120,7 @@ dict_stats_update(
 /*********************************************************************//**
 Removes the information for a particular index's stats from the persistent
 storage if it exists and if there is data stored for this index.
-The transaction is not committed, it must not be committed in this
-function because this is the user trx that is running DROP INDEX.
-The transaction will be committed at the very end when dropping an
-index.
+This function creates its own trx and commits it.
 @return DB_SUCCESS or error code */
 UNIV_INTERN
 dberr_t
@@ -131,7 +128,6 @@ dict_stats_drop_index(
 /*==================*/
 	const char*	tname,	/*!< in: table name */
 	const char*	iname,	/*!< in: index name */
-	trx_t*		trx,	/*!< in/out: user transaction */
 	char*		errstr, /*!< out: error message if != DB_SUCCESS
 				is returned */
 	ulint		errstr_sz);/*!< in: size of the errstr buffer */

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (vasil.dimov:3896 to 3898) vasil.dimov25 May