Commit 109893da authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent 54fd56c5
...@@ -3753,7 +3753,6 @@ dict_update_statistics_low( ...@@ -3753,7 +3753,6 @@ dict_update_statistics_low(
dictionary mutex */ dictionary mutex */
{ {
dict_index_t* index; dict_index_t* index;
ulint size;
ulint sum_of_index_sizes = 0; ulint sum_of_index_sizes = 0;
if (table->ibd_file_missing) { if (table->ibd_file_missing) {
...@@ -3769,14 +3768,6 @@ dict_update_statistics_low( ...@@ -3769,14 +3768,6 @@ dict_update_statistics_low(
return; 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 /* Find out the sizes of the indexes and how many different values
for the key they approximately have */ for the key they approximately have */
...@@ -3788,26 +3779,48 @@ dict_update_statistics_low( ...@@ -3788,26 +3779,48 @@ dict_update_statistics_low(
return; return;
} }
while (index) {
size = btr_get_size(index, BTR_TOTAL_SIZE);
index->stat_index_size = size; 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);
sum_of_index_sizes += size; index->stat_index_size = size;
size = btr_get_size(index, BTR_N_LEAF_PAGES); sum_of_index_sizes += size;
if (size == 0) { size = btr_get_size(index, BTR_N_LEAF_PAGES);
/* The root node of the tree is a leaf */
size = 1; 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;
index->stat_n_leaf_pages = size; sum_of_index_sizes++;
index->stat_index_size = index->stat_n_leaf_pages = 1;
btr_estimate_number_of_different_key_vals(index); for (i = dict_index_get_n_unique(index); i; ) {
index->stat_n_diff_key_vals[i--] = 1;
}
}
index = dict_table_get_next_index(index); index = dict_table_get_next_index(index);
} } while (index);
index = dict_table_get_first_index(table); index = dict_table_get_first_index(table);
......
...@@ -6365,8 +6365,6 @@ ha_innobase::info( ...@@ -6365,8 +6365,6 @@ ha_innobase::info(
dict_index_t* index; dict_index_t* index;
ha_rows rec_per_key; ha_rows rec_per_key;
ib_longlong n_rows; ib_longlong n_rows;
ulong j;
ulong i;
char path[FN_REFLEN]; char path[FN_REFLEN];
os_file_stat_t stat_info; os_file_stat_t stat_info;
...@@ -6376,16 +6374,6 @@ ha_innobase::info( ...@@ -6376,16 +6374,6 @@ ha_innobase::info(
statistics calculation on tables, because that may crash the statistics calculation on tables, because that may crash the
server if an index is badly corrupted. */ 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 /* We do not know if MySQL can call this function before calling
external_lock(). To be safe, update the thd of the current table external_lock(). To be safe, update the thd of the current table
handle. */ handle. */
...@@ -6480,11 +6468,18 @@ ha_innobase::info( ...@@ -6480,11 +6468,18 @@ ha_innobase::info(
acquiring latches inside InnoDB, we do not call it if we acquiring latches inside InnoDB, we do not call it if we
are asked by MySQL to avoid locking. Another reason to are asked by MySQL to avoid locking. Another reason to
avoid the call is that it uses quite a lot of CPU. avoid the call is that it uses quite a lot of CPU.
See Bug#38185. See Bug#38185. */
We do not update delete_length if no locking is requested if (flag & HA_STATUS_NO_LOCK) {
so the "old" value can remain. delete_length is initialized /* We do not update delete_length if no
to 0 in the ha_statistics' constructor. */ locking is requested so the "old" value can
if (!(flag & HA_STATUS_NO_LOCK)) { 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; ullint avail_space;
avail_space = fsp_get_available_space_in_free_extents( avail_space = fsp_get_available_space_in_free_extents(
...@@ -6522,6 +6517,7 @@ ha_innobase::info( ...@@ -6522,6 +6517,7 @@ ha_innobase::info(
} }
if (flag & HA_STATUS_CONST) { if (flag & HA_STATUS_CONST) {
ulong i = 0;
index = dict_table_get_first_index_noninline(ib_table); index = dict_table_get_first_index_noninline(ib_table);
if (prebuilt->clust_index_was_generated) { if (prebuilt->clust_index_was_generated) {
...@@ -6529,6 +6525,8 @@ ha_innobase::info( ...@@ -6529,6 +6525,8 @@ ha_innobase::info(
} }
for (i = 0; i < table->s->keys; i++) { for (i = 0; i < table->s->keys; i++) {
ulong j;
if (index == NULL) { if (index == NULL) {
sql_print_error("Table %s contains fewer " sql_print_error("Table %s contains fewer "
"indexes inside InnoDB than " "indexes inside InnoDB than "
...@@ -6585,6 +6583,11 @@ ha_innobase::info( ...@@ -6585,6 +6583,11 @@ ha_innobase::info(
} }
} }
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
goto func_exit;
}
if (flag & HA_STATUS_ERRKEY) { if (flag & HA_STATUS_ERRKEY) {
ut_a(prebuilt->trx); ut_a(prebuilt->trx);
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N); ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
...@@ -6597,6 +6600,7 @@ ha_innobase::info( ...@@ -6597,6 +6600,7 @@ ha_innobase::info(
stats.auto_increment_value = innobase_peek_autoinc(); stats.auto_increment_value = innobase_peek_autoinc();
} }
func_exit:
prebuilt->trx->op_info = (char*)""; prebuilt->trx->op_info = (char*)"";
DBUG_RETURN(0); DBUG_RETURN(0);
......
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