Commit c436338d authored by Marko Mäkelä's avatar Marko Mäkelä

Assert that DB_TRX_ID must be set on delete-marked records

This is preparation for MDEV-12288, which would set DB_TRX_ID=0
when purging history. Also with that change in place, delete-marked
records must always refer to an undo log record via a nonzero
DB_TRX_ID column. (The DB_TRX_ID is only present in clustered index
leaf page records.)

btr_cur_parse_del_mark_set_clust_rec(), rec_get_trx_id():
Statically allocate the offsets
(should never use the heap). Add some debug assertions.

Replace some use of rec_get_trx_id() with row_get_rec_trx_id().

trx_undo_report_row_operation(): Add some sanity checks that are
common for all operations that produce undo log.
parent 53235cbb
...@@ -3679,6 +3679,11 @@ btr_cur_update_in_place( ...@@ -3679,6 +3679,11 @@ btr_cur_update_in_place(
was_delete_marked = rec_get_deleted_flag( was_delete_marked = rec_get_deleted_flag(
rec, page_is_comp(buf_block_get_frame(block))); rec, page_is_comp(buf_block_get_frame(block)));
/* In delete-marked records, DB_TRX_ID must always refer to an
existing undo log record. */
ut_ad(!was_delete_marked
|| !dict_index_is_clust(index)
|| row_get_rec_trx_id(rec, index, offsets));
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (block->index) { if (block->index) {
...@@ -4321,6 +4326,10 @@ btr_cur_pessimistic_update( ...@@ -4321,6 +4326,10 @@ btr_cur_pessimistic_update(
stored fields */ stored fields */
btr_cur_unmark_extern_fields( btr_cur_unmark_extern_fields(
page_zip, rec, index, *offsets, mtr); page_zip, rec, index, *offsets, mtr);
} else {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(row_get_rec_trx_id(rec, index, *offsets));
} }
bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG); bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG);
...@@ -4448,6 +4457,10 @@ btr_cur_pessimistic_update( ...@@ -4448,6 +4457,10 @@ btr_cur_pessimistic_update(
btr_cur_unmark_extern_fields(page_zip, btr_cur_unmark_extern_fields(page_zip,
rec, index, *offsets, mtr); rec, index, *offsets, mtr);
} else {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(row_get_rec_trx_id(rec, index, *offsets));
} }
if (!dict_table_is_locking_disabled(index->table)) { if (!dict_table_is_locking_disabled(index->table)) {
...@@ -4573,6 +4586,10 @@ btr_cur_parse_del_mark_set_clust_rec( ...@@ -4573,6 +4586,10 @@ btr_cur_parse_del_mark_set_clust_rec(
ut_a(offset <= UNIV_PAGE_SIZE); ut_a(offset <= UNIV_PAGE_SIZE);
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(trx_id || (flags & BTR_KEEP_SYS_FLAG));
if (page) { if (page) {
rec = page + offset; rec = page + offset;
...@@ -4582,22 +4599,35 @@ btr_cur_parse_del_mark_set_clust_rec( ...@@ -4582,22 +4599,35 @@ btr_cur_parse_del_mark_set_clust_rec(
and the adaptive hash index does not depend on them. */ and the adaptive hash index does not depend on them. */
btr_rec_set_deleted_flag(rec, page_zip, val); btr_rec_set_deleted_flag(rec, page_zip, val);
ut_ad(pos <= MAX_REF_PARTS);
if (!(flags & BTR_KEEP_SYS_FLAG)) { ulint offsets[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2];
rec_offs_init(offsets);
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs_init(offsets_);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_rec_sys_fields_in_recovery( row_upd_rec_sys_fields_in_recovery(
rec, page_zip, rec, page_zip,
rec_get_offsets(rec, index, offsets_, rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap), pos + 1, &heap),
pos, trx_id, roll_ptr); pos, trx_id, roll_ptr);
} else {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(memcmp(rec_get_nth_field(
rec,
rec_get_offsets(rec, index,
offsets, pos,
&heap),
pos, &offset),
field_ref_zero, DATA_TRX_ID_LEN));
ut_ad(offset == DATA_TRX_ID_LEN);
}
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
} }
} }
}
return(ptr); return(ptr);
} }
...@@ -4633,8 +4663,10 @@ btr_cur_del_mark_set_clust_rec( ...@@ -4633,8 +4663,10 @@ btr_cur_del_mark_set_clust_rec(
ut_ad(mtr->is_named_space(index->space)); ut_ad(mtr->is_named_space(index->space));
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* While cascading delete operations, this becomes possible. */ /* We may already have delete-marked this record
ut_ad(rec_get_trx_id(rec, index) == thr_get_trx(thr)->id); when executing an ON DELETE CASCADE operation. */
ut_ad(row_get_rec_trx_id(rec, index, offsets)
== thr_get_trx(thr)->id);
return(DB_SUCCESS); return(DB_SUCCESS);
} }
...@@ -4663,10 +4695,6 @@ btr_cur_del_mark_set_clust_rec( ...@@ -4663,10 +4695,6 @@ btr_cur_del_mark_set_clust_rec(
btr_rec_set_deleted_flag(rec, page_zip, TRUE); btr_rec_set_deleted_flag(rec, page_zip, TRUE);
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
/* This function must not be invoked during rollback
(of a TRX_STATE_PREPARE transaction or otherwise). */
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
ut_ad(!trx->in_rollback);
DBUG_LOG("ib_cur", DBUG_LOG("ib_cur",
"delete-mark clust " << index->table->name "delete-mark clust " << index->table->name
......
...@@ -1080,14 +1080,14 @@ class rec_printer : public std::ostringstream { ...@@ -1080,14 +1080,14 @@ class rec_printer : public std::ostringstream {
# endif /* !DBUG_OFF */ # endif /* !DBUG_OFF */
# ifdef UNIV_DEBUG # ifdef UNIV_DEBUG
/************************************************************//** /** Read the DB_TRX_ID of a clustered index record.
Reads the DB_TRX_ID of a clustered index record. @param[in] rec clustered index record
@param[in] index clustered index
@return the value of DB_TRX_ID */ @return the value of DB_TRX_ID */
trx_id_t trx_id_t
rec_get_trx_id( rec_get_trx_id(
/*===========*/ const rec_t* rec,
const rec_t* rec, /*!< in: record */ const dict_index_t* index)
const dict_index_t* index) /*!< in: clustered index */
MY_ATTRIBUTE((nonnull, warn_unused_result)); MY_ATTRIBUTE((nonnull, warn_unused_result));
# endif /* UNIV_DEBUG */ # endif /* UNIV_DEBUG */
......
...@@ -3711,6 +3711,10 @@ page_zip_write_rec( ...@@ -3711,6 +3711,10 @@ page_zip_write_rec(
ut_a(slot); ut_a(slot);
/* Copy the delete mark. */ /* Copy the delete mark. */
if (rec_get_deleted_flag(rec, TRUE)) { if (rec_get_deleted_flag(rec, TRUE)) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(!dict_index_is_clust(index)
|| row_get_rec_trx_id(rec, index, offsets));
*slot |= PAGE_ZIP_DIR_SLOT_DEL >> 8; *slot |= PAGE_ZIP_DIR_SLOT_DEL >> 8;
} else { } else {
*slot &= ~(PAGE_ZIP_DIR_SLOT_DEL >> 8); *slot &= ~(PAGE_ZIP_DIR_SLOT_DEL >> 8);
......
...@@ -2104,8 +2104,6 @@ rec_print_mbr_rec( ...@@ -2104,8 +2104,6 @@ rec_print_mbr_rec(
rec_validate(rec, offsets); rec_validate(rec, offsets);
} }
/***************************************************************//**
Prints a physical record. */
/***************************************************************//** /***************************************************************//**
Prints a physical record. */ Prints a physical record. */
void void
...@@ -2254,14 +2252,14 @@ operator<<(std::ostream& o, const rec_offsets_print& r) ...@@ -2254,14 +2252,14 @@ operator<<(std::ostream& o, const rec_offsets_print& r)
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/************************************************************//** /** Read the DB_TRX_ID of a clustered index record.
Reads the DB_TRX_ID of a clustered index record. @param[in] rec clustered index record
@param[in] index clustered index
@return the value of DB_TRX_ID */ @return the value of DB_TRX_ID */
trx_id_t trx_id_t
rec_get_trx_id( rec_get_trx_id(
/*===========*/ const rec_t* rec,
const rec_t* rec, /*!< in: record */ const dict_index_t* index)
const dict_index_t* index) /*!< in: clustered index */
{ {
const page_t* page const page_t* page
= page_align(rec); = page_align(rec);
...@@ -2270,10 +2268,11 @@ rec_get_trx_id( ...@@ -2270,10 +2268,11 @@ rec_get_trx_id(
const byte* trx_id; const byte* trx_id;
ulint len; ulint len;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2];
ulint* offsets = offsets_;
rec_offs_init(offsets_); rec_offs_init(offsets_);
ulint* offsets = offsets_;
ut_ad(trx_id_col <= MAX_REF_PARTS);
ut_ad(fil_page_index_page_check(page)); ut_ad(fil_page_index_page_check(page));
ut_ad(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID) ut_ad(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)
== index->id); == index->id);
...@@ -2287,7 +2286,7 @@ rec_get_trx_id( ...@@ -2287,7 +2286,7 @@ rec_get_trx_id(
ut_ad(len == DATA_TRX_ID_LEN); ut_ad(len == DATA_TRX_ID_LEN);
if (heap) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
} }
......
...@@ -346,6 +346,9 @@ row_ins_clust_index_entry_by_modify( ...@@ -346,6 +346,9 @@ row_ins_clust_index_entry_by_modify(
ut_ad(rec_get_deleted_flag(rec, ut_ad(rec_get_deleted_flag(rec,
dict_table_is_comp(cursor->index->table))); dict_table_is_comp(cursor->index->table)));
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(rec_get_trx_id(rec, cursor->index));
/* Build an update vector containing all the fields to be modified; /* Build an update vector containing all the fields to be modified;
NOTE that this vector may NOT contain system columns trx_id or NOTE that this vector may NOT contain system columns trx_id or
...@@ -1266,6 +1269,9 @@ row_ins_foreign_check_on_constraint( ...@@ -1266,6 +1269,9 @@ row_ins_foreign_check_on_constraint(
} }
if (rec_get_deleted_flag(clust_rec, dict_table_is_comp(table))) { if (rec_get_deleted_flag(clust_rec, dict_table_is_comp(table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(rec_get_trx_id(clust_rec, clust_index));
/* This can happen if there is a circular reference of /* This can happen if there is a circular reference of
rows such that cascading delete comes to delete a row rows such that cascading delete comes to delete a row
already in the process of being delete marked */ already in the process of being delete marked */
...@@ -1274,7 +1280,6 @@ row_ins_foreign_check_on_constraint( ...@@ -1274,7 +1280,6 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func; goto nonstandard_exit_func;
} }
if (table->fts) { if (table->fts) {
doc_id = fts_get_doc_id_from_rec(table, clust_rec, doc_id = fts_get_doc_id_from_rec(table, clust_rec,
clust_index, tmp_heap); clust_index, tmp_heap);
...@@ -1758,6 +1763,12 @@ row_ins_check_foreign_constraint( ...@@ -1758,6 +1763,12 @@ row_ins_check_foreign_constraint(
if (rec_get_deleted_flag(rec, if (rec_get_deleted_flag(rec,
rec_offs_comp(offsets))) { rec_offs_comp(offsets))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(!dict_index_is_clust(check_index)
|| row_get_rec_trx_id(rec, check_index,
offsets));
err = row_ins_set_shared_rec_lock( err = row_ins_set_shared_rec_lock(
lock_type, block, lock_type, block,
rec, check_index, offsets, thr); rec, check_index, offsets, thr);
......
...@@ -2130,10 +2130,10 @@ row_merge_read_clustered_index( ...@@ -2130,10 +2130,10 @@ row_merge_read_clustered_index(
rec = page_cur_get_rec(cur); rec = page_cur_get_rec(cur);
if (online) {
offsets = rec_get_offsets(rec, clust_index, NULL, offsets = rec_get_offsets(rec, clust_index, NULL,
ULINT_UNDEFINED, &row_heap); ULINT_UNDEFINED, &row_heap);
if (online) {
/* Perform a REPEATABLE READ. /* Perform a REPEATABLE READ.
When rebuilding the table online, When rebuilding the table online,
...@@ -2176,6 +2176,10 @@ row_merge_read_clustered_index( ...@@ -2176,6 +2176,10 @@ row_merge_read_clustered_index(
if (rec_get_deleted_flag( if (rec_get_deleted_flag(
rec, rec,
dict_table_is_comp(old_table))) { dict_table_is_comp(old_table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(row_get_rec_trx_id(rec, clust_index,
offsets));
/* This record was deleted in the latest /* This record was deleted in the latest
committed version, or it was deleted and committed version, or it was deleted and
then reinserted-by-update before purge then reinserted-by-update before purge
...@@ -2186,6 +2190,9 @@ row_merge_read_clustered_index( ...@@ -2186,6 +2190,9 @@ row_merge_read_clustered_index(
ut_ad(!rec_offs_any_null_extern(rec, offsets)); ut_ad(!rec_offs_any_null_extern(rec, offsets));
} else if (rec_get_deleted_flag( } else if (rec_get_deleted_flag(
rec, dict_table_is_comp(old_table))) { rec, dict_table_is_comp(old_table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(rec_get_trx_id(rec, clust_index));
/* Skip delete-marked records. /* Skip delete-marked records.
Skipping delete-marked records will make the Skipping delete-marked records will make the
...@@ -2195,6 +2202,9 @@ row_merge_read_clustered_index( ...@@ -2195,6 +2202,9 @@ row_merge_read_clustered_index(
would make it tricky to detect duplicate would make it tricky to detect duplicate
keys. */ keys. */
continue; continue;
} else {
offsets = rec_get_offsets(rec, clust_index, NULL,
ULINT_UNDEFINED, &row_heap);
} }
/* When !online, we are holding a lock on old_table, preventing /* When !online, we are holding a lock on old_table, preventing
......
...@@ -160,6 +160,9 @@ row_purge_remove_clust_if_poss_low( ...@@ -160,6 +160,9 @@ row_purge_remove_clust_if_poss_low(
} }
ut_ad(rec_get_deleted_flag(rec, rec_offs_comp(offsets))); ut_ad(rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(row_get_rec_trx_id(rec, index, offsets));
if (mode == BTR_MODIFY_LEAF) { if (mode == BTR_MODIFY_LEAF) {
success = btr_cur_optimistic_delete( success = btr_cur_optimistic_delete(
......
...@@ -183,6 +183,9 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -183,6 +183,9 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_get_deleted_flag(clust_rec, if (rec_get_deleted_flag(clust_rec,
dict_table_is_comp(clust_index->table))) { dict_table_is_comp(clust_index->table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(rec_get_trx_id(clust_rec, clust_index));
/* The clustered index record is delete-marked; /* The clustered index record is delete-marked;
it is not visible in the read view. Besides, it is not visible in the read view. Besides,
...@@ -2042,6 +2045,11 @@ row_sel( ...@@ -2042,6 +2045,11 @@ row_sel(
if (rec_get_deleted_flag(clust_rec, if (rec_get_deleted_flag(clust_rec,
dict_table_is_comp(plan->table))) { dict_table_is_comp(plan->table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing update_undo log record. */
ut_ad(rec_get_trx_id(clust_rec,
dict_table_get_first_index(
plan->table)));
/* The record is delete marked: we can skip it */ /* The record is delete marked: we can skip it */
...@@ -3934,6 +3942,9 @@ row_sel_try_search_shortcut_for_mysql( ...@@ -3934,6 +3942,9 @@ row_sel_try_search_shortcut_for_mysql(
} }
if (rec_get_deleted_flag(rec, dict_table_is_comp(index->table))) { if (rec_get_deleted_flag(rec, dict_table_is_comp(index->table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(row_get_rec_trx_id(rec, index, *offsets));
return(SEL_EXHAUSTED); return(SEL_EXHAUSTED);
} }
...@@ -5119,6 +5130,10 @@ row_search_mvcc( ...@@ -5119,6 +5130,10 @@ row_search_mvcc(
page_rec_is_comp() cannot be used! */ page_rec_is_comp() cannot be used! */
if (rec_get_deleted_flag(rec, comp)) { if (rec_get_deleted_flag(rec, comp)) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(index != clust_index
|| row_get_rec_trx_id(rec, index, offsets));
/* The record is delete-marked: we can skip it */ /* The record is delete-marked: we can skip it */
......
...@@ -230,6 +230,14 @@ row_undo_ins_remove_sec_low( ...@@ -230,6 +230,14 @@ row_undo_ins_remove_sec_low(
case ROW_NOT_FOUND: case ROW_NOT_FOUND:
goto func_exit; goto func_exit;
case ROW_FOUND: case ROW_FOUND:
if (dict_index_is_spatial(index)
&& rec_get_deleted_flag(
btr_pcur_get_rec(&pcur),
dict_table_is_comp(index->table))) {
ib::error() << "Record found in index " << index->name
<< " is deleted marked on insert rollback.";
ut_ad(0);
}
break; break;
case ROW_BUFFERED: case ROW_BUFFERED:
...@@ -240,15 +248,6 @@ row_undo_ins_remove_sec_low( ...@@ -240,15 +248,6 @@ row_undo_ins_remove_sec_low(
ut_error; ut_error;
} }
if (search_result == ROW_FOUND && dict_index_is_spatial(index)) {
rec_t* rec = btr_pcur_get_rec(&pcur);
if (rec_get_deleted_flag(rec,
dict_table_is_comp(index->table))) {
ib::error() << "Record found in index " << index->name
<< " is deleted marked on insert rollback.";
}
}
btr_cur = btr_pcur_get_btr_cur(&pcur); btr_cur = btr_pcur_get_btr_cur(&pcur);
if (modify_leaf) { if (modify_leaf) {
......
...@@ -215,6 +215,9 @@ row_undo_mod_remove_clust_low( ...@@ -215,6 +215,9 @@ row_undo_mod_remove_clust_low(
than the rolling-back one. */ than the rolling-back one. */
ut_ad(rec_get_deleted_flag(btr_cur_get_rec(btr_cur), ut_ad(rec_get_deleted_flag(btr_cur_get_rec(btr_cur),
dict_table_is_comp(node->table))); dict_table_is_comp(node->table)));
/* In delete-marked records, DB_TRX_ID must
always refer to an existing update_undo log record. */
ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur), btr_cur->index));
if (mode == BTR_MODIFY_LEAF) { if (mode == BTR_MODIFY_LEAF) {
err = btr_cur_optimistic_delete(btr_cur, 0, mtr) err = btr_cur_optimistic_delete(btr_cur, 0, mtr)
...@@ -350,8 +353,9 @@ row_undo_mod_clust( ...@@ -350,8 +353,9 @@ row_undo_mod_clust(
* it can be reallocated at any time after this mtr-commits * it can be reallocated at any time after this mtr-commits
* which is just below * which is just below
*/ */
ut_ad(srv_immediate_scrub_data_uncompressed || ut_ad(srv_immediate_scrub_data_uncompressed
rec_get_trx_id(btr_pcur_get_rec(pcur), index) == node->new_trx_id); || row_get_rec_trx_id(btr_pcur_get_rec(pcur), index, offsets)
== node->new_trx_id);
btr_pcur_commit_specify_mtr(pcur, &mtr); btr_pcur_commit_specify_mtr(pcur, &mtr);
...@@ -515,6 +519,7 @@ row_undo_mod_del_mark_or_remove_sec_low( ...@@ -515,6 +519,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
ib::error() << "Record found in index " ib::error() << "Record found in index "
<< index->name << " is deleted marked" << index->name << " is deleted marked"
" on rollback update."; " on rollback update.";
ut_ad(0);
} }
} }
......
...@@ -2663,7 +2663,8 @@ row_upd_clust_rec_by_insert( ...@@ -2663,7 +2663,8 @@ row_upd_clust_rec_by_insert(
marked, then we are here after a DB_LOCK_WAIT. marked, then we are here after a DB_LOCK_WAIT.
Skip delete marking clustered index and disowning Skip delete marking clustered index and disowning
its blobs. */ its blobs. */
ut_ad(rec_get_trx_id(rec, index) == trx->id); ut_ad(row_get_rec_trx_id(rec, index, offsets)
== trx->id);
ut_ad(!trx_undo_roll_ptr_is_insert( ut_ad(!trx_undo_roll_ptr_is_insert(
row_get_rec_roll_ptr(rec, index, row_get_rec_roll_ptr(rec, index,
offsets))); offsets)));
......
...@@ -906,6 +906,10 @@ trx_undo_page_report_modify( ...@@ -906,6 +906,10 @@ trx_undo_page_report_modify(
ut_ad(!rec_get_deleted_flag(rec, dict_table_is_comp(table))); ut_ad(!rec_get_deleted_flag(rec, dict_table_is_comp(table)));
type_cmpl = TRX_UNDO_DEL_MARK_REC; type_cmpl = TRX_UNDO_DEL_MARK_REC;
} else if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { } else if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing update_undo log record. */
ut_ad(row_get_rec_trx_id(rec, index, offsets));
type_cmpl = TRX_UNDO_UPD_DEL_REC; type_cmpl = TRX_UNDO_UPD_DEL_REC;
/* We are about to update a delete marked record. /* We are about to update a delete marked record.
We don't typically need the prefix in this case unless We don't typically need the prefix in this case unless
...@@ -1875,6 +1879,10 @@ trx_undo_report_row_operation( ...@@ -1875,6 +1879,10 @@ trx_undo_report_row_operation(
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
/* This function must not be invoked during rollback
(of a TRX_STATE_PREPARE transaction or otherwise). */
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
ut_ad(!trx->in_rollback);
mtr.start(); mtr.start();
trx_undo_t** pundo; trx_undo_t** pundo;
...@@ -1888,6 +1896,7 @@ trx_undo_report_row_operation( ...@@ -1888,6 +1896,7 @@ trx_undo_report_row_operation(
pundo = &trx->rsegs.m_noredo.undo; pundo = &trx->rsegs.m_noredo.undo;
} else { } else {
ut_ad(!trx->read_only); ut_ad(!trx->read_only);
ut_ad(trx->id);
/* Keep INFORMATION_SCHEMA.TABLES.UPDATE_TIME /* Keep INFORMATION_SCHEMA.TABLES.UPDATE_TIME
up-to-date for persistent tables. Temporary tables are up-to-date for persistent tables. Temporary tables are
not listed there. */ not listed there. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment