summaryrefslogtreecommitdiff
path: root/innobase/lock/lock0lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/lock/lock0lock.c')
-rw-r--r--innobase/lock/lock0lock.c86
1 files changed, 82 insertions, 4 deletions
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 4bb1d243ed4..fecb1f95c68 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -356,7 +356,7 @@ lock_mutex_enter_kernel(void)
}
/*************************************************************************
-Releses the kernel mutex. This function is used in this module to allow
+Releases the kernel mutex. This function is used in this module to allow
monitoring the contention degree on the kernel mutex caused by the lock
operations. */
UNIV_INLINE
@@ -515,6 +515,53 @@ lock_rec_mutex_own_all(void)
#endif
/*************************************************************************
+Checks that a transaction id is sensible, i.e., not in the future. */
+
+ibool
+lock_check_trx_id_sanity(
+/*=====================*/
+ /* out: TRUE if ok */
+ dulint trx_id, /* in: trx id */
+ rec_t* rec, /* in: user record */
+ dict_index_t* index, /* in: clustered index */
+ ibool has_kernel_mutex)/* in: TRUE if the caller owns the
+ kernel mutex */
+{
+ char err_buf[500];
+ ibool is_ok = TRUE;
+
+ if (!has_kernel_mutex) {
+ mutex_enter(&kernel_mutex);
+ }
+
+ /* A sanity check: the trx_id in rec must be smaller than the global
+ trx id counter */
+
+ if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
+ rec_sprintf(err_buf, 400, rec);
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+"InnoDB: Error: transaction id associated with record\n%s\n"
+"InnoDB: in table %s index %s\n"
+"InnoDB: is %lu %lu which is higher than the global trx id counter %lu %lu!\n"
+"InnoDB: The table is corrupt. You have to do dump + drop + reimport.\n",
+ err_buf, index->table_name, index->name,
+ ut_dulint_get_high(trx_id),
+ ut_dulint_get_low(trx_id),
+ ut_dulint_get_high(trx_sys->max_trx_id),
+ ut_dulint_get_low(trx_sys->max_trx_id));
+
+ is_ok = FALSE;
+ }
+
+ if (!has_kernel_mutex) {
+ mutex_exit(&kernel_mutex);
+ }
+
+ return(is_ok);
+}
+
+/*************************************************************************
Checks that a record is seen in a consistent read. */
ibool
@@ -539,6 +586,15 @@ lock_clust_rec_cons_read_sees(
return(TRUE);
}
+ if (!lock_check_trx_id_sanity(trx_id, rec, index, FALSE)) {
+ /* Trying to get the 'history' of a corrupt record is bound
+ to fail: let us try to use the record itself in the query */
+ fprintf(stderr,
+"InnoDB: We try to access the corrupt record in the query anyway.\n");
+
+ return(TRUE);
+ }
+
return(FALSE);
}
@@ -562,7 +618,9 @@ lock_sec_rec_cons_read_sees(
read_view_t* view) /* in: consistent read view */
{
dulint max_trx_id;
-
+
+ UT_NOT_USED(index);
+
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec));
@@ -575,6 +633,16 @@ lock_sec_rec_cons_read_sees(
if (ut_dulint_cmp(max_trx_id, view->up_limit_id) >= 0) {
+ if (!lock_check_trx_id_sanity(max_trx_id, rec, index, FALSE)) {
+ /* Trying to get the 'history' of a corrupt record is
+ bound to fail: let us try to use the record itself in
+ the query */
+ fprintf(stderr,
+"InnoDB: We try to access the corrupt record in the query anyway.\n");
+
+ return(TRUE);
+ }
+
return(FALSE);
}
@@ -1569,6 +1637,15 @@ lock_sec_rec_some_has_impl_off_kernel(
/* Ok, in this case it is possible that some transaction has an
implicit x-lock. We have to look in the clustered index. */
+ if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index,
+ TRUE)) {
+ buf_page_print(page);
+
+ /* The page is corrupt: try to avoid a crash by returning
+ NULL */
+ return(NULL);
+ }
+
return(row_vers_impl_x_locked_off_kernel(rec, index));
}
@@ -2565,7 +2642,7 @@ lock_move_rec_list_start(
ulint heap_no;
ulint type_mode;
- ut_ad(new_page);
+ ut_a(new_page);
lock_mutex_enter_kernel();
@@ -3028,7 +3105,7 @@ lock_deadlock_recursive(
we return LOCK_VICTIM_IS_START */
{
lock_t* lock;
- ulint bit_no;
+ ulint bit_no = ULINT_UNDEFINED;
trx_t* lock_trx;
char* err_buf;
ulint ret;
@@ -3067,6 +3144,7 @@ lock_deadlock_recursive(
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
} else {
ut_ad(lock_get_type(lock) == LOCK_REC);
+ ut_a(bit_no != ULINT_UNDEFINED);
lock = lock_rec_get_prev(lock, bit_no);
}