Permalink
Browse files

Bug #19138298 RECORD IN INDEX WAS NOT FOUND ON ROLLBACK, TRYING TO IN…

…SERT

Scenario:

1. The purge thread takes an undo log record and parses it and forms
   the record to be purged. We have the primary and secondary keys
   to locate the actual records.
2. Using the secondary index key, we search in the secondary index.
   One record is found.
3. Then it is checked if this record can be purged.  The answer is we
   can purge this record.  To determine this we look up the clustered
   index record.  Either there is no corresponding clustered index
   record, or the matching clustered index record is delete marked.
4. Then we check whether the secondary index record is delete marked.
   We find that it is not delete marked.  We report warning in optimized
   build and assert in debug build.

Problem:

In step 3, we report that the record is purgeable even though it is
not delete marked.  This is because of inconsistency between the
following members of purge_node_t structure - found_clust, ref and pcur.

Solution:

In the row_purge_reposition_pcur(), if the persistent cursor restore
fails, then reset the purge_node_t->found_clust member.  This will
keep the members of purge_node_t structure in a consistent state.

rb#8813 approved by Marko.
  • Loading branch information...
gurusami committed May 9, 2015
1 parent b984d61 commit 982a157c71667040838def7a00d951ffc55eccbc
Showing with 63 additions and 5 deletions.
  1. +11 −1 storage/innobase/include/row0purge.h
  2. +52 −4 storage/innobase/row/row0purge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2015, 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
@@ -119,6 +119,16 @@ struct purge_node_t{
clustered index record */
ibool done; /* Debug flag */
#ifdef UNIV_DEBUG
/***********************************************************//**
Validate the persisent cursor. The purge node has two references
to the clustered index record - one via the ref member, and the
other via the persistent cursor. These two references must match
each other if the found_clust flag is set.
@return true if the persistent cursor is consistent with
the ref member.*/
bool validate_pcur();
#endif
};
#ifndef UNIV_NONINL
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2015, 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
@@ -95,11 +95,10 @@ row_purge_reposition_pcur(
mtr_t* mtr) /*!< in: mtr */
{
if (node->found_clust) {
ibool found;
ut_ad(node->validate_pcur());
found = btr_pcur_restore_position(mode, &node->pcur, mtr);
node->found_clust = btr_pcur_restore_position(mode, &node->pcur, mtr);
return(found);
} else {
node->found_clust = row_search_on_row_ref(
&node->pcur, mode, node->table, node->ref, mtr);
@@ -831,6 +830,8 @@ row_purge_record_func(
dict_index_t* clust_index;
bool purged = true;
ut_ad(!node->found_clust);
clust_index = dict_table_get_first_index(node->table);
node->index = dict_table_get_next_index(clust_index);
@@ -986,3 +987,50 @@ row_purge_step(
return(thr);
}
#ifdef UNIV_DEBUG
/***********************************************************//**
Validate the persisent cursor. The purge node has two references
to the clustered index record - one via the ref member, and the
other via the persistent cursor. These two references must match
each other if the found_clust flag is set.
@return true if the persistent cursor is consistent with
the ref member.*/
bool
purge_node_t::validate_pcur()
{
if (!found_clust) {
return(true);
}
if (index == NULL) {
return(true);
}
if (index->type == DICT_FTS) {
return(true);
}
const rec_t* rec ;
dict_index_t* clust_index = pcur.btr_cur.index;
if (pcur.old_stored == BTR_PCUR_OLD_STORED) {
rec = pcur.old_rec;
} else {
rec = btr_pcur_get_rec(&pcur);
}
ulint* offsets = rec_get_offsets(rec,
clust_index, NULL, ULINT_UNDEFINED, &heap);
int st = cmp_dtuple_rec(ref, rec, offsets);
if (st != 0) {
fprintf(stderr, "Purge node pcur validation failed\n");
dtuple_print(stderr, ref);
rec_print(stderr, rec, clust_index);
return(false);
}
return(true);
}
#endif /* UNIV_DEBUG */

0 comments on commit 982a157

Please sign in to comment.