List:Commits« Previous MessageNext Message »
From:marko.makela Date:August 24 2010 8:34am
Subject:bzr commit into mysql-5.5-innodb branch (marko.makela:3170) Bug#55832
View as plain text  
#At file:///home/marko/innobase/dev/mysql2a/5.5-innodb/ based on revid:inaam.rana@strippedflh3ymvwau

 3170 Marko Mäkelä	2010-08-24
      Merge Bug#55832 fix from mysql-5.1-innodb:
      ------------------------------------------------------------
      revno: 3550
      revision-id: marko.makela@stripped4081003-v4ecy0tga99cpxw2
      parent: marko.makela@oracle.com-20100823102854-t1clrojqis2ley36
      committer: Marko Mäkelä <marko.makela@stripped>
      branch nick: 5.1-innodb
      timestamp: Tue 2010-08-24 11:10:03 +0300
      message:
        Bug#55832: selects crash too easily when innodb_force_recovery>3
      
        dict_update_statistics_low(): Create bogus statistics for those
        indexes that cannot be accessed because of the innodb_force_recovery
        setting.
      
        ha_innobase::info(): Calculate statistics for each index, even if
        innodb_force_recovery is set. Fill in bogus data for those indexes
        that are not accessed because of the innodb_force_recovery setting.

    modified:
      storage/innobase/dict/dict0dict.c
      storage/innobase/handler/ha_innodb.cc
=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c	revid:inaam.rana@strippedymvwau
+++ b/storage/innobase/dict/dict0dict.c	revid:marko.makela@stripped
@@ -4206,7 +4206,6 @@ dict_update_statistics_low(
 					dictionary mutex */
 {
 	dict_index_t*	index;
-	ulint		size;
 	ulint		sum_of_index_sizes	= 0;
 
 	if (table->ibd_file_missing) {
@@ -4221,14 +4220,6 @@ dict_update_statistics_low(
 		return;
 	}
 
-	/* If we have set a high innodb_force_recovery level, do not calculate
-	statistics, as a badly corrupted index can cause a crash in it. */
-
-	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
-
-		return;
-	}
-
 	/* Find out the sizes of the indexes and how many different values
 	for the key they approximately have */
 
@@ -4240,26 +4231,48 @@ dict_update_statistics_low(
 		return;
 	}
 
-	while (index) {
-		size = btr_get_size(index, BTR_TOTAL_SIZE);
-
-		index->stat_index_size = size;
 
-		sum_of_index_sizes += size;
-
-		size = btr_get_size(index, BTR_N_LEAF_PAGES);
-
-		if (size == 0) {
-			/* The root node of the tree is a leaf */
-			size = 1;
+	do {
+		if (UNIV_LIKELY
+		    (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
+		     || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
+			 && dict_index_is_clust(index)))) {
+			ulint	size;
+			size = btr_get_size(index, BTR_TOTAL_SIZE);
+
+			index->stat_index_size = size;
+
+			sum_of_index_sizes += size;
+
+			size = btr_get_size(index, BTR_N_LEAF_PAGES);
+
+			if (size == 0) {
+				/* The root node of the tree is a leaf */
+				size = 1;
+			}
+
+			index->stat_n_leaf_pages = size;
+
+			btr_estimate_number_of_different_key_vals(index);
+		} else {
+			/* If we have set a high innodb_force_recovery
+			level, do not calculate statistics, as a badly
+			corrupted index can cause a crash in it.
+			Initialize some bogus index cardinality
+			statistics, so that the data can be queried in
+			various means, also via secondary indexes. */
+			ulint	i;
+
+			sum_of_index_sizes++;
+			index->stat_index_size = index->stat_n_leaf_pages = 1;
+
+			for (i = dict_index_get_n_unique(index); i; ) {
+				index->stat_n_diff_key_vals[i--] = 1;
+			}
 		}
 
-		index->stat_n_leaf_pages = size;
-
-		btr_estimate_number_of_different_key_vals(index);
-
 		index = dict_table_get_next_index(index);
-	}
+	} while (index);
 
 	index = dict_table_get_first_index(table);
 

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	revid:inaam.rana@strippedflh3ymvwau
+++ b/storage/innobase/handler/ha_innodb.cc	revid:marko.makela@strippedzu
@@ -7700,28 +7700,15 @@ ha_innobase::info(
 	dict_index_t*	index;
 	ha_rows		rec_per_key;
 	ib_int64_t	n_rows;
-	ulong		j;
-	ulong		i;
 	char		path[FN_REFLEN];
 	os_file_stat_t	stat_info;
 
-
 	DBUG_ENTER("info");
 
 	/* If we are forcing recovery at a high level, we will suppress
 	statistics calculation on tables, because that may crash the
 	server if an index is badly corrupted. */
 
-	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
-
-		/* We return success (0) instead of HA_ERR_CRASHED,
-		because we want MySQL to process this query and not
-		stop, like it would do if it received the error code
-		HA_ERR_CRASHED. */
-
-		DBUG_RETURN(0);
-	}
-
 	/* We do not know if MySQL can call this function before calling
 	external_lock(). To be safe, update the thd of the current table
 	handle. */
@@ -7816,12 +7803,18 @@ ha_innobase::info(
 		acquiring latches inside InnoDB, we do not call it if we
 		are asked by MySQL to avoid locking. Another reason to
 		avoid the call is that it uses quite a lot of CPU.
-		See Bug#38185.
-		We do not update delete_length if no locking is requested
-		so the "old" value can remain. delete_length is initialized
-		to 0 in the ha_statistics' constructor. */
-		if (!(flag & HA_STATUS_NO_LOCK)) {
-
+		See Bug#38185. */
+		if (flag & HA_STATUS_NO_LOCK) {
+			/* We do not update delete_length if no
+			locking is requested so the "old" value can
+			remain. delete_length is initialized to 0 in
+			the ha_statistics' constructor. */
+		} else if (UNIV_UNLIKELY
+			   (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE)) {
+			/* Avoid accessing the tablespace if
+			innodb_crash_recovery is set to a high value. */
+			stats.delete_length = 0;
+		} else {
 			/* lock the data dictionary to avoid races with
 			ibd_file_missing and tablespace_discarded */
 			row_mysql_lock_data_dictionary(prebuilt->trx);
@@ -7866,6 +7859,7 @@ ha_innobase::info(
 	}
 
 	if (flag & HA_STATUS_CONST) {
+		ulong	i;
 		/* Verify the number of index in InnoDB and MySQL
 		matches up. If prebuilt->clust_index_was_generated
 		holds, InnoDB defines GEN_CLUST_INDEX internally */
@@ -7882,6 +7876,7 @@ ha_innobase::info(
 		}
 
 		for (i = 0; i < table->s->keys; i++) {
+			ulong	j;
 			/* We could get index quickly through internal
 			index mapping with the index translation table.
 			The identity of index (match up index name with
@@ -7947,6 +7942,11 @@ ha_innobase::info(
 		}
 	}
 
+	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+		goto func_exit;
+	}
+
 	if (flag & HA_STATUS_ERRKEY) {
 		const dict_index_t*	err_index;
 
@@ -7967,6 +7967,7 @@ ha_innobase::info(
 		stats.auto_increment_value = innobase_peek_autoinc();
 	}
 
+func_exit:
 	prebuilt->trx->op_info = (char*)"";
 
 	DBUG_RETURN(0);

Attachment: [text/bzr-bundle] bzr/marko.makela@oracle.com-20100824083419-ciowjldbt806j5zu.bundle
Thread
bzr commit into mysql-5.5-innodb branch (marko.makela:3170) Bug#55832marko.makela24 Aug