summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0mysql.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row/row0mysql.cc')
-rw-r--r--storage/innobase/row/row0mysql.cc104
1 files changed, 32 insertions, 72 deletions
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 57ba35a57f6..2a4be043984 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1197,58 +1197,6 @@ row_get_prebuilt_insert_row(
}
/*********************************************************************//**
-Updates the table modification counter and calculates new estimates
-for table and index statistics if necessary. */
-UNIV_INLINE
-void
-row_update_statistics_if_needed(
-/*============================*/
- dict_table_t* table) /*!< in: table */
-{
- ib_uint64_t counter;
- ib_uint64_t n_rows;
-
- if (!table->stat_initialized) {
- DBUG_EXECUTE_IF(
- "test_upd_stats_if_needed_not_inited",
- fprintf(stderr, "test_upd_stats_if_needed_not_inited"
- " was executed\n");
- );
- return;
- }
-
- counter = table->stat_modified_counter++;
- n_rows = dict_table_get_n_rows(table);
-
- if (dict_stats_is_persistent_enabled(table)) {
- if (counter > n_rows / 10 /* 10% */
- && dict_stats_auto_recalc_is_enabled(table)) {
-
- dict_stats_recalc_pool_add(table);
- table->stat_modified_counter = 0;
- }
- return;
- }
-
- /* Calculate new statistics if 1 / 16 of table has been modified
- since the last time a statistics batch was run.
- We calculate statistics at most every 16th round, since we may have
- a counter table which is very small and updated very often. */
- ib_uint64_t threshold= 16 + n_rows / 16; /* 6.25% */
-
- if (srv_stats_modified_counter) {
- threshold= ut_min((ib_uint64_t)srv_stats_modified_counter, threshold);
- }
-
- if (counter > threshold) {
-
- ut_ad(!mutex_own(&dict_sys->mutex));
- /* this will reset table->stat_modified_counter to 0 */
- dict_stats_update(table, DICT_STATS_RECALC_TRANSIENT);
- }
-}
-
-/*********************************************************************//**
Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
AUTO_INC lock gives exclusive access to the auto-inc counter of the
table. The lock is reserved only for the duration of an SQL statement.
@@ -1649,7 +1597,7 @@ error_exit:
ut_memcpy(prebuilt->row_id, node->row_id_buf, DATA_ROW_ID_LEN);
}
- row_update_statistics_if_needed(table);
+ dict_stats_update_if_needed(table);
trx->op_info = "";
if (blob_heap != NULL) {
@@ -1895,6 +1843,7 @@ row_update_for_mysql_using_upd_graph(
ut_ad(trx);
ut_a(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
ut_a(prebuilt->magic_n2 == ROW_PREBUILT_ALLOCATED);
+ ut_ad(table->stat_initialized);
UT_NOT_USED(mysql_rec);
if (!table->is_readable()) {
@@ -1931,6 +1880,8 @@ row_update_for_mysql_using_upd_graph(
}
node = prebuilt->upd_node;
+ const bool is_delete = node->is_delete;
+ ut_ad(node->table == table);
if (node->cascade_heap) {
mem_heap_empty(node->cascade_heap);
@@ -2101,8 +2052,11 @@ run_again:
thr->fk_cascade_depth = 0;
- /* Update the statistics only after completing all cascaded
- operations */
+ /* Update the statistics of each involved table
+ only after completing all operations, including
+ FOREIGN KEY...ON...CASCADE|SET NULL. */
+ bool update_statistics;
+
for (upd_cascade_t::iterator i = processed_cascades->begin();
i != processed_cascades->end();
++i) {
@@ -2116,16 +2070,25 @@ run_again:
than protecting the following code with a latch. */
dict_table_n_rows_dec(node->table);
+ update_statistics = !srv_stats_include_delete_marked;
srv_stats.n_rows_deleted.inc(size_t(trx->id));
} else {
+ update_statistics
+ = !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
srv_stats.n_rows_updated.inc(size_t(trx->id));
}
- row_update_statistics_if_needed(node->table);
+ if (update_statistics) {
+ dict_stats_update_if_needed(node->table);
+ } else {
+ /* Always update the table modification counter. */
+ node->table->stat_modified_counter++;
+ }
+
que_graph_free_recursive(node);
}
- if (node->is_delete) {
+ if (is_delete) {
/* Not protected by dict_table_stats_lock() for performance
reasons, we would rather get garbage in stat_n_rows (which is
just an estimate anyway) than protecting the following code
@@ -2137,25 +2100,24 @@ run_again:
} else {
srv_stats.n_rows_deleted.inc(size_t(trx->id));
}
+
+ update_statistics = !srv_stats_include_delete_marked;
} else {
if (table->is_system_db) {
srv_stats.n_system_rows_updated.inc(size_t(trx->id));
} else {
srv_stats.n_rows_updated.inc(size_t(trx->id));
}
+
+ update_statistics
+ = !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
}
- /* We update table statistics only if it is a DELETE or UPDATE
- that changes indexed columns, UPDATEs that change only non-indexed
- columns would not affect statistics. */
- if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
- row_update_statistics_if_needed(prebuilt->table);
+ if (update_statistics) {
+ dict_stats_update_if_needed(prebuilt->table);
} else {
- /* Update the table modification counter even when
- non-indexed columns change if statistics is initialized. */
- if (prebuilt->table->stat_initialized) {
- prebuilt->table->stat_modified_counter++;
- }
+ /* Always update the table modification counter. */
+ prebuilt->table->stat_modified_counter++;
}
trx->op_info = "";
@@ -5122,12 +5084,10 @@ loop:
case DB_INTERRUPTED:
goto func_exit;
default:
- {
- const char* doing = "CHECK TABLE";
- ib::warn() << doing << " on index " << index->name << " of"
+ ib::warn() << "CHECK TABLE on index " << index->name << " of"
" table " << index->table->name << " returned " << ret;
- /* fall through (this error is ignored by CHECK TABLE) */
- }
+ /* (this error is ignored by CHECK TABLE) */
+ /* fall through */
case DB_END_OF_INDEX:
ret = DB_SUCCESS;
func_exit: