diff options
Diffstat (limited to 'storage/innobase/row/row0undo.cc')
-rw-r--r-- | storage/innobase/row/row0undo.cc | 116 |
1 files changed, 63 insertions, 53 deletions
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 149dc671930..cfd4f8e1b51 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -23,6 +23,8 @@ Row undo Created 1/8/1997 Heikki Tuuri *******************************************************/ +#include "ha_prototypes.h" + #include "row0undo.h" #ifdef UNIV_NONINL @@ -122,18 +124,19 @@ or if the roll ptr is NULL, i.e., it was a fresh insert. */ /********************************************************************//** Creates a row undo node to a query graph. -@return own: undo node */ -UNIV_INTERN +@return own: undo node */ undo_node_t* row_undo_node_create( /*=================*/ - trx_t* trx, /*!< in: transaction */ + trx_t* trx, /*!< in/out: transaction */ que_thr_t* parent, /*!< in: parent node, i.e., a thr node */ mem_heap_t* heap) /*!< in: memory heap where created */ { undo_node_t* undo; - ut_ad(trx && parent && heap); + ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) + || trx_state_eq(trx, TRX_STATE_PREPARED)); + ut_ad(parent); undo = static_cast<undo_node_t*>( mem_heap_alloc(heap, sizeof(undo_node_t))); @@ -156,50 +159,46 @@ Looks for the clustered index record when node has the row reference. The pcur in node is used in the search. If found, stores the row to node, and stores the position of pcur, and detaches it. The pcur must be closed by the caller in any case. -@return TRUE if found; NOTE the node->pcur must be closed by the +@return true if found; NOTE the node->pcur must be closed by the caller, regardless of the return value */ -UNIV_INTERN -ibool +bool row_undo_search_clust_to_pcur( /*==========================*/ - undo_node_t* node) /*!< in: row undo node */ + undo_node_t* node) /*!< in/out: row undo node */ { dict_index_t* clust_index; - ibool found; + bool found; mtr_t mtr; - ibool ret; - rec_t* rec; + row_ext_t** ext; + const rec_t* rec; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; rec_offs_init(offsets_); mtr_start(&mtr); + dict_disable_redo_if_temporary(node->table, &mtr); clust_index = dict_table_get_first_index(node->table); - found = row_search_on_row_ref(&(node->pcur), BTR_MODIFY_LEAF, + found = row_search_on_row_ref(&node->pcur, BTR_MODIFY_LEAF, node->table, node->ref, &mtr); - rec = btr_pcur_get_rec(&(node->pcur)); + if (!found) { + goto func_exit; + } + + rec = btr_pcur_get_rec(&node->pcur); offsets = rec_get_offsets(rec, clust_index, offsets, ULINT_UNDEFINED, &heap); - if (!found || node->roll_ptr - != row_get_rec_roll_ptr(rec, clust_index, offsets)) { + found = row_get_rec_roll_ptr(rec, clust_index, offsets) + == node->roll_ptr; - /* We must remove the reservation on the undo log record - BEFORE releasing the latch on the clustered index page: this - is to make sure that some thread will eventually undo the - modification corresponding to node->roll_ptr. */ - - /* fputs("--------------------undoing a previous version\n", - stderr); */ - - ret = FALSE; - } else { - row_ext_t** ext; + if (found) { + ut_ad(row_get_rec_trx_id(rec, clust_index, offsets) + == node->trx->id); if (dict_table_get_format(node->table) >= UNIV_FORMAT_B) { /* In DYNAMIC or COMPRESSED format, there is @@ -218,6 +217,20 @@ row_undo_search_clust_to_pcur( node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets, NULL, NULL, NULL, ext, node->heap); + + /* We will need to parse out virtual column info from undo + log, first mark them DATA_MISSING. So we will know if the + value gets updated */ + if (node->table->n_v_cols + && node->state != UNDO_NODE_INSERT + && !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { + for (ulint i = 0; + i < dict_table_get_n_v_cols(node->table); i++) { + dfield_get_type(dtuple_get_nth_v_field( + node->row, i))->mtype = DATA_MISSING; + } + } + if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { node->undo_row = dtuple_copy(node->row, node->heap); row_upd_replace(node->undo_row, &node->undo_ext, @@ -227,24 +240,23 @@ row_undo_search_clust_to_pcur( node->undo_ext = NULL; } - btr_pcur_store_position(&(node->pcur), &mtr); - - ret = TRUE; + btr_pcur_store_position(&node->pcur, &mtr); } - btr_pcur_commit_specify_mtr(&(node->pcur), &mtr); - - if (UNIV_LIKELY_NULL(heap)) { + if (heap) { mem_heap_free(heap); } - return(ret); + +func_exit: + btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + return(found); } /***********************************************************//** Fetches an undo log record and does the undo for the recorded operation. If none left, or a partial rollback completed, returns control to the parent node, which is always a query thread node. -@return DB_SUCCESS if operation successfully completed, else error code */ +@return DB_SUCCESS if operation successfully completed, else error code */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t row_undo( @@ -261,18 +273,26 @@ row_undo( ut_ad(thr != NULL); trx = node->trx; + ut_ad(trx->in_rollback); if (node->state == UNDO_NODE_FETCH_NEXT) { - node->undo_rec = trx_roll_pop_top_rec_of_trx(trx, - trx->roll_limit, - &roll_ptr, - node->heap); + node->undo_rec = trx_roll_pop_top_rec_of_trx( + trx, trx->roll_limit, &roll_ptr, node->heap); + if (!node->undo_rec) { /* Rollback completed for this query thread */ thr->run_node = que_node_get_parent(node); + /* Mark any partial rollback completed, so + that if the transaction object is committed + and reused later, the roll_limit will remain + at 0. trx->roll_limit will be nonzero during a + partial rollback only. */ + trx->roll_limit = 0; + ut_d(trx->in_rollback = false); + return(DB_SUCCESS); } @@ -301,7 +321,7 @@ row_undo( if (node->state == UNDO_NODE_INSERT) { - err = row_undo_ins(node); + err = row_undo_ins(node, thr); node->state = UNDO_NODE_FETCH_NEXT; } else { @@ -327,8 +347,7 @@ row_undo( /***********************************************************//** Undoes a row operation in a table. This is a high-level function used in SQL execution graphs. -@return query thread to run next or NULL */ -UNIV_INTERN +@return query thread to run next or NULL */ que_thr_t* row_undo_step( /*==========*/ @@ -355,21 +374,12 @@ row_undo_step( if (err != DB_SUCCESS) { /* SQL error detected */ - fprintf(stderr, "InnoDB: Fatal error (%s) in rollback.\n", - ut_strerr(err)); - if (err == DB_OUT_OF_FILE_SPACE) { - fprintf(stderr, - "InnoDB: Out of tablespace.\n" - "InnoDB: Consider increasing" - " your tablespace.\n"); - - exit(1); + ib::fatal() << "Out of tablespace during rollback." + " Consider increasing your tablespace."; } - ut_error; - - return(NULL); + ib::fatal() << "Error (" << ut_strerr(err) << ") in rollback."; } return(thr); |