diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2010-06-01 13:37:38 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@oracle.com> | 2010-06-01 13:37:38 +0300 |
commit | 2caade505362cb2ab66514c64ac9424af775cbf3 (patch) | |
tree | 7c2e6e4e824ab74f648cfb0e29761e186a8a6aea /storage | |
parent | da0b6d611fcbe15e18fd888e9bf3578855caca09 (diff) | |
download | mariadb-git-2caade505362cb2ab66514c64ac9424af775cbf3.tar.gz |
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.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innodb_plugin/row/row0umod.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c index e7245dbee41..c497c469aae 100644 --- a/storage/innodb_plugin/row/row0umod.c +++ b/storage/innodb_plugin/row/row0umod.c @@ -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); |