diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-03-11 17:49:36 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-03-11 17:49:36 +0200 |
commit | 814205f306cad8a4b3e55785616ea69a027fef9d (patch) | |
tree | f70402682975e8c6a99ea34a7b1ff3dd9ba73b32 /storage/innobase | |
parent | 89b463ee99c22e69fe4adf686e0d61cd20973c49 (diff) | |
parent | 28e713dc12881e7f50207d0c642523ca3e630114 (diff) | |
download | mariadb-git-814205f306cad8a4b3e55785616ea69a027fef9d.tar.gz |
Merge 10.2 into 10.3
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/include/que0que.h | 35 | ||||
-rw-r--r-- | storage/innobase/include/que0types.h | 39 | ||||
-rw-r--r-- | storage/innobase/include/row0import.h | 21 | ||||
-rw-r--r-- | storage/innobase/include/row0purge.h | 77 | ||||
-rw-r--r-- | storage/innobase/row/row0import.cc | 30 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.cc | 76 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.cc | 21 |
8 files changed, 151 insertions, 150 deletions
diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h index ffca9034b38..9912960e3b4 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. 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 @@ -442,39 +442,6 @@ struct que_fork_t{ /* Flag which is ORed to control structure statement node types */ #define QUE_NODE_CONTROL_STAT 1024 -/* Query graph node types */ -#define QUE_NODE_LOCK 1 -#define QUE_NODE_INSERT 2 -#define QUE_NODE_UPDATE 4 -#define QUE_NODE_CURSOR 5 -#define QUE_NODE_SELECT 6 -#define QUE_NODE_AGGREGATE 7 -#define QUE_NODE_FORK 8 -#define QUE_NODE_THR 9 -#define QUE_NODE_UNDO 10 -#define QUE_NODE_COMMIT 11 -#define QUE_NODE_ROLLBACK 12 -#define QUE_NODE_PURGE 13 -#define QUE_NODE_CREATE_TABLE 14 -#define QUE_NODE_CREATE_INDEX 15 -#define QUE_NODE_SYMBOL 16 -#define QUE_NODE_RES_WORD 17 -#define QUE_NODE_FUNC 18 -#define QUE_NODE_ORDER 19 -#define QUE_NODE_PROC (20 + QUE_NODE_CONTROL_STAT) -#define QUE_NODE_IF (21 + QUE_NODE_CONTROL_STAT) -#define QUE_NODE_WHILE (22 + QUE_NODE_CONTROL_STAT) -#define QUE_NODE_ASSIGNMENT 23 -#define QUE_NODE_FETCH 24 -#define QUE_NODE_OPEN 25 -#define QUE_NODE_COL_ASSIGNMENT 26 -#define QUE_NODE_FOR (27 + QUE_NODE_CONTROL_STAT) -#define QUE_NODE_RETURN 28 -#define QUE_NODE_ROW_PRINTF 29 -#define QUE_NODE_ELSIF 30 -#define QUE_NODE_CALL 31 -#define QUE_NODE_EXIT 32 - #include "que0que.ic" #endif diff --git a/storage/innobase/include/que0types.h b/storage/innobase/include/que0types.h index 017e5df9a6f..2b5a04811b3 100644 --- a/storage/innobase/include/que0types.h +++ b/storage/innobase/include/que0types.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. 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 @@ -36,6 +37,39 @@ typedef struct que_fork_t que_t; struct que_thr_t; +/* Query graph node types */ +#define QUE_NODE_LOCK 1 +#define QUE_NODE_INSERT 2 +#define QUE_NODE_UPDATE 4 +#define QUE_NODE_CURSOR 5 +#define QUE_NODE_SELECT 6 +#define QUE_NODE_AGGREGATE 7 +#define QUE_NODE_FORK 8 +#define QUE_NODE_THR 9 +#define QUE_NODE_UNDO 10 +#define QUE_NODE_COMMIT 11 +#define QUE_NODE_ROLLBACK 12 +#define QUE_NODE_PURGE 13 +#define QUE_NODE_CREATE_TABLE 14 +#define QUE_NODE_CREATE_INDEX 15 +#define QUE_NODE_SYMBOL 16 +#define QUE_NODE_RES_WORD 17 +#define QUE_NODE_FUNC 18 +#define QUE_NODE_ORDER 19 +#define QUE_NODE_PROC (20 + QUE_NODE_CONTROL_STAT) +#define QUE_NODE_IF (21 + QUE_NODE_CONTROL_STAT) +#define QUE_NODE_WHILE (22 + QUE_NODE_CONTROL_STAT) +#define QUE_NODE_ASSIGNMENT 23 +#define QUE_NODE_FETCH 24 +#define QUE_NODE_OPEN 25 +#define QUE_NODE_COL_ASSIGNMENT 26 +#define QUE_NODE_FOR (27 + QUE_NODE_CONTROL_STAT) +#define QUE_NODE_RETURN 28 +#define QUE_NODE_ROW_PRINTF 29 +#define QUE_NODE_ELSIF 30 +#define QUE_NODE_CALL 31 +#define QUE_NODE_EXIT 32 + /* Common struct at the beginning of each query graph node; the name of this substruct must be 'common' */ @@ -51,6 +85,11 @@ struct que_common_t{ symbol node or a function node, then we have to free the data field in val explicitly */ + + /** Constructor */ + que_common_t(ulint type, que_node_t* parent) + : type(type), parent(parent), brother(), val(), val_buf_size() + {} }; #endif diff --git a/storage/innobase/include/row0import.h b/storage/innobase/include/row0import.h index 94df1a61341..9c4d3a7f7a5 100644 --- a/storage/innobase/include/row0import.h +++ b/storage/innobase/include/row0import.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. 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 @@ -55,22 +55,13 @@ dberr_t row_import_update_discarded_flag(trx_t* trx, table_id_t table_id, bool discarded) MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*****************************************************************//** -Update the (space, root page) of a table's indexes from the values -in the data dictionary. +/** Update the root page numbers and tablespace ID of a table. +@param[in,out] trx dictionary transaction +@param[in,out] table persistent table +@param[in] reset whether to reset the fields to FIL_NULL @return DB_SUCCESS or error code */ dberr_t -row_import_update_index_root( -/*=========================*/ - trx_t* trx, /*!< in/out: transaction that - covers the update */ - const dict_table_t* table, /*!< in: Table for which we want - to set the root page_no */ - bool reset, /*!< in: if true then set to - FIL_NUL */ - bool dict_locked) /*!< in: Set to true if the - caller already owns the - dict_sys_t:: mutex. */ +row_import_update_index_root(trx_t* trx, dict_table_t* table, bool reset) MY_ATTRIBUTE((nonnull, warn_unused_result)); #endif /* row0import_h */ diff --git a/storage/innobase/include/row0purge.h b/storage/innobase/include/row0purge.h index 25cd43979bf..a1718398a83 100644 --- a/storage/innobase/include/row0purge.h +++ b/storage/innobase/include/row0purge.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. 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 @@ -35,16 +35,6 @@ Created 3/14/1997 Heikki Tuuri #include "ut0vec.h" #include "row0mysql.h" -/** Create a purge node to a query graph. -@param[in] parent parent node, i.e., a thr node -@param[in] heap memory heap where created -@return own: purge node */ -purge_node_t* -row_purge_node_create( - que_thr_t* parent, - mem_heap_t* heap) - MY_ATTRIBUTE((warn_unused_result)); - /** Determines if it is possible to remove a secondary index entry. Removal is possible if the secondary index entry does not refer to any not delete marked version of a clustered index record where DB_TRX_ID @@ -102,6 +92,13 @@ struct purge_node_t{ ulint rec_type;/*!< undo log record type: TRX_UNDO_INSERT_REC, ... */ +private: + /** latest unavailable table ID (do not bother looking up again) */ + table_id_t unavailable_table_id; + /** the latest modification of the table definition identified by + unavailable_table_id, or TRX_ID_MAX */ + trx_id_t def_trx_id; +public: dict_table_t* table; /*!< table where purge is done */ ulint cmpl_info;/* compiler analysis info of an update */ @@ -118,19 +115,27 @@ struct purge_node_t{ mem_heap_t* heap; /*!< memory heap used as auxiliary storage for row; this must be emptied after a successful purge of a row */ - ibool found_clust;/* TRUE if the clustered index record + ibool found_clust;/*!< whether the clustered index record determined by ref was found in the clustered index, and we were able to position pcur on it */ btr_pcur_t pcur; /*!< persistent cursor used in searching the clustered index record */ - ibool done; /* Debug flag */ +#ifdef UNIV_DEBUG + /** whether the operation is in progress */ + bool in_progress; +#endif trx_id_t trx_id; /*!< trx id for this purging record */ /** Virtual column information about opening of MariaDB table. It resets after processing each undo log record. */ purge_vcol_info_t vcol_info; + /** Constructor */ + explicit purge_node_t(que_thr_t* parent) : + common(QUE_NODE_PURGE, parent), heap(mem_heap_create(256)) + {} + #ifdef UNIV_DEBUG /***********************************************************//** Validate the persisent cursor. The purge node has two references @@ -146,6 +151,52 @@ struct purge_node_t{ computation. @return true if the table failed to open. */ bool vcol_op_failed() const { return !vcol_info.validate(); } + + /** Determine if a table should be skipped in purge. + @param[in] table_id table identifier + @return whether to skip the table lookup and processing */ + bool is_skipped(table_id_t id) const + { + return id == unavailable_table_id && trx_id <= def_trx_id; + } + + /** Remember that a table should be skipped in purge. + @param[in] id table identifier + @param[in] limit last transaction for which to skip */ + void skip(table_id_t id, trx_id_t limit) + { + DBUG_ASSERT(limit >= trx_id); + unavailable_table_id = id; + def_trx_id = limit; + } + + /** Start processing an undo log record. */ + void start() + { + ut_ad(in_progress); + DBUG_ASSERT(common.type == QUE_NODE_PURGE); + + table = NULL; + row = NULL; + ref = NULL; + index = NULL; + update = NULL; + found_clust = FALSE; + rec_type = ULINT_UNDEFINED; + cmpl_info = ULINT_UNDEFINED; + } + + /** Reset the state at end + @return the query graph parent */ + que_node_t* end() + { + DBUG_ASSERT(common.type == QUE_NODE_PURGE); + undo_recs = NULL; + ut_d(in_progress = false); + vcol_info.reset(); + mem_heap_empty(heap); + return common.parent; + } }; #endif diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 9cdb4cab764..9174a922cdb 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3066,23 +3066,13 @@ row_import_read_cfg( return(err); } -/*****************************************************************//** -Update the <space, root page> of a table's indexes from the values -in the data dictionary. +/** Update the root page numbers and tablespace ID of a table. +@param[in,out] trx dictionary transaction +@param[in,out] table persistent table +@param[in] reset whether to reset the fields to FIL_NULL @return DB_SUCCESS or error code */ dberr_t -row_import_update_index_root( -/*=========================*/ - trx_t* trx, /*!< in/out: transaction that - covers the update */ - const dict_table_t* table, /*!< in: Table for which we want - to set the root page_no */ - bool reset, /*!< in: if true then set to - FIL_NUL */ - bool dict_locked) /*!< in: Set to true if the - caller already owns the - dict_sys_t:: mutex. */ - +row_import_update_index_root(trx_t* trx, dict_table_t* table, bool reset) { const dict_index_t* index; que_t* graph = 0; @@ -3100,9 +3090,7 @@ row_import_update_index_root( "WHERE TABLE_ID = :table_id AND ID = :index_id;\n" "END;\n"}; - if (!dict_locked) { - mutex_enter(&dict_sys->mutex); - } + table->def_trx_id = trx->id; for (index = dict_table_get_first_index(table); index != 0; @@ -3177,10 +3165,6 @@ row_import_update_index_root( que_graph_free(graph); - if (!dict_locked) { - mutex_exit(&dict_sys->mutex); - } - return(err); } @@ -4115,7 +4099,7 @@ row_import_for_mysql( row_mysql_lock_data_dictionary(trx); /* Update the root pages of the table's indexes. */ - err = row_import_update_index_root(trx, table, false, true); + err = row_import_update_index_root(trx, table, false); if (err != DB_SUCCESS) { return(row_import_error(prebuilt, trx, err)); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index e5bc21c21a7..1d5357f7473 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3028,7 +3028,7 @@ row_discard_tablespace( } /* Update the index root pages in the system tables, on disk */ - err = row_import_update_index_root(trx, table, true, true); + err = row_import_update_index_root(trx, table, true); if (err != DB_SUCCESS) { return(err); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 5699c8b2f56..7854901cfa8 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. 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 @@ -57,31 +57,6 @@ check. If you make a change in this module make sure that no codepath is introduced where a call to log_free_check() is bypassed. */ -/** Create a purge node to a query graph. -@param[in] parent parent node, i.e., a thr node -@param[in] heap memory heap where created -@return own: purge node */ -purge_node_t* -row_purge_node_create( - que_thr_t* parent, - mem_heap_t* heap) -{ - purge_node_t* node; - - ut_ad(parent != NULL); - ut_ad(heap != NULL); - - node = static_cast<purge_node_t*>( - mem_heap_zalloc(heap, sizeof(*node))); - - node->common.type = QUE_NODE_PURGE; - node->common.parent = parent; - node->done = TRUE; - node->heap = mem_heap_create(256); - - return(node); -} - /***********************************************************//** Repositions the pcur in the purge node on the clustered index record, if found. If the record is not found, close pcur. @@ -1066,6 +1041,10 @@ row_purge_parse_undo_rec( break; } + if (node->is_skipped(table_id)) { + return false; + } + /* Prevent DROP TABLE etc. from running when we are doing the purge for this row */ @@ -1075,15 +1054,18 @@ try_again: node->table = dict_table_open_on_id( table_id, FALSE, DICT_TABLE_OP_NORMAL); + trx_id_t trx_id; + if (node->table == NULL) { /* The table has been dropped: no need to do purge */ + trx_id = TRX_ID_MAX; goto err_exit; } ut_ad(!node->table->is_temporary()); if (!fil_table_accessible(node->table)) { - goto close_exit; + goto inaccessible; } switch (type) { @@ -1119,11 +1101,20 @@ try_again: /* The table was corrupt in the data dictionary. dict_set_corrupted() works on an index, and we do not have an index to call it with. */ -close_exit: +inaccessible: + DBUG_ASSERT(table_id == node->table->id); + trx_id = node->table->def_trx_id; + if (!trx_id) { + trx_id = TRX_ID_MAX; + } + dict_table_close(node->table, FALSE, FALSE); node->table = NULL; err_exit: rw_lock_s_unlock(dict_operation_lock); + if (table_id) { + node->skip(table_id, trx_id); + } return(false); } @@ -1283,25 +1274,11 @@ row_purge_end( /*==========*/ que_thr_t* thr) /*!< in: query thread */ { - purge_node_t* node; - ut_ad(thr); - node = static_cast<purge_node_t*>(thr->run_node); - - ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); - - thr->run_node = que_node_get_parent(node); - - node->undo_recs = NULL; - - node->done = TRUE; - - node->vcol_info.reset(); + thr->run_node = static_cast<purge_node_t*>(thr->run_node)->end(); ut_a(thr->run_node != NULL); - - mem_heap_empty(node->heap); } /***********************************************************//** @@ -1319,18 +1296,7 @@ row_purge_step( node = static_cast<purge_node_t*>(thr->run_node); - node->table = NULL; - node->row = NULL; - node->ref = NULL; - node->index = NULL; - node->update = NULL; - node->found_clust = FALSE; - node->rec_type = ULINT_UNDEFINED; - node->cmpl_info = ULINT_UNDEFINED; - - ut_a(!node->done); - - ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); + node->start(); if (!(node->undo_recs == NULL || ib_vector_is_empty(node->undo_recs))) { trx_purge_rec_t*purge_rec; diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index a4fa12708ac..980e518daf6 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. 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 @@ -148,7 +148,8 @@ purge_graph_build() for (ulint i = 0; i < srv_n_purge_threads; ++i) { que_thr_t* thr = que_thr_create(fork, heap, NULL); - thr->child = row_purge_node_create(thr, heap); + thr->child = new(mem_heap_zalloc(heap, sizeof(purge_node_t))) + purge_node_t(thr); } return(fork); @@ -1404,7 +1405,7 @@ ulint trx_purge_attach_undo_recs(ulint n_purge_threads) { que_thr_t* thr; - ulint i = 0; + ulint i; ulint n_pages_handled = 0; ulint n_thrs = UT_LIST_GET_LEN(purge_sys.query->thrs); @@ -1412,6 +1413,8 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) purge_sys.head = purge_sys.tail; +#ifdef UNIV_DEBUG + i = 0; /* Debug code to validate some pre-requisites and reset done flag. */ for (thr = UT_LIST_GET_FIRST(purge_sys.query->thrs); thr != NULL && i < n_purge_threads; @@ -1422,16 +1425,16 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) /* Get the purge node. */ node = (purge_node_t*) thr->child; - ut_a(que_node_get_type(node) == QUE_NODE_PURGE); - ut_a(node->undo_recs == NULL); - ut_a(node->done); - - node->done = FALSE; + ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); + ut_ad(node->undo_recs == NULL); + ut_ad(!node->in_progress); + ut_d(node->in_progress = true); } /* There should never be fewer nodes than threads, the inverse however is allowed because we only use purge threads as needed. */ - ut_a(i == n_purge_threads); + ut_ad(i == n_purge_threads); +#endif /* Fetch and parse the UNDO records. The UNDO records are added to a per purge node vector. */ |