/*************************************************************** Parses the row reference and other info in a fresh insert undo record. */ static void row_undo_ins_parse_undo_rec( /*========================*/ undo_node_t* node, /* in: row undo node */ que_thr_t* thr) /* in: query thread */ { dict_index_t* clust_index; byte* ptr; dulint undo_no; dulint table_id; ulint type; ulint dummy; ibool dummy_extern; ut_ad(node && thr); ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy, &dummy_extern, &undo_no, &table_id); ut_ad(type == TRX_UNDO_INSERT_REC); node->rec_type = type; node->table = dict_table_get_on_id(table_id, node->trx); if (node->table == NULL) { return; } clust_index = dict_table_get_first_index(node->table); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); }
/***********************************************************//** Parses the row reference and other info in a modify undo log record. */ static void row_undo_mod_parse_undo_rec( /*========================*/ undo_node_t* node, /*!< in: row undo node */ que_thr_t* thr) /*!< in: query thread */ { dict_index_t* clust_index; byte* ptr; undo_no_t undo_no; table_id_t table_id; trx_id_t trx_id; roll_ptr_t roll_ptr; ulint info_bits; ulint type; ulint cmpl_info; ibool dummy_extern; trx_t* trx; ut_ad(node && thr); trx = thr_get_trx(thr); ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, &dummy_extern, &undo_no, &table_id); node->rec_type = type; node->table = dict_table_get_on_id(table_id, trx); /* TODO: other fixes associated with DROP TABLE + rollback in the same table by another user */ if (node->table == NULL) { /* Table was dropped */ return; } if (node->table->ibd_file_missing) { /* We skip undo operations to missing .ibd files */ node->table = NULL; return; } clust_index = dict_table_get_first_index(node->table); ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); trx_undo_update_rec_get_update(ptr, clust_index, type, trx_id, roll_ptr, info_bits, trx, node->heap, &(node->update)); node->new_roll_ptr = roll_ptr; node->new_trx_id = trx_id; node->cmpl_info = cmpl_info; }
/***********************************************************//** Parses the row reference and other info in a fresh insert undo record. */ static void row_undo_ins_parse_undo_rec( /*========================*/ ib_recovery_t recovery, /*!< in: recovery flag */ undo_node_t* node) /*!< in/out: row undo node */ { dict_index_t* clust_index; byte* ptr; undo_no_t undo_no; dulint table_id; ulint type; ulint dummy; ibool dummy_extern; ut_ad(node); ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy, &dummy_extern, &undo_no, &table_id); ut_ad(type == TRX_UNDO_INSERT_REC); node->rec_type = type; node->update = NULL; node->table = dict_table_get_on_id( srv_force_recovery, table_id, node->trx); /* Skip the UNDO if we can't find the table or the .ibd file. */ if (UNIV_UNLIKELY(node->table == NULL)) { } else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) { node->table = NULL; } else { clust_index = dict_table_get_first_index(node->table); if (clust_index != NULL) { ptr = trx_undo_rec_get_row_ref( ptr, clust_index, &node->ref, node->heap); } else { ut_print_timestamp(ib_stream); ib_logger(ib_stream, " InnoDB: table "); ut_print_name(ib_stream, node->trx, TRUE, node->table->name); ib_logger(ib_stream, " has no indexes, " "ignoring the table\n"); node->table = NULL; } } }
/*************************************************************** Parses the row reference and other info in a fresh insert undo record. */ static void row_undo_ins_parse_undo_rec( /*========================*/ undo_node_t* node) /* in: row undo node */ { dict_index_t* clust_index; byte* ptr; dulint undo_no; dulint table_id; ulint type; ulint dummy; ibool dummy_extern; ut_ad(node); ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy, &dummy_extern, &undo_no, &table_id); ut_ad(type == TRX_UNDO_INSERT_REC); node->rec_type = type; node->table = dict_table_get_on_id(table_id, node->trx); if (node->table == NULL) { return; } if (node->table->ibd_file_missing) { /* We skip undo operations to missing .ibd files */ node->table = NULL; return; } clust_index = dict_table_get_first_index(node->table); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); }
/***********************************************************//** Parses the row reference and other info in a modify undo log record. @return TRUE if purge operation required: NOTE that then the CALLER must unfreeze data dictionary! */ static ibool row_purge_parse_undo_rec( /*=====================*/ purge_node_t* node, /*!< in: row undo node */ ibool* updated_extern, /*!< out: TRUE if an externally stored field was updated */ que_thr_t* thr) /*!< in: query thread */ { dict_index_t* clust_index; byte* ptr; trx_t* trx; undo_no_t undo_no; table_id_t table_id; trx_id_t trx_id; roll_ptr_t roll_ptr; ulint info_bits; ulint type; ut_ad(node && thr); trx = thr_get_trx(thr); ptr = trx_undo_rec_get_pars( node->undo_rec, &type, &node->cmpl_info, updated_extern, &undo_no, &table_id); node->rec_type = type; if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) { return(FALSE); } ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); node->table = NULL; if (type == TRX_UNDO_UPD_EXIST_REC && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) { /* Purge requires no changes to indexes: we may return */ return(FALSE); } /* Prevent DROP TABLE etc. from running when we are doing the purge for this row */ row_mysql_freeze_data_dictionary(trx); mutex_enter(&(dict_sys->mutex)); node->table = dict_table_get_on_id_low(table_id); mutex_exit(&(dict_sys->mutex)); if (node->table == NULL) { /* The table has been dropped: no need to do purge */ err_exit: row_mysql_unfreeze_data_dictionary(trx); return(FALSE); } if (node->table->ibd_file_missing) { /* We skip purge of missing .ibd files */ node->table = NULL; goto err_exit; } clust_index = dict_table_get_first_index(node->table); if (clust_index == NULL) { /* The table was corrupt in the data dictionary */ goto err_exit; } ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); ptr = trx_undo_update_rec_get_update(ptr, clust_index, type, trx_id, roll_ptr, info_bits, trx, node->heap, &(node->update)); /* Read to the partial row the fields that occur in indexes */ if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { ptr = trx_undo_rec_get_partial_row( ptr, clust_index, &node->row, type == TRX_UNDO_UPD_DEL_REC, node->heap); } return(TRUE); }
/*************************************************************** Parses the row reference and other info in a modify undo log record. */ static ibool row_purge_parse_undo_rec( /*=====================*/ /* out: TRUE if purge operation required */ purge_node_t* node, /* in: row undo node */ ibool* updated_extern, /* out: TRUE if an externally stored field was updated */ que_thr_t* thr) /* in: query thread */ { dict_index_t* clust_index; byte* ptr; dulint undo_no; dulint table_id; dulint trx_id; dulint roll_ptr; ulint info_bits; ulint type; ulint cmpl_info; ut_ad(node && thr); ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, updated_extern, &undo_no, &table_id); node->rec_type = type; if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) { return(FALSE); } ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); node->table = NULL; if (type == TRX_UNDO_UPD_EXIST_REC && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) { /* Purge requires no changes to indexes: we may return */ return(FALSE); } mutex_enter(&(dict_sys->mutex)); node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr)); rw_lock_x_lock(&(purge_sys->purge_is_running)); mutex_exit(&(dict_sys->mutex)); if (node->table == NULL) { /* The table has been dropped: no need to do purge */ rw_lock_x_unlock(&(purge_sys->purge_is_running)); return(FALSE); } clust_index = dict_table_get_first_index(node->table); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); ptr = trx_undo_update_rec_get_update(ptr, clust_index, type, trx_id, roll_ptr, info_bits, node->heap, &(node->update)); /* Read to the partial row the fields that occur in indexes */ if (!cmpl_info & UPD_NODE_NO_ORD_CHANGE) { ptr = trx_undo_rec_get_partial_row(ptr, clust_index, &(node->row), node->heap); } return(TRUE); }