Commit 417a2679 authored by Marko Mäkelä's avatar Marko Mäkelä

Re-enable the debug assertions for Bug#12650861.

Replace UNIV_BLOB_NULL_DEBUG with UNIV_DEBUG||UNIV_BLOB_LIGHT_DEBUG. 
Fix known bogus failures.

btr_cur_optimistic_update(): If rec_offs_any_null_extern(), assert that
the current transaction is an incomplete transaction that is being
rolled back in crash recovery.

row_build(): If rec_offs_any_null_extern(), assert that the transaction
that last updated the record was recovered during crash recovery
(and will soon be rolled back).
parent 5b4ceba5
......@@ -31,6 +31,7 @@ Created 10/16/1994 Heikki Tuuri
#include "btr0sea.h"
#include "row0upd.h"
#include "trx0rec.h"
#include "trx0roll.h" /* trx_roll_crash_recv_trx */
#include "que0que.h"
#include "row0row.h"
#include "srv0srv.h"
......@@ -1579,7 +1580,6 @@ btr_cur_optimistic_update(
ulint old_rec_size;
dtuple_t* new_entry;
dulint roll_ptr;
trx_t* trx;
mem_heap_t* heap;
ibool reorganized = FALSE;
ulint i;
......@@ -1592,9 +1592,10 @@ btr_cur_optimistic_update(
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
#ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets)
|| thr_get_trx(thr) == trx_roll_crash_recv_trx);
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
......@@ -1701,13 +1702,11 @@ btr_cur_optimistic_update(
page_cur_move_to_prev(page_cursor);
trx = thr_get_trx(thr);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
trx->id);
thr_get_trx(thr)->id);
}
rec = btr_cur_insert_if_possible(cursor, new_entry, &reorganized, mtr);
......
......@@ -339,7 +339,7 @@ rec_offs_any_extern(
/*================*/
/* out: TRUE if a field is stored externally */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/********************************************************
Determine if the offsets are for a record containing null BLOB pointers. */
UNIV_INLINE
......@@ -351,7 +351,7 @@ rec_offs_any_null_extern(
or NULL if none found */
rec_t* rec, /*!< in: record */
const ulint* offsets); /*!< in: rec_get_offsets(rec) */
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/***************************************************************
Sets the value of the ith field extern storage bit. */
UNIV_INLINE
......
......@@ -1021,7 +1021,7 @@ rec_offs_any_extern(
return(FALSE);
}
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/********************************************************
Determine if the offsets are for a record containing null BLOB pointers. */
UNIV_INLINE
......@@ -1055,7 +1055,7 @@ rec_offs_any_null_extern(
return(NULL);
}
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/***************************************************************
Sets the value of the ith field extern storage bit. */
......
......@@ -15,6 +15,9 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
/* In crash recovery, the current trx to be rolled back */
extern trx_t* trx_roll_crash_recv_trx;
#define trx_roll_free_all_savepoints(s) trx_roll_savepoints_free((s), NULL)
/***********************************************************************
......
......@@ -88,8 +88,8 @@ memory is read outside the allocated blocks. */
#if 0
#define UNIV_DEBUG_VALGRIND /* Enable extra
Valgrind instrumentation */
#define UNIV_BLOB_NULL_DEBUG /* Enable deep off-page
column debugging */
#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
debugging without UNIV_DEBUG */
#define UNIV_DEBUG /* Enable ut_ad() assertions */
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
......
......@@ -202,6 +202,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(!mutex_own(&kernel_mutex));
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
......@@ -210,13 +211,37 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets));
}
#if 0 && defined UNIV_BLOB_NULL_DEBUG
/* This one can fail in trx_rollback_or_clean_all_without_sess()
if the server crashed during an insert before the
btr_store_big_rec_extern_fields() did mtr_commit()
all BLOB pointers to the clustered index record. */
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* 0 && UNIV_BLOB_NULL_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
if (UNIV_LIKELY_NULL(rec_offs_any_null_extern(rec, offsets))) {
/* This condition can occur during crash recovery before
trx_rollback_or_clean_all_without_sess() has completed
execution.
This condition is possible if the server crashed
during an insert or update before
btr_store_big_rec_extern_fields() did mtr_commit() all
BLOB pointers to the clustered index record.
Look up the transaction that holds the implicit lock
on this record, and assert that it was recovered (and
will soon be rolled back). */
ulint trx_id_pos = dict_index_get_sys_col_pos(
index, DATA_TRX_ID);
ulint len;
dulint trx_id = trx_read_trx_id(
rec_get_nth_field(rec, offsets, trx_id_pos, &len));
trx_t* trx;
ut_a(len == 6);
mutex_enter(&kernel_mutex);
trx = trx_get_on_id(trx_id);
ut_a(trx);
/* This field does not exist in this version of InnoDB. */
/* ut_a(trx->is_recovered); */
mutex_exit(&kernel_mutex);
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
......@@ -310,10 +335,10 @@ row_rec_to_index_entry(
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets);
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
} else {
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}
rec_len = rec_offs_n_fields(offsets);
......
......@@ -473,10 +473,10 @@ row_vers_build_for_consistent_read(
/* The view already sees this version: we can
copy it to in_heap and return */
#if defined UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(
version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
buf = mem_heap_alloc(in_heap,
rec_offs_size(*offsets));
......@@ -511,9 +511,9 @@ row_vers_build_for_consistent_read(
*offsets = rec_get_offsets(prev_version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
......@@ -615,9 +615,9 @@ row_vers_build_for_semi_consistent_read(
/* We found a version that belongs to a
committed transaction: return it. */
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (rec == version) {
*old_vers = rec;
......@@ -676,9 +676,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}/* for (;;) */
if (heap) {
......
......@@ -1397,9 +1397,9 @@ trx_undo_prev_version_build(
return(DB_ERROR);
}
# ifdef UNIV_BLOB_NULL_DEBUG
# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets));
# endif /* UNIV_BLOB_NULL_DEBUG */
# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint* ext_vect;
......
......@@ -1854,7 +1854,6 @@ btr_cur_optimistic_update(
ulint old_rec_size;
dtuple_t* new_entry;
roll_ptr_t roll_ptr;
trx_t* trx;
mem_heap_t* heap;
ulint i;
ulint n_ext;
......@@ -1871,9 +1870,10 @@ btr_cur_optimistic_update(
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
#ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets)
|| trx_is_recv(thr_get_trx(thr)));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
......@@ -1996,13 +1996,11 @@ any_extern:
page_cur_move_to_prev(page_cursor);
trx = thr_get_trx(thr);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
trx->id);
thr_get_trx(thr)->id);
}
/* There are no externally stored columns in new_entry */
......
......@@ -480,7 +480,7 @@ ulint
rec_offs_any_extern(
/*================*/
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/******************************************************//**
Determine if the offsets are for a record containing null BLOB pointers.
@return first field containing a null BLOB pointer, or NULL if none found */
......@@ -491,7 +491,7 @@ rec_offs_any_null_extern(
const rec_t* rec, /*!< in: record */
const ulint* offsets) /*!< in: rec_get_offsets(rec) */
__attribute__((nonnull, warn_unused_result));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
......
......@@ -1088,7 +1088,7 @@ rec_offs_any_extern(
return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL));
}
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/******************************************************//**
Determine if the offsets are for a record containing null BLOB pointers.
@return first field containing a null BLOB pointer, or NULL if none found */
......@@ -1124,7 +1124,7 @@ rec_offs_any_null_extern(
return(NULL);
}
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
......
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Sun Microsystems, Inc.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -179,8 +178,6 @@ command. Not tested on Windows. */
debugging without UNIV_DEBUG */
#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
debugging without UNIV_DEBUG */
#define UNIV_BLOB_NULL_DEBUG /* Enable deep off-page
column debugging */
#define UNIV_DEBUG /* Enable ut_ad() assertions
and disable UNIV_INLINE */
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable
......
......@@ -223,6 +223,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(dict_index_is_clust(index));
ut_ad(!mutex_own(&kernel_mutex));
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
......@@ -231,13 +232,35 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets));
}
#if 0 && defined UNIV_BLOB_NULL_DEBUG
/* This one can fail in trx_rollback_active() if
the server crashed during an insert before the
btr_store_big_rec_extern_fields() did mtr_commit()
all BLOB pointers to the clustered index record. */
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* 0 && UNIV_BLOB_NULL_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
if (UNIV_LIKELY_NULL(rec_offs_any_null_extern(rec, offsets))) {
/* This condition can occur during crash recovery before
trx_rollback_active() has completed execution.
This condition is possible if the server crashed
during an insert or update before
btr_store_big_rec_extern_fields() did mtr_commit() all
BLOB pointers to the clustered index record.
Look up the transaction that holds the implicit lock
on this record, and assert that it was recovered (and
will soon be rolled back). */
ulint trx_id_pos = dict_index_get_sys_col_pos(
index, DATA_TRX_ID);
ulint len;
trx_id_t trx_id = trx_read_trx_id(
rec_get_nth_field(rec, offsets, trx_id_pos, &len));
trx_t* trx;
ut_a(len == 6);
mutex_enter(&kernel_mutex);
trx = trx_get_on_id(trx_id);
ut_a(trx);
ut_a(trx->is_recovered);
mutex_exit(&kernel_mutex);
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
......@@ -423,10 +446,10 @@ row_rec_to_index_entry(
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets);
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
} else {
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}
entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
......
......@@ -550,10 +550,10 @@ row_vers_build_for_consistent_read(
/* The view already sees this version: we can
copy it to in_heap and return */
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(
version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
buf = mem_heap_alloc(in_heap,
rec_offs_size(*offsets));
......@@ -588,9 +588,9 @@ row_vers_build_for_consistent_read(
*offsets = rec_get_offsets(prev_version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
......@@ -691,9 +691,9 @@ row_vers_build_for_semi_consistent_read(
/* We found a version that belongs to a
committed transaction: return it. */
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (rec == version) {
*old_vers = rec;
......@@ -752,9 +752,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
#ifdef UNIV_BLOB_NULL_DEBUG
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(version, *offsets));
#endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}/* for (;;) */
if (heap) {
......
......@@ -1577,9 +1577,9 @@ trx_undo_prev_version_build(
return(DB_ERROR);
}
# ifdef UNIV_BLOB_NULL_DEBUG
# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets));
# endif /* UNIV_BLOB_NULL_DEBUG */
# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint n_ext;
......
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