mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
Bug#59230 assert 0 row_upd_changes_ord_field_binary() in post-crash
trx rollback or purge This patch does not relax the failing debug assertion during purge. That will be revisited once we have managed to repeat the assertion failure. row_upd_changes_ord_field_binary_func(): Renamed from row_upd_changes_ord_field_binary(). Add the parameter que_thr_t* in UNIV_DEBUG builds. When the off-page column cannot be retrieved, assert that the current transaction is a recovered one and that it is the one that is currently being rolled back. row_upd_changes_ord_field_binary(): A wrapper macro for row_upd_changes_ord_field_binary_func() that discards the que_thr_t* parameter unless UNIV_DEBUG is defined. row_purge_upd_exist_or_extern_func(): Renamed from row_purge_upd_exist_or_extern(). Add the parameter que_thr_t* in UNIV_DEBUG builds. row_purge_upd_exist_or_extern(): A wrapper macro for row_purge_upd_exist_or_extern_func() that discards the que_thr_t* parameter unless UNIV_DEBUG is defined. Make trx_roll_crash_recv_trx const. If there were a 'do not dereference' attribute, it would be appropriate as well. rb://588 approved by Jimmy Yang
This commit is contained in:
parent
7751e38cd0
commit
e952ee1158
7 changed files with 74 additions and 34 deletions
|
@ -1,3 +1,10 @@
|
|||
2011-01-31 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, include/row0upd.h,
|
||||
row/row0purge.c, row/row0umod.c, row/row0upd.c:
|
||||
Bug#59230 assert 0 row_upd_changes_ord_field_binary()
|
||||
in post-crash rollback or purge
|
||||
|
||||
2011-01-27 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c:
|
||||
|
|
|
@ -1768,8 +1768,8 @@ btr_cur_update_in_place(
|
|||
NOT call it if index is secondary */
|
||||
|
||||
if (!dict_index_is_clust(index)
|
||||
|| row_upd_changes_ord_field_binary(NULL, NULL,
|
||||
index, update)) {
|
||||
|| row_upd_changes_ord_field_binary(index, update, thr,
|
||||
NULL, NULL)) {
|
||||
|
||||
/* Remove possible hash index pointer to this record */
|
||||
btr_search_update_hash_on_delete(cursor);
|
||||
|
|
|
@ -280,19 +280,29 @@ NOTE: we compare the fields as binary strings!
|
|||
@return TRUE if update vector changes an ordering field in the index record */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
row_upd_changes_ord_field_binary(
|
||||
/*=============================*/
|
||||
row_upd_changes_ord_field_binary_func(
|
||||
/*==================================*/
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update, /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
#ifdef UNIV_DEBUG
|
||||
const que_thr_t*thr, /*!< in: query thread */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const dtuple_t* row, /*!< in: old value of row, or NULL if the
|
||||
row and the data values in update are not
|
||||
known when this function is called, e.g., at
|
||||
compile time */
|
||||
const row_ext_t*ext, /*!< NULL, or prefixes of the externally
|
||||
const row_ext_t*ext) /*!< NULL, or prefixes of the externally
|
||||
stored columns in the old row */
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update) /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
__attribute__((nonnull(3,4), warn_unused_result));
|
||||
__attribute__((nonnull(1,2), warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
|
||||
row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
|
||||
row_upd_changes_ord_field_binary_func(index,update,row,ext)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/***********************************************************//**
|
||||
Checks if an update vector changes an ordering field of an index record.
|
||||
This function is fast if the update vector is short or the number of ordering
|
||||
|
|
|
@ -387,8 +387,11 @@ Purges an update of an existing record. Also purges an update of a delete
|
|||
marked record if that record contained an externally stored field. */
|
||||
static
|
||||
void
|
||||
row_purge_upd_exist_or_extern(
|
||||
/*==========================*/
|
||||
row_purge_upd_exist_or_extern_func(
|
||||
/*===============================*/
|
||||
#ifdef UNIV_DEBUG
|
||||
const que_thr_t*thr, /*!< in: query thread */
|
||||
#endif /* UNIV_DEBUG */
|
||||
purge_node_t* node) /*!< in: row purge node */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
|
@ -413,8 +416,8 @@ row_purge_upd_exist_or_extern(
|
|||
while (node->index != NULL) {
|
||||
index = node->index;
|
||||
|
||||
if (row_upd_changes_ord_field_binary(NULL, NULL, node->index,
|
||||
node->update)) {
|
||||
if (row_upd_changes_ord_field_binary(node->index, node->update,
|
||||
thr, NULL, NULL)) {
|
||||
/* Build the older version of the index entry */
|
||||
entry = row_build_index_entry(node->row, NULL,
|
||||
index, heap);
|
||||
|
@ -496,6 +499,14 @@ skip_secondaries:
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
# define row_purge_upd_exist_or_extern(thr,node) \
|
||||
row_purge_upd_exist_or_extern_func(thr,node)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define row_purge_upd_exist_or_extern(thr,node) \
|
||||
row_purge_upd_exist_or_extern_func(node)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/***********************************************************//**
|
||||
Parses the row reference and other info in a modify undo log record.
|
||||
@return TRUE if purge operation required: NOTE that then the CALLER
|
||||
|
@ -654,7 +665,7 @@ row_purge(
|
|||
} else if (updated_extern
|
||||
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
|
||||
|
||||
row_purge_upd_exist_or_extern(node);
|
||||
row_purge_upd_exist_or_extern(thr, node);
|
||||
}
|
||||
|
||||
if (node->found_clust) {
|
||||
|
|
|
@ -668,8 +668,9 @@ row_undo_mod_upd_exist_sec(
|
|||
while (node->index != NULL) {
|
||||
index = node->index;
|
||||
|
||||
if (row_upd_changes_ord_field_binary(
|
||||
node->row, node->ext, node->index, node->update)) {
|
||||
if (row_upd_changes_ord_field_binary(node->index, node->update,
|
||||
thr,
|
||||
node->row, node->ext)) {
|
||||
|
||||
/* Build the newest version of the index entry */
|
||||
entry = row_build_index_entry(node->row, node->ext,
|
||||
|
|
|
@ -1192,25 +1192,31 @@ NOTE: we compare the fields as binary strings!
|
|||
@return TRUE if update vector changes an ordering field in the index record */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
row_upd_changes_ord_field_binary(
|
||||
/*=============================*/
|
||||
row_upd_changes_ord_field_binary_func(
|
||||
/*==================================*/
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update, /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
#ifdef UNIV_DEBUG
|
||||
const que_thr_t*thr, /*!< in: query thread */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const dtuple_t* row, /*!< in: old value of row, or NULL if the
|
||||
row and the data values in update are not
|
||||
known when this function is called, e.g., at
|
||||
compile time */
|
||||
const row_ext_t*ext, /*!< NULL, or prefixes of the externally
|
||||
const row_ext_t*ext) /*!< NULL, or prefixes of the externally
|
||||
stored columns in the old row */
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update) /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
{
|
||||
ulint n_unique;
|
||||
ulint i;
|
||||
const dict_index_t* clust_index;
|
||||
|
||||
ut_ad(update);
|
||||
ut_ad(index);
|
||||
ut_ad(update);
|
||||
ut_ad(thr);
|
||||
ut_ad(thr->graph);
|
||||
ut_ad(thr->graph->trx);
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
|
@ -1263,9 +1269,14 @@ row_upd_changes_ord_field_binary(
|
|||
|
||||
if (UNIV_LIKELY_NULL(buf)) {
|
||||
if (UNIV_UNLIKELY(buf == field_ref_zero)) {
|
||||
/* This should never happen, but
|
||||
we try to fail safe here. */
|
||||
ut_ad(0);
|
||||
/* The externally stored field
|
||||
was not written yet. This
|
||||
record should only be seen by
|
||||
recv_recovery_rollback_active(),
|
||||
when the server had crashed before
|
||||
storing the field. */
|
||||
ut_ad(thr->graph->trx->is_recovered);
|
||||
ut_ad(trx_is_recv(thr->graph->trx));
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
@ -1612,8 +1623,8 @@ row_upd_sec_step(
|
|||
ut_ad(!dict_index_is_clust(node->index));
|
||||
|
||||
if (node->state == UPD_NODE_UPDATE_ALL_SEC
|
||||
|| row_upd_changes_ord_field_binary(node->row, node->ext,
|
||||
node->index, node->update)) {
|
||||
|| row_upd_changes_ord_field_binary(node->index, node->update,
|
||||
thr, node->row, node->ext)) {
|
||||
return(row_upd_sec_index_entry(node, thr));
|
||||
}
|
||||
|
||||
|
@ -2140,8 +2151,8 @@ exit_func:
|
|||
|
||||
row_upd_store_row(node);
|
||||
|
||||
if (row_upd_changes_ord_field_binary(node->row, node->ext, index,
|
||||
node->update)) {
|
||||
if (row_upd_changes_ord_field_binary(index, node->update, thr,
|
||||
node->row, node->ext)) {
|
||||
|
||||
/* Update causes an ordering field (ordering fields within
|
||||
the B-tree) of the clustered index record to change: perform
|
||||
|
|
|
@ -48,8 +48,8 @@ Created 3/26/1996 Heikki Tuuri
|
|||
rollback */
|
||||
#define TRX_ROLL_TRUNC_THRESHOLD 1
|
||||
|
||||
/** In crash recovery, the current trx to be rolled back */
|
||||
static trx_t* trx_roll_crash_recv_trx = NULL;
|
||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
||||
|
||||
/** In crash recovery we set this to the undo n:o of the current trx to be
|
||||
rolled back. Then we can print how many % the rollback has progressed. */
|
||||
|
|
Loading…
Reference in a new issue