diff options
Diffstat (limited to 'storage/innobase/row/row0umod.c')
-rw-r--r-- | storage/innobase/row/row0umod.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index fae67c95c43..69831fee8ac 100644 --- a/storage/innobase/row/row0umod.c +++ b/storage/innobase/row/row0umod.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. 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 @@ -128,11 +128,10 @@ row_undo_mod_clust_low( } /***********************************************************//** -Removes a clustered index record after undo if possible. +Purges a clustered index record after undo if possible. This is attempted when the record was inserted by updating a delete-marked record and there no longer exist transactions -that would see the delete-marked record. In other words, we -roll back the insert by purging the record. +that would see the delete-marked record. @return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */ static ulint @@ -140,11 +139,12 @@ row_undo_mod_remove_clust_low( /*==========================*/ undo_node_t* node, /*!< in: row undo node */ que_thr_t* thr, /*!< in: query thread */ - mtr_t* mtr, /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction */ ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { btr_cur_t* btr_cur; ulint err; + ulint trx_id_offset; ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); @@ -159,6 +159,42 @@ row_undo_mod_remove_clust_low( btr_cur = btr_pcur_get_btr_cur(&node->pcur); + trx_id_offset = btr_cur_get_index(btr_cur)->trx_id_offset; + + if (!trx_id_offset) { + mem_heap_t* heap = NULL; + ulint trx_id_col; + ulint* offsets; + ulint len; + + trx_id_col = dict_index_get_sys_col_pos( + btr_cur_get_index(btr_cur), DATA_TRX_ID); + ut_ad(trx_id_col > 0); + ut_ad(trx_id_col != ULINT_UNDEFINED); + + offsets = rec_get_offsets( + btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur), + NULL, trx_id_col + 1, &heap); + + trx_id_offset = rec_get_nth_field_offs( + offsets, trx_id_col, &len); + ut_ad(len == DATA_TRX_ID_LEN); + mem_heap_free(heap); + } + + if (trx_read_trx_id(btr_cur_get_rec(btr_cur) + trx_id_offset) + != node->new_trx_id) { + /* The record must have been purged and then replaced + with a different one. */ + return(DB_SUCCESS); + } + + /* We are about to remove an old, delete-marked version of the + record that may have been delete-marked by a different transaction + than the rolling-back one. */ + ut_ad(rec_get_deleted_flag(btr_cur_get_rec(btr_cur), + dict_table_is_comp(node->table))); + if (mode == BTR_MODIFY_LEAF) { err = btr_cur_optimistic_delete(btr_cur, mtr) ? DB_SUCCESS |