80
80
/** Identifies generated InnoDB foreign key names */
81
81
static char dict_ibfk[] = "_ibfk_";
83
/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
84
#define DICT_INDEX_STAT_MUTEX_SIZE 32
85
static mutex_t dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
83
/** array of rw locks protecting
84
dict_table_t::stat_initialized
85
dict_table_t::stat_n_rows (*)
86
dict_table_t::stat_clustered_index_size
87
dict_table_t::stat_sum_of_other_index_sizes
88
dict_table_t::stat_modified_counter (*)
89
dict_table_t::indexes*::stat_n_diff_key_vals[]
90
dict_table_t::indexes*::stat_index_size
91
dict_table_t::indexes*::stat_n_leaf_pages
92
(*) those are not always protected for performance reasons */
93
#define DICT_TABLE_STATS_LATCHES_SIZE 64
94
static rw_lock_t dict_table_stats_latches[DICT_TABLE_STATS_LATCHES_SIZE];
87
96
/*******************************************************************//**
88
97
Tries to find column names for the index and sets the col field of the
243
252
mutex_exit(&(dict_sys->mutex));
246
/** Get the mutex that protects index->stat_n_diff_key_vals[] */
247
#define GET_INDEX_STAT_MUTEX(index) \
248
(&dict_index_stat_mutex[ut_fold_dulint(index->id) \
249
% DICT_INDEX_STAT_MUTEX_SIZE])
255
/** Get the latch that protects the stats of a given table */
256
#define GET_TABLE_STATS_LATCH(table) \
257
(&dict_table_stats_latches[ut_fold_dulint(table->id) \
258
% DICT_TABLE_STATS_LATCHES_SIZE])
251
260
/**********************************************************************//**
252
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
253
index->id is used to pick the right mutex and it should not change
254
before dict_index_stat_mutex_exit() is called on this index. */
261
Lock the appropriate latch to protect a given table's statistics.
262
table->id is used to pick the corresponding latch from a global array of
257
dict_index_stat_mutex_enter(
258
/*========================*/
259
const dict_index_t* index) /*!< in: index */
266
dict_table_stats_lock(
267
/*==================*/
268
const dict_table_t* table, /*!< in: table */
269
ulint latch_mode) /*!< in: RW_S_LATCH or
261
ut_ad(index != NULL);
262
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
263
ut_ad(index->cached);
264
ut_ad(!index->to_be_dropped);
272
ut_ad(table != NULL);
273
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
266
mutex_enter(GET_INDEX_STAT_MUTEX(index));
275
switch (latch_mode) {
277
rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
280
rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
269
289
/**********************************************************************//**
270
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
290
Unlock the latch that has been locked by dict_table_stats_lock() */
273
dict_index_stat_mutex_exit(
274
/*=======================*/
275
const dict_index_t* index) /*!< in: index */
293
dict_table_stats_unlock(
294
/*====================*/
295
const dict_table_t* table, /*!< in: table */
296
ulint latch_mode) /*!< in: RW_S_LATCH or
277
ut_ad(index != NULL);
278
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
279
ut_ad(index->cached);
280
ut_ad(!index->to_be_dropped);
299
ut_ad(table != NULL);
300
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
282
mutex_exit(GET_INDEX_STAT_MUTEX(index));
302
switch (latch_mode) {
304
rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
307
rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
285
316
/********************************************************************//**
569
600
dict_table_t* table;
571
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
572
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
602
if (trx->dict_operation_lock_mode == RW_X_LATCH) {
574
604
/* Note: An X latch implies that the transaction
575
605
already owns the dictionary mutex. */
670
700
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
672
for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
673
mutex_create(&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
702
for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
703
rw_lock_create(&dict_table_stats_latches[i], SYNC_INDEX_TREE);
701
731
mutex_exit(&(dict_sys->mutex));
703
733
if (table != NULL) {
704
if (!table->stat_initialized) {
705
/* If table->ibd_file_missing == TRUE, this will
706
print an error message and return without doing
708
dict_update_statistics(table);
734
/* If table->ibd_file_missing == TRUE, this will
735
print an error message and return without doing
737
dict_update_statistics(table, TRUE /* only update stats
738
if they have not been initialized */);
4184
4213
are used in query optimization. */
4187
dict_update_statistics_low(
4188
/*=======================*/
4216
dict_update_statistics(
4217
/*===================*/
4189
4218
dict_table_t* table, /*!< in/out: table */
4190
ibool has_dict_mutex __attribute__((unused)))
4191
/*!< in: TRUE if the caller has the
4219
ibool only_calc_if_missing_stats)/*!< in: only
4220
update/recalc the stats if they have
4221
not been initialized yet, otherwise
4194
4224
dict_index_t* index;
4196
4225
ulint sum_of_index_sizes = 0;
4198
4227
if (table->ibd_file_missing) {
4210
/* If we have set a high innodb_force_recovery level, do not calculate
4211
statistics, as a badly corrupted index can cause a crash in it. */
4213
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
4218
4239
/* Find out the sizes of the indexes and how many different values
4219
4240
for the key they approximately have */
4230
size = btr_get_size(index, BTR_TOTAL_SIZE);
4232
index->stat_index_size = size;
4234
sum_of_index_sizes += size;
4236
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4239
/* The root node of the tree is a leaf */
4250
dict_table_stats_lock(table, RW_X_LATCH);
4252
if (only_calc_if_missing_stats && table->stat_initialized) {
4253
dict_table_stats_unlock(table, RW_X_LATCH);
4259
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
4260
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
4261
&& dict_index_is_clust(index)))) {
4263
size = btr_get_size(index, BTR_TOTAL_SIZE);
4265
index->stat_index_size = size;
4267
sum_of_index_sizes += size;
4269
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4272
/* The root node of the tree is a leaf */
4276
index->stat_n_leaf_pages = size;
4278
btr_estimate_number_of_different_key_vals(index);
4280
/* If we have set a high innodb_force_recovery
4281
level, do not calculate statistics, as a badly
4282
corrupted index can cause a crash in it.
4283
Initialize some bogus index cardinality
4284
statistics, so that the data can be queried in
4285
various means, also via secondary indexes. */
4288
sum_of_index_sizes++;
4289
index->stat_index_size = index->stat_n_leaf_pages = 1;
4291
for (i = dict_index_get_n_unique(index); i; ) {
4292
index->stat_n_diff_key_vals[i--] = 1;
4243
index->stat_n_leaf_pages = size;
4245
btr_estimate_number_of_different_key_vals(index);
4247
4296
index = dict_table_get_next_index(index);
4250
4299
index = dict_table_get_first_index(table);
4252
dict_index_stat_mutex_enter(index);
4254
4301
table->stat_n_rows = index->stat_n_diff_key_vals[
4255
4302
dict_index_get_n_unique(index)];
4257
dict_index_stat_mutex_exit(index);
4259
4304
table->stat_clustered_index_size = index->stat_index_size;
4261
4306
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4264
4309
table->stat_initialized = TRUE;
4266
4311
table->stat_modified_counter = 0;
4269
/*********************************************************************//**
4270
Calculates new estimates for table and index statistics. The statistics
4271
are used in query optimization. */
4274
dict_update_statistics(
4275
/*===================*/
4276
dict_table_t* table) /*!< in/out: table */
4278
dict_update_statistics_low(table, FALSE);
4313
dict_table_stats_unlock(table, RW_X_LATCH);
4281
4316
/**********************************************************************//**
4356
4391
ut_ad(mutex_own(&(dict_sys->mutex)));
4358
dict_update_statistics_low(table, TRUE);
4393
dict_update_statistics(table, FALSE /* update even if initialized */);
4395
dict_table_stats_lock(table, RW_S_LATCH);
4360
4397
fprintf(stderr,
4361
4398
"--------------------------------------\n"
4442
4478
n_vals = index->stat_n_diff_key_vals[1];
4445
dict_index_stat_mutex_exit(index);
4447
if (dict_index_is_clust(index)) {
4448
type_string = "clustered index";
4449
} else if (dict_index_is_unique(index)) {
4450
type_string = "unique index";
4452
type_string = "secondary index";
4455
4481
fprintf(stderr,
4456
4482
" INDEX: name %s, id %lu %lu, fields %lu/%lu,"
4457
4483
" uniq %lu, type %lu\n"
4795
4821
dict_table_replace_index_in_foreign_list(
4796
4822
/*=====================================*/
4797
4823
dict_table_t* table, /*!< in/out: table */
4798
dict_index_t* index) /*!< in: index to be replaced */
4824
dict_index_t* index, /*!< in: index to be replaced */
4825
const trx_t* trx) /*!< in: transaction handle */
4800
4827
dict_foreign_t* foreign;
4806
4833
if (foreign->foreign_index == index) {
4807
4834
dict_index_t* new_index
4808
4835
= dict_foreign_find_equiv_index(foreign);
4837
/* There must exist an alternative index if
4838
check_foreigns (FOREIGN_KEY_CHECKS) is on,
4839
since ha_innobase::prepare_drop_index had done
4840
the check before we reach here. */
4842
ut_a(new_index || !trx->check_foreigns);
4811
4844
foreign->foreign_index = new_index;