Index: srv/srv0srv.c =================================================================== --- srv/srv0srv.c (revision 4681) +++ srv/srv0srv.c (working copy) @@ -253,12 +253,18 @@ ulint srv_buf_pool_reads = 0; /* variable to count the number of sequential read-aheads */ ulint srv_read_ahead_seq = 0; /* variable to count the number of random read-aheads */ ulint srv_read_ahead_rnd = 0; +/* An option to enable the fix for "Bug#43660 SHOW INDEXES/ANALYZE does +NOT update cardinality for indexes of InnoDB table". By default we are +running with the fix disabled because MySQL 5.1 is frozen for such +behavioral changes. */ +char srv_use_legacy_cardinality_algorithm = TRUE; + /* structure to pass status variables to MySQL */ export_struc export_vars; /* If the following is != 0 we do not allow inserts etc. This protects the user from forgetting the innodb_force_recovery keyword to my.cnf */ Index: handler/ha_innodb.cc =================================================================== --- handler/ha_innodb.cc (revision 4681) +++ handler/ha_innodb.cc (working copy) @@ -8258,12 +8258,20 @@ static MYSQL_SYSVAR_BOOL(status_file, in static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata, PLUGIN_VAR_OPCMDARG, "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)", NULL, NULL, TRUE); +static MYSQL_SYSVAR_BOOL(use_legacy_cardinality_algorithm, + srv_use_legacy_cardinality_algorithm, + PLUGIN_VAR_OPCMDARG, + "Use legacy algorithm for picking random pages during index cardinality " + "estimation. Disable this to use a better algorithm, but note that your " + "query plans may change (enabled by default).", + NULL, NULL, TRUE); + static MYSQL_SYSVAR_BOOL(adaptive_hash_index, innobase_adaptive_hash_index, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "Enable InnoDB adaptive hash index (enabled by default). " "Disable with --skip-innodb-adaptive-hash-index.", NULL, NULL, TRUE); @@ -8393,12 +8401,13 @@ static struct st_mysql_sys_var* innobase MYSQL_SYSVAR(max_dirty_pages_pct), MYSQL_SYSVAR(max_purge_lag), MYSQL_SYSVAR(mirrored_log_groups), MYSQL_SYSVAR(open_files), MYSQL_SYSVAR(rollback_on_timeout), MYSQL_SYSVAR(stats_on_metadata), + MYSQL_SYSVAR(use_legacy_cardinality_algorithm), MYSQL_SYSVAR(adaptive_hash_index), MYSQL_SYSVAR(status_file), MYSQL_SYSVAR(support_xa), MYSQL_SYSVAR(sync_spin_loops), MYSQL_SYSVAR(table_locks), MYSQL_SYSVAR(thread_concurrency), Index: include/srv0srv.h =================================================================== --- include/srv0srv.h (revision 4681) +++ include/srv0srv.h (working copy) @@ -232,12 +232,18 @@ extern ulint srv_buf_pool_reads; /* variable to count the number of sequential read-aheads were done */ extern ulint srv_read_ahead_seq; /* variable to count the number of random read-aheads were done */ extern ulint srv_read_ahead_rnd; +/* An option to enable the fix for "Bug#43660 SHOW INDEXES/ANALYZE does +NOT update cardinality for indexes of InnoDB table". By default we are +running with the fix disabled because MySQL 5.1 is frozen for such +behavioral changes. */ +extern char srv_use_legacy_cardinality_algorithm; + /* In this structure we store status variables to be passed to MySQL */ typedef struct export_var_struct export_struc; extern export_struc export_vars; typedef struct srv_sys_struct srv_sys_t; Index: page/page0cur.c =================================================================== --- page/page0cur.c (revision 4681) +++ page/page0cur.c (working copy) @@ -12,20 +12,60 @@ Created 10/4/1994 Heikki Tuuri #endif #include "rem0cmp.h" #include "mtr0log.h" #include "log0recv.h" #include "rem0cmp.h" +#include "srv0srv.h" +#include "ut0ut.h" static ulint page_rnd = 976722341; #ifdef PAGE_CUR_ADAPT # ifdef UNIV_SEARCH_PERF_STAT ulint page_cur_short_succ = 0; # endif /* UNIV_SEARCH_PERF_STAT */ +/*********************************************************************** +This is a linear congruential generator PRNG. Returns a pseudo random +number between 0 and 2^64-1 inclusive. The formula and the constants +being used are: +X[n+1] = (a * X[n] + c) mod m +where: +X[0] = ut_usectime() +a = 1103515245 (3^5 * 5 * 7 * 129749) +c = 12345 (3 * 5 * 823) +m = 18446744073709551616 (2^64) +*/ +#define LCG_a 1103515245 +#define LCG_c 12345 +static +unsigned long long +page_cur_lcg_prng() +/*===============*/ + /* out: number between 0 and 2^64-1 */ +{ + static unsigned long long lcg_current = 0; + static ibool initialized = FALSE; + ulint time_sec; + ulint time_ms; + + if (!initialized) { + ut_usectime(&time_sec, &time_ms); + lcg_current = (unsigned long long) (time_sec * 1000000 + + time_ms); + initialized = TRUE; + } + + /* no need to "% 2^64" explicitly because lcg_current is + 64 bit and this will be done anyway */ + lcg_current = LCG_a * lcg_current + LCG_c; + + return(lcg_current); +} + /******************************************************************** Tries a search shortcut based on the last insert. */ UNIV_INLINE ibool page_cur_try_search_shortcut( /*=========================*/ @@ -490,15 +530,19 @@ page_cur_open_on_rnd_user_rec( if (page_get_n_recs(page) == 0) { page_cur_position(page_get_infimum_rec(page), cursor); return; } - page_rnd += 87584577; + if (srv_use_legacy_cardinality_algorithm) { + page_rnd += 87584577; - rnd = page_rnd % page_get_n_recs(page); + rnd = page_rnd % page_get_n_recs(page); + } else { + rnd = (ulint) page_cur_lcg_prng() % page_get_n_recs(page); + } rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); while (rnd > 0) { @@ -1434,6 +1478,33 @@ page_cur_delete_rec( slots. */ if (cur_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED) { page_dir_balance_slot(page, cur_slot_no); } } + +#ifdef UNIV_COMPILE_TEST_FUNCS + +/*********************************************************************** +Print the first n numbers, generated by page_cur_lcg_prng() to make sure +(visually) that it works properly. */ +void +test_page_cur_lcg_prng( +/*===================*/ + int n) /* in: print first n numbers */ +{ + int i; + unsigned long long rnd; + + for (i = 0; i < n; i++) { + rnd = page_cur_lcg_prng(); + printf("%llu\t%%2=%llu %%3=%llu %%5=%llu %%7=%llu %%11=%llu\n", + rnd, + rnd % 2, + rnd % 3, + rnd % 5, + rnd % 7, + rnd % 11); + } +} + +#endif /* UNIV_COMPILE_TEST_FUNCS */