summaryrefslogtreecommitdiff
path: root/innobase/row/row0vers.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/row/row0vers.c')
-rw-r--r--innobase/row/row0vers.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index cd8b18e5e12..d4a463d8a96 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -27,6 +27,7 @@ Created 2/6/1997 Heikki Tuuri
#include "row0upd.h"
#include "rem0cmp.h"
#include "read0read.h"
+#include "lock0lock.h"
/*********************************************************************
Finds out if an active transaction has inserted or modified a secondary
@@ -58,7 +59,6 @@ row_vers_impl_x_locked_off_kernel(
ibool rec_del;
ulint err;
mtr_t mtr;
- char err_buf[1000];
ut_ad(mutex_own(&kernel_mutex));
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
@@ -76,22 +76,20 @@ row_vers_impl_x_locked_off_kernel(
clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index,
&clust_index, &mtr);
if (!clust_rec) {
- rec_sprintf(err_buf, 900, rec);
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: cannot find the clustered index record\n"
-"InnoDB: for a secondary index record in table %s index %s.\n"
-"InnoDB: Secondary index record %s.\n"
-"InnoDB: The table is probably corrupt. Please run CHECK TABLE on it.\n"
-"InnoDB: You can try to repair the table by dump + drop + reimport.\n"
-"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n",
- index->table_name, index->name, err_buf);
- mutex_enter(&kernel_mutex);
- mtr_commit(&mtr);
-
- /* We assume there is no lock on the record, though this
- is not certain because the table is apparently corrupt */
+ /* In a rare case it is possible that no clust rec is found
+ for a secondary index record: if in row0umod.c
+ row_undo_mod_remove_clust_low() we have already removed the
+ clust rec, while purge is still cleaning and removing
+ secondary index records associated with earlier versions of
+ the clustered index record. In that case there cannot be
+ any implicit lock on the secondary index record, because
+ an active transaction which has modified the secondary index
+ record has also modified the clustered index record. And in
+ a rollback we always undo the modifications to secondary index
+ records before the clustered index record. */
+
+ mutex_enter(&kernel_mutex);
+ mtr_commit(&mtr);
return(NULL);
}
@@ -111,6 +109,14 @@ row_vers_impl_x_locked_off_kernel(
return(NULL);
}
+ if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index, TRUE)) {
+ /* Corruption noticed: try to avoid a crash by returning */
+
+ mtr_commit(&mtr);
+
+ return(NULL);
+ }
+
/* We look up if some earlier version of the clustered index record
would require rec to be in a different state (delete marked or
unmarked, or not existing). If there is such a version, then rec was
@@ -177,7 +183,8 @@ row_vers_impl_x_locked_off_kernel(
/* If we get here, we know that the trx_id transaction is
still active and it has modified prev_version. Let us check
- if prev_version would require rec to be in a different state. */
+ if prev_version would require rec to be in a different
+ state. */
vers_del = rec_get_deleted_flag(prev_version);