diff options
author | monty@hundin.mysql.fi <> | 2002-04-25 01:16:42 +0300 |
---|---|---|
committer | monty@hundin.mysql.fi <> | 2002-04-25 01:16:42 +0300 |
commit | 727122aadd80f9e1a127bcc1562c8dc95d786e4a (patch) | |
tree | 539e3f41736108728458d901c552313e5f058e8f /innobase/row/row0mysql.c | |
parent | 1f5f3612f30d67029fe9cc2ff5d5e44daa5698f2 (diff) | |
parent | ecf2c4e15a677a9f33ba8e7d6b2eb6a9da6538e4 (diff) | |
download | mariadb-git-727122aadd80f9e1a127bcc1562c8dc95d786e4a.tar.gz |
merge
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r-- | innobase/row/row0mysql.c | 177 |
1 files changed, 136 insertions, 41 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 78b32a5642b..841d03acc48 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -499,29 +499,24 @@ UNIV_INLINE void row_update_statistics_if_needed( /*============================*/ - row_prebuilt_t* prebuilt) /* in: prebuilt struct */ + dict_table_t* table) /* in: table */ { ulint counter; - counter = prebuilt->table->stat_modified_counter; - - /* Since the physical size of an InnoDB row is bigger than the - MySQL row len, we put a safety factor 2 below */ - - counter += 2 * prebuilt->mysql_row_len; + counter = table->stat_modified_counter; - prebuilt->table->stat_modified_counter = counter; + table->stat_modified_counter = counter + 1; /* Calculate new statistics if 1 / 16 of table has been modified since the last time a statistics batch was run, or if - stat_modified_counter > 2 000 000 000 (to avoid wrap-around) */ + stat_modified_counter > 2 000 000 000 (to avoid wrap-around). + We calculate statistics at most every 16th round, since we may have + a counter table which is very small and updated very often. */ if (counter > 2000000000 - || ((ib_longlong)counter > - (UNIV_PAGE_SIZE * prebuilt->table->stat_clustered_index_size) - / 16)) { + || ((ib_longlong)counter > 16 + table->stat_n_rows / 16)) { - dict_update_statistics(prebuilt->table); + dict_update_statistics(table); } } @@ -712,7 +707,7 @@ run_again: prebuilt->table->stat_n_rows--; } - row_update_statistics_if_needed(prebuilt); + row_update_statistics_if_needed(prebuilt->table); trx->op_info = (char *) ""; return((int) err); @@ -746,6 +741,43 @@ row_prebuild_sel_graph( } /************************************************************************* +Creates an query graph node of 'update' type to be used in the MySQL +interface. */ + +upd_node_t* +row_create_update_node_for_mysql( +/*=============================*/ + /* out, own: update node */ + dict_table_t* table, /* in: table to update */ + mem_heap_t* heap) /* in: mem heap from which allocated */ +{ + upd_node_t* node; + + node = upd_node_create(heap); + + node->in_mysql_interface = TRUE; + node->is_delete = FALSE; + node->searched_update = FALSE; + node->select_will_do_update = FALSE; + node->select = NULL; + node->pcur = btr_pcur_create_for_mysql(); + node->table = table; + + node->update = upd_create(dict_table_get_n_cols(table), heap); + + node->update_n_fields = dict_table_get_n_cols(table); + + UT_LIST_INIT(node->columns); + node->has_clust_rec_x_lock = TRUE; + node->cmpl_info = 0; + + node->table_sym = NULL; + node->col_assign_list = NULL; + + return(node); +} + +/************************************************************************* Gets pointer to a prebuilt update vector used in updates. If the update graph has not yet been built in the prebuilt struct, then this function first builds it. */ @@ -767,26 +799,9 @@ row_get_prebuilt_update_vector( /* Not called before for this handle: create an update node and query graph to the prebuilt struct */ - node = upd_node_create(prebuilt->heap); - - prebuilt->upd_node = node; + node = row_create_update_node_for_mysql(table, prebuilt->heap); - node->in_mysql_interface = TRUE; - node->is_delete = FALSE; - node->searched_update = FALSE; - node->select_will_do_update = FALSE; - node->select = NULL; - node->pcur = btr_pcur_create_for_mysql(); - node->table = table; - - node->update = upd_create(dict_table_get_n_cols(table), - prebuilt->heap); - UT_LIST_INIT(node->columns); - node->has_clust_rec_x_lock = TRUE; - node->cmpl_info = 0; - - node->table_sym = NULL; - node->col_assign_list = NULL; + prebuilt->upd_node = node; prebuilt->upd_graph = que_node_get_parent( @@ -914,7 +929,7 @@ run_again: que_thr_stop_for_mysql_no_error(thr, trx); - if (prebuilt->upd_node->is_delete) { + if (node->is_delete) { if (prebuilt->table->stat_n_rows > 0) { prebuilt->table->stat_n_rows--; } @@ -924,13 +939,66 @@ run_again: srv_n_rows_updated++; } - row_update_statistics_if_needed(prebuilt); + row_update_statistics_if_needed(prebuilt->table); trx->op_info = (char *) ""; return((int) err); } +/************************************************************************** +Does a cascaded delete or set null in a foreign key operation. */ + +ulint +row_update_cascade_for_mysql( +/*=========================*/ + /* out: error code or DB_SUCCESS */ + que_thr_t* thr, /* in: query thread */ + upd_node_t* node, /* in: update node used in the cascade + or set null operation */ + dict_table_t* table) /* in: table where we do the operation */ +{ + ulint err; + trx_t* trx; + + trx = thr_get_trx(thr); + +run_again: + thr->run_node = node; + thr->prev_node = node; + + row_upd_step(thr); + + err = trx->error_state; + + if (err == DB_LOCK_WAIT) { + que_thr_stop_for_mysql(thr); + + row_mysql_handle_errors(&err, trx, thr, NULL); + + goto run_again; + } + + if (err != DB_SUCCESS) { + + return(err); + } + + if (node->is_delete) { + if (table->stat_n_rows > 0) { + table->stat_n_rows--; + } + + srv_n_rows_deleted++; + } else { + srv_n_rows_updated++; + } + + row_update_statistics_if_needed(table); + + return(err); +} + /************************************************************************* Checks if a table is such that we automatically created a clustered index on it (on row id). */ @@ -1171,6 +1239,7 @@ row_create_table_for_mysql( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); heap = mem_heap_create(512); @@ -1223,6 +1292,8 @@ row_create_table_for_mysql( } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); + que_graph_free((que_t*) que_node_get_parent(thr)); trx->op_info = (char *) ""; @@ -1270,6 +1341,7 @@ row_create_index_for_mysql( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); heap = mem_heap_create(512); @@ -1300,6 +1372,7 @@ row_create_index_for_mysql( } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); que_graph_free((que_t*) que_node_get_parent(thr)); @@ -1355,6 +1428,7 @@ row_table_add_foreign_constraints( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); trx->dict_operation = TRUE; @@ -1379,6 +1453,7 @@ row_table_add_foreign_constraints( } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); return((int) err); } @@ -1473,7 +1548,8 @@ loop: goto already_dropped; } - if (table->n_mysql_handles_opened > 0) { + if (table->n_mysql_handles_opened > 0 + || table->n_foreign_key_checks_running > 0) { return(n_tables + n_tables_dropped); } @@ -1722,6 +1798,9 @@ row_drop_table_for_mysql( no deadlocks can occur then in these operations */ if (!has_dict_mutex) { + /* Prevent foreign key checks while we are dropping the table */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); + mutex_enter(&(dict_sys->mutex)); } @@ -1734,9 +1813,6 @@ row_drop_table_for_mysql( graph->fork_type = QUE_FORK_MYSQL_INTERFACE; - /* Prevent foreign key checks while we are dropping the table */ - rw_lock_x_lock(&(dict_foreign_key_check_lock)); - /* Prevent purge from running while we are dropping the table */ rw_lock_s_lock(&(purge_sys->purge_is_running)); @@ -1771,6 +1847,22 @@ row_drop_table_for_mysql( goto funct_exit; } + if (table->n_foreign_key_checks_running > 0) { + + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: You are trying to drop table %s\n" + "InnoDB: though there are foreign key check running on it.\n" + "InnoDB: Adding the table to the background drop queue.\n", + table->name); + + row_add_table_to_background_drop_list(table); + + err = DB_SUCCESS; + + goto funct_exit; + } + /* Remove any locks there are on the table or its records */ lock_reset_all_on_table(table); @@ -1798,10 +1890,9 @@ row_drop_table_for_mysql( funct_exit: rw_lock_s_unlock(&(purge_sys->purge_is_running)); - rw_lock_x_unlock(&(dict_foreign_key_check_lock)); - if (!has_dict_mutex) { mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); } que_graph_free(graph); @@ -1837,6 +1928,7 @@ row_drop_database_for_mysql( trx_start_if_not_started(trx); loop: + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); while ((table_name = dict_get_first_table_name_in_db(name))) { @@ -1878,6 +1970,7 @@ loop: } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); trx_commit_for_mysql(trx); @@ -2014,6 +2107,7 @@ row_rename_table_for_mysql( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); table = dict_table_get_low(old_name); @@ -2095,6 +2189,7 @@ row_rename_table_for_mysql( } funct_exit: mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); que_graph_free(graph); |