diff options
author | Sergei Golubchik <sergii@pisem.net> | 2014-05-07 17:33:33 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2014-05-07 17:33:33 +0200 |
commit | a2807e41e8fcac00711cf4465e910327bfd69fe2 (patch) | |
tree | c94b0a32226b09e8675f8b9b559a610c554cda6b /storage/xtradb/dict | |
parent | 8ee9d19607d84aeebf97b704a19453f6a772299b (diff) | |
parent | 6cb3146af896eb7d27aed6815428008f105e8ae8 (diff) | |
download | mariadb-git-a2807e41e8fcac00711cf4465e910327bfd69fe2.tar.gz |
xtradb 5.6.17-65.0
Diffstat (limited to 'storage/xtradb/dict')
-rw-r--r-- | storage/xtradb/dict/dict0dict.cc | 9 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0load.cc | 3 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0stats.cc | 181 |
3 files changed, 134 insertions, 59 deletions
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 5cc013b7d6b..1aa40f92836 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -6229,9 +6229,8 @@ dict_fs2utf8( db[db_len] = '\0'; strconvert( - &my_charset_filename, db, db_len, - system_charset_info, db_utf8, db_utf8_size, - &errors); + &my_charset_filename, db, db_len, system_charset_info, + db_utf8, static_cast<uint>(db_utf8_size), &errors); /* convert each # to @0023 in table name and store the result in buf */ const char* table = dict_remove_db_name(db_and_table); @@ -6256,8 +6255,8 @@ dict_fs2utf8( errors = 0; strconvert( - &my_charset_filename, buf, buf_p - buf, - system_charset_info, table_utf8, table_utf8_size, + &my_charset_filename, buf, buf_p - buf, system_charset_info, + table_utf8, static_cast<uint>(table_utf8_size), &errors); if (errors != 0) { diff --git a/storage/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc index 9add88c0ea5..013a5fb7b37 100644 --- a/storage/xtradb/dict/dict0load.cc +++ b/storage/xtradb/dict/dict0load.cc @@ -1065,7 +1065,8 @@ loop: bool is_temp = false; bool discarded = false; - ib_uint32_t flags2 = mach_read_from_4(field); + ib_uint32_t flags2 = static_cast<ib_uint32_t>( + mach_read_from_4(field)); /* Check that the tablespace (the .ibd file) really exists; print a warning to the .err log if not. diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc index 68c02a301cd..928bdb3f2ef 100644 --- a/storage/xtradb/dict/dict0stats.cc +++ b/storage/xtradb/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2014, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -46,6 +46,7 @@ Created Jan 06, 2010 Vasil Dimov #include "ut0rnd.h" /* ut_rnd_interval() */ #include "ut0ut.h" /* ut_format_name(), ut_time() */ +#include <map> #include <vector> /* Sampling algorithm description @{ @@ -143,6 +144,17 @@ data: b,b,b,b,b,b,g,g,j,j,j, x, y then we would store 5,7,10,11,12 in the array. */ typedef std::vector<ib_uint64_t> boundaries_t; +/* This is used to arrange the index based on the index name. +@return true if index_name1 is smaller than index_name2. */ +struct index_cmp +{ + bool operator()(const char* index_name1, const char* index_name2) const { + return(strcmp(index_name1, index_name2) < 0); + } +}; + +typedef std::map<const char*, dict_index_t*, index_cmp> index_map_t; + /*********************************************************************//** Checks whether an index should be ignored in stats manipulations: * stats fetch @@ -266,22 +278,24 @@ dict_stats_persistent_storage_check( return(true); } -/*********************************************************************//** -Executes a given SQL statement using the InnoDB internal SQL parser -in its own transaction and commits it. +/** Executes a given SQL statement using the InnoDB internal SQL parser. This function will free the pinfo object. +@param[in,out] pinfo pinfo to pass to que_eval_sql() must already +have any literals bound to it +@param[in] sql SQL string to execute +@param[in,out] trx in case of NULL the function will allocate and +free the trx object. If it is not NULL then it will be rolled back +only in the case of error, but not freed. @return DB_SUCCESS or error code */ static dberr_t dict_stats_exec_sql( -/*================*/ - pars_info_t* pinfo, /*!< in/out: pinfo to pass to que_eval_sql() - must already have any literals bound to it */ - const char* sql) /*!< in: SQL string to execute */ + pars_info_t* pinfo, + const char* sql, + trx_t* trx) { - trx_t* trx; dberr_t err; - + bool trx_started = false; #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ @@ -292,11 +306,24 @@ dict_stats_exec_sql( return(DB_STATS_DO_NOT_EXIST); } - trx = trx_allocate_for_background(); - trx_start_if_not_started(trx); + if (trx == NULL) { + trx = trx_allocate_for_background(); + trx_start_if_not_started(trx); + trx_started = true; + } err = que_eval_sql(pinfo, sql, FALSE, trx); /* pinfo is freed here */ + DBUG_EXECUTE_IF("stats_index_error", + if (!trx_started) { + err = DB_STATS_DO_NOT_EXIST; + trx->error_state = DB_STATS_DO_NOT_EXIST; + }); + + if (!trx_started && err == DB_SUCCESS) { + return(DB_SUCCESS); + } + if (err == DB_SUCCESS) { trx_commit_for_mysql(trx); } else { @@ -308,7 +335,9 @@ dict_stats_exec_sql( ut_a(trx->error_state == DB_SUCCESS); } - trx_free_for_background(trx); + if (trx_started) { + trx_free_for_background(trx); + } return(err); } @@ -1588,7 +1617,8 @@ dict_stats_analyze_index_for_n_prefix( == !(REC_INFO_MIN_REC_FLAG & rec_get_info_bits( btr_pcur_get_rec(&pcur), page_is_comp(page)))); - last_idx_on_level = boundaries->at(n_diff_for_this_prefix - 1); + last_idx_on_level = boundaries->at( + static_cast<unsigned int>(n_diff_for_this_prefix - 1)); rec_idx = 0; @@ -1600,7 +1630,7 @@ dict_stats_analyze_index_for_n_prefix( for (i = 0; i < n_recs_to_dive_below; i++) { ib_uint64_t left; ib_uint64_t right; - ulint rnd; + ib_uint64_t rnd; ib_uint64_t dive_below_idx; /* there are n_diff_for_this_prefix elements @@ -1641,9 +1671,11 @@ dict_stats_analyze_index_for_n_prefix( /* we do not pass (left, right) because we do not want to ask ut_rnd_interval() to work with too big numbers since ib_uint64_t could be bigger than ulint */ - rnd = ut_rnd_interval(0, (ulint) (right - left)); + rnd = static_cast<ib_uint64_t>( + ut_rnd_interval(0, static_cast<ulint>(right - left))); - dive_below_idx = boundaries->at(left + rnd); + dive_below_idx = boundaries->at( + static_cast<unsigned int>(left + rnd)); #if 0 DEBUG_PRINTF(" %s(): dive below record with index=" @@ -2084,20 +2116,28 @@ dict_stats_update_persistent( } #include "mysql_com.h" -/*********************************************************************//** -Save an individual index's statistic into the persistent statistics +/** Save an individual index's statistic into the persistent statistics storage. +@param[in] index index to be updated +@param[in] last_update timestamp of the stat +@param[in] stat_name name of the stat +@param[in] stat_value value of the stat +@param[in] sample_size n pages sampled or NULL +@param[in] stat_description description of the stat +@param[in,out] trx in case of NULL the function will +allocate and free the trx object. If it is not NULL then it will be +rolled back only in the case of error, but not freed. @return DB_SUCCESS or error code */ static dberr_t dict_stats_save_index_stat( -/*=======================*/ - dict_index_t* index, /*!< in: index */ - lint last_update, /*!< in: timestamp of the stat */ - const char* stat_name, /*!< in: name of the stat */ - ib_uint64_t stat_value, /*!< in: value of the stat */ - ib_uint64_t* sample_size, /*!< in: n pages sampled or NULL */ - const char* stat_description)/*!< in: description of the stat */ + dict_index_t* index, + lint last_update, + const char* stat_name, + ib_uint64_t stat_value, + ib_uint64_t* sample_size, + const char* stat_description, + trx_t* trx) { pars_info_t* pinfo; dberr_t ret; @@ -2158,7 +2198,7 @@ dict_stats_save_index_stat( ":sample_size,\n" ":stat_description\n" ");\n" - "END;"); + "END;", trx); if (ret != DB_SUCCESS) { char buf_table[MAX_FULL_NAME_LEN]; @@ -2241,7 +2281,7 @@ dict_stats_save( ":clustered_index_size,\n" ":sum_of_other_index_sizes\n" ");\n" - "END;"); + "END;", NULL); if (ret != DB_SUCCESS) { char buf[MAX_FULL_NAME_LEN]; @@ -2251,15 +2291,46 @@ dict_stats_save( "%s: %s\n", ut_format_name(table->name, TRUE, buf, sizeof(buf)), ut_strerr(ret)); - goto end; + + mutex_exit(&dict_sys->mutex); + rw_lock_x_unlock(&dict_operation_lock); + + dict_stats_snapshot_free(table); + + return(ret); } + trx_t* trx = trx_allocate_for_background(); + trx_start_if_not_started(trx); + dict_index_t* index; + index_map_t indexes; + + /* Below we do all the modifications in innodb_index_stats in a single + transaction for performance reasons. Modifying more than one row in a + single transaction may deadlock with other transactions if they + lock the rows in different order. Other transaction could be for + example when we DROP a table and do + DELETE FROM innodb_index_stats WHERE database_name = '...' + AND table_name = '...'; which will affect more than one row. To + prevent deadlocks we always lock the rows in the same order - the + order of the PK, which is (database_name, table_name, index_name, + stat_name). This is why below we sort the indexes by name and then + for each index, do the mods ordered by stat_name. */ for (index = dict_table_get_first_index(table); index != NULL; index = dict_table_get_next_index(index)) { + indexes[index->name] = index; + } + + index_map_t::const_iterator it; + + for (it = indexes.begin(); it != indexes.end(); ++it) { + + index = it->second; + if (only_for_index != NULL && index->id != *only_for_index) { continue; } @@ -2270,24 +2341,6 @@ dict_stats_save( ut_ad(!dict_index_is_univ(index)); - ret = dict_stats_save_index_stat(index, now, "size", - index->stat_index_size, - NULL, - "Number of pages " - "in the index"); - if (ret != DB_SUCCESS) { - goto end; - } - - ret = dict_stats_save_index_stat(index, now, "n_leaf_pages", - index->stat_n_leaf_pages, - NULL, - "Number of leaf pages " - "in the index"); - if (ret != DB_SUCCESS) { - goto end; - } - for (ulint i = 0; i < index->n_uniq; i++) { char stat_name[16]; @@ -2315,15 +2368,37 @@ dict_stats_save( index, now, stat_name, index->stat_n_diff_key_vals[i], &index->stat_n_sample_sizes[i], - stat_description); + stat_description, trx); if (ret != DB_SUCCESS) { goto end; } } + + ret = dict_stats_save_index_stat(index, now, "n_leaf_pages", + index->stat_n_leaf_pages, + NULL, + "Number of leaf pages " + "in the index", trx); + if (ret != DB_SUCCESS) { + goto end; + } + + ret = dict_stats_save_index_stat(index, now, "size", + index->stat_index_size, + NULL, + "Number of pages " + "in the index", trx); + if (ret != DB_SUCCESS) { + goto end; + } } + trx_commit_for_mysql(trx); + end: + trx_free_for_background(trx); + mutex_exit(&dict_sys->mutex); rw_lock_x_unlock(&dict_operation_lock); @@ -3138,7 +3213,7 @@ dict_stats_drop_index( "database_name = :database_name AND\n" "table_name = :table_name AND\n" "index_name = :index_name;\n" - "END;\n"); + "END;\n", NULL); mutex_exit(&dict_sys->mutex); rw_lock_x_unlock(&dict_operation_lock); @@ -3206,7 +3281,7 @@ dict_stats_delete_from_table_stats( "DELETE FROM \"" TABLE_STATS_NAME "\" WHERE\n" "database_name = :database_name AND\n" "table_name = :table_name;\n" - "END;\n"); + "END;\n", NULL); return(ret); } @@ -3244,7 +3319,7 @@ dict_stats_delete_from_index_stats( "DELETE FROM \"" INDEX_STATS_NAME "\" WHERE\n" "database_name = :database_name AND\n" "table_name = :table_name;\n" - "END;\n"); + "END;\n", NULL); return(ret); } @@ -3367,7 +3442,7 @@ dict_stats_rename_in_table_stats( "WHERE\n" "database_name = :old_dbname_utf8 AND\n" "table_name = :old_tablename_utf8;\n" - "END;\n"); + "END;\n", NULL); return(ret); } @@ -3413,7 +3488,7 @@ dict_stats_rename_in_index_stats( "WHERE\n" "database_name = :old_dbname_utf8 AND\n" "table_name = :old_tablename_utf8;\n" - "END;\n"); + "END;\n", NULL); return(ret); } |