#At file:///home/marko/innobase/dev/mysql2a/5.1-innodb/ based on revid:sunny.bains@stripped2hnj8zztsu2
3549 Marko Mäkelä 2010-08-23
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:sunny.bains@stripped4943-8w1yw2hnj8zztsu2
+++ b/storage/innobase/dict/dict0dict.c revid:marko.makela@strippedqis2ley36
@@ -3753,7 +3753,6 @@ dict_update_statistics_low(
dictionary mutex */
{
dict_index_t* index;
- ulint size;
ulint sum_of_index_sizes = 0;
if (table->ibd_file_missing) {
@@ -3769,14 +3768,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 */
@@ -3788,26 +3779,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
+ && (index->type & DICT_CLUSTERED)))) {
+ 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:sunny.bains@stripped0100820074943-8w1yw2hnj8zztsu2
+++ b/storage/innobase/handler/ha_innodb.cc revid:marko.makela@stripped02854-t1clrojqis2ley36
@@ -6365,8 +6365,6 @@ ha_innobase::info(
dict_index_t* index;
ha_rows rec_per_key;
ib_longlong n_rows;
- ulong j;
- ulong i;
char path[FN_REFLEN];
os_file_stat_t stat_info;
@@ -6376,16 +6374,6 @@ ha_innobase::info(
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. */
@@ -6480,11 +6468,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 {
ullint avail_space;
avail_space = fsp_get_available_space_in_free_extents(
@@ -6522,6 +6517,7 @@ ha_innobase::info(
}
if (flag & HA_STATUS_CONST) {
+ ulong i = 0;
index = dict_table_get_first_index_noninline(ib_table);
if (prebuilt->clust_index_was_generated) {
@@ -6529,6 +6525,8 @@ ha_innobase::info(
}
for (i = 0; i < table->s->keys; i++) {
+ ulong j;
+
if (index == NULL) {
sql_print_error("Table %s contains fewer "
"indexes inside InnoDB than "
@@ -6585,6 +6583,11 @@ ha_innobase::info(
}
}
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ goto func_exit;
+ }
+
if (flag & HA_STATUS_ERRKEY) {
ut_a(prebuilt->trx);
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
@@ -6597,6 +6600,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-20100823102854-t1clrojqis2ley36.bundle
Thread |
---|
• bzr commit into mysql-5.1-innodb branch (marko.makela:3549) Bug#55832 | marko.makela | 23 Aug |