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,33 +657,63 @@ row_undo_mod_upd_exist_sec( ...@@ -657,33 +657,63 @@ row_undo_mod_upd_exist_sec(
/* Build the newest version of the index entry */ /* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, node->ext, entry = row_build_index_entry(node->row, node->ext,
index, heap); index, heap);
ut_a(entry); 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 /* NOTE that if we updated the fields of a
delete-marked secondary index record so that delete-marked secondary index record so that
alphabetically they stayed the same, e.g., alphabetically they stayed the same, e.g.,
'abc' -> 'aBc', we cannot return to the original 'abc' -> 'aBc', we cannot return to the
values because we do not know them. But this should original values because we do not know them.
not cause problems because in row0sel.c, in queries But this should not cause problems because
we always retrieve the clustered index record or an in row0sel.c, in queries we always retrieve
earlier version of it, if the secondary index record the clustered index record or an earlier
through which we do the search is delete-marked. */ version of it, if the secondary index record
through which we do the search is
err = row_undo_mod_del_mark_or_remove_sec(node, thr, delete-marked. */
index,
entry); err = row_undo_mod_del_mark_or_remove_sec(
node, thr, index, entry);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
mem_heap_free(heap); mem_heap_free(heap);
return(err); return(err);
} }
mem_heap_empty(heap);
}
/* We may have to update the delete mark in the /* We may have to update the delete mark in the
secondary index record of the previous version of secondary index record of the previous version of
the row. We also need to update the fields of the row. We also need to update the fields of
the secondary index record if we updated its fields the secondary index record if we updated its fields
but alphabetically they stayed the same, e.g., but alphabetically they stayed the same, e.g.,
'abc' -> 'aBc'. */ 'abc' -> 'aBc'. */
mem_heap_empty(heap);
entry = row_build_index_entry(node->undo_row, entry = row_build_index_entry(node->undo_row,
node->undo_ext, node->undo_ext,
index, heap); 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