Skip to content

Commit e7b6e81

Browse files
committed
Bug #19138298 RECORD IN INDEX WAS NOT FOUND ON ROLLBACK, TRYING TO INSERT
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.
1 parent f5ac718 commit e7b6e81

File tree

2 files changed

+72
-13
lines changed

2 files changed

+72
-13
lines changed

storage/innobase/include/row0purge.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
3+
Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved.
44
55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -111,6 +111,17 @@ struct purge_node_struct{
111111
purge of a row */
112112
};
113113

114+
#ifdef UNIV_DEBUG
115+
/***********************************************************//**
116+
Validate the persisent cursor in the purge node. The purge node has two
117+
references to the clustered index record - one via the ref member, and the
118+
other via the persistent cursor. These two references must match each
119+
other if the found_clust flag is set.
120+
@return true if the persistent cursor is consistent with the ref member.*/
121+
ibool
122+
row_purge_validate_pcur(purge_node_t* node);
123+
#endif /* UNIV_DEBUG */
124+
114125
#ifndef UNIV_NONINL
115126
#include "row0purge.ic"
116127
#endif

storage/innobase/row/row0purge.c

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved.
44
55
This program is free software; you can redistribute it and/or modify it under
66
the terms of the GNU General Public License as published by the Free Software
@@ -90,23 +90,23 @@ row_purge_reposition_pcur(
9090
purge_node_t* node, /*!< in: row purge node */
9191
mtr_t* mtr) /*!< in: mtr */
9292
{
93-
ibool found;
94-
9593
if (node->found_clust) {
96-
found = btr_pcur_restore_position(mode, &(node->pcur), mtr);
94+
ut_ad(row_purge_validate_pcur(node));
9795

98-
return(found);
99-
}
96+
node->found_clust = btr_pcur_restore_position(
97+
mode, &(node->pcur), mtr);
98+
99+
} else {
100100

101-
found = row_search_on_row_ref(&(node->pcur), mode, node->table,
102-
node->ref, mtr);
103-
node->found_clust = found;
101+
node->found_clust = row_search_on_row_ref(
102+
&(node->pcur), mode, node->table, node->ref, mtr);
104103

105-
if (found) {
106-
btr_pcur_store_position(&(node->pcur), mtr);
104+
if (node->found_clust) {
105+
btr_pcur_store_position(&(node->pcur), mtr);
106+
}
107107
}
108108

109-
return(found);
109+
return(node->found_clust);
110110
}
111111

112112
/***********************************************************//**
@@ -806,3 +806,51 @@ row_purge_step(
806806

807807
return(thr);
808808
}
809+
810+
#ifdef UNIV_DEBUG
811+
/***********************************************************//**
812+
Validate the persisent cursor in the purge node. The purge node has two
813+
references to the clustered index record - one via the ref member, and the
814+
other via the persistent cursor. These two references must match each
815+
other if the found_clust flag is set.
816+
@return true if the persistent cursor is consistent with the ref member.*/
817+
ibool
818+
row_purge_validate_pcur(
819+
purge_node_t* node)
820+
{
821+
const rec_t* rec ;
822+
dict_index_t* clust_index;
823+
ulint* offsets;
824+
int st;
825+
826+
if (!node->found_clust) {
827+
return(TRUE);
828+
}
829+
830+
if (node->index == NULL) {
831+
return(TRUE);
832+
}
833+
834+
clust_index = node->pcur.btr_cur.index;
835+
836+
if (node->pcur.old_stored == BTR_PCUR_OLD_STORED) {
837+
rec = node->pcur.old_rec;
838+
} else {
839+
rec = btr_pcur_get_rec(&node->pcur);
840+
}
841+
842+
offsets = rec_get_offsets(rec,
843+
clust_index, NULL, ULINT_UNDEFINED, &node->heap);
844+
845+
st = cmp_dtuple_rec(node->ref, rec, offsets);
846+
847+
if (st != 0) {
848+
fprintf(stderr, "Purge node pcur validation failed\n");
849+
dtuple_print(stderr, node->ref);
850+
rec_print(stderr, rec, clust_index);
851+
return(FALSE);
852+
}
853+
854+
return(TRUE);
855+
}
856+
#endif /* UNIV_DEBUG */

0 commit comments

Comments
 (0)