Commit 2caade50 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#53812: assert row/row0umod.c line 660 in txn rollback after crash recovery

row_undo_mod_upd_exist_sec(): Tolerate a failure to build the index entry
for a DYNAMIC or COMPRESSED table during crash recovery.
parent da0b6d61
......@@ -657,24 +657,55 @@ row_undo_mod_upd_exist_sec(
/* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, node->ext,
index, heap);
ut_a(entry);
/* NOTE that if we updated the fields of a
delete-marked secondary index record so that
alphabetically they stayed the same, e.g.,
'abc' -> 'aBc', we cannot return to the original
values because we do not know them. But this should
not cause problems because in row0sel.c, in queries
we always retrieve the clustered index record or an
earlier version of it, if the secondary index record
through which we do the search is delete-marked. */
err = row_undo_mod_del_mark_or_remove_sec(node, thr,
index,
entry);
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
if (UNIV_UNLIKELY(!entry)) {
/* The server must have crashed in
row_upd_clust_rec_by_insert(), in
row_ins_index_entry_low() before
btr_store_big_rec_extern_fields()
has written the externally stored columns
(BLOBs) of the new clustered index entry. */
/* The table must be in DYNAMIC or COMPRESSED
format. REDUNDANT and COMPACT formats
store a local 768-byte prefix of each
externally stored column. */
ut_a(dict_table_get_format(index->table)
>= DICT_TF_FORMAT_ZIP);
/* This is only legitimate when
rolling back an incomplete transaction
after crash recovery. */
ut_a(thr_get_trx(thr)->is_recovered);
/* The server must have crashed before
completing the insert of the new
clustered index entry and before
inserting to the secondary indexes.
Because node->row was not yet written
to this index, we can ignore it. But
we must restore node->undo_row. */
} else {
/* NOTE that if we updated the fields of a
delete-marked secondary index record so that
alphabetically they stayed the same, e.g.,
'abc' -> 'aBc', we cannot return to the
original values because we do not know them.
But this should not cause problems because
in row0sel.c, in queries we always retrieve
the clustered index record or an earlier
version of it, if the secondary index record
through which we do the search is
delete-marked. */
err = row_undo_mod_del_mark_or_remove_sec(
node, thr, index, entry);
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
mem_heap_empty(heap);
}
/* We may have to update the delete mark in the
......@@ -683,7 +714,6 @@ row_undo_mod_upd_exist_sec(
the secondary index record if we updated its fields
but alphabetically they stayed the same, e.g.,
'abc' -> 'aBc'. */
mem_heap_empty(heap);
entry = row_build_index_entry(node->undo_row,
node->undo_ext,
index, heap);
......
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