diff options
author | unknown <heikki@hundin.mysql.fi> | 2003-12-13 01:31:59 +0200 |
---|---|---|
committer | unknown <heikki@hundin.mysql.fi> | 2003-12-13 01:31:59 +0200 |
commit | 691bd823b56ce44f0775661f06dc7eeb7320c915 (patch) | |
tree | 9f17ab7f196d035399a17e44f428da4b395e3937 | |
parent | cd3548585ddbbb1d20f8bc1a6d8e2e064747c9fa (diff) | |
download | mariadb-git-691bd823b56ce44f0775661f06dc7eeb7320c915.tar.gz |
btr0cur.c, row0umod.c:
Fix bug: if one updated a secondary index column so that its alphabetical value did not change (e.g., abc -> aBc) and rolled back the update, InnoDB failed to return the value in the secondary index to its original value
row0upd.h:
Correct typing error
sync0sync.ic:
Remove inadvertently pushed sync debug code
innobase/include/sync0sync.ic:
Remove inadvertently pushed sync debug code
innobase/include/row0upd.h:
Correct typing error
innobase/row/row0umod.c:
Fix bug: if one updated a secondary index column so that its alphabetical value did not change (e.g., abc -> aBc) and rolled back the update, InnoDB failed to return the value in the secondary index to its original value
innobase/btr/btr0cur.c:
Fix bug: if one updated a secondary index column so that its alphabetical value did not change (e.g., abc -> aBc) and rolled back the update, InnoDB failed to return the value in the secondary index to its original value
-rw-r--r-- | innobase/btr/btr0cur.c | 3 | ||||
-rw-r--r-- | innobase/include/row0upd.h | 2 | ||||
-rw-r--r-- | innobase/include/sync0sync.ic | 2 | ||||
-rw-r--r-- | innobase/row/row0umod.c | 124 |
4 files changed, 109 insertions, 22 deletions
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index bd09895656c..bfb4d042850 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -1175,7 +1175,8 @@ btr_cur_upd_lock_and_undo( if (!(index->type & DICT_CLUSTERED)) { /* We do undo logging only when we update a clustered index record */ - return(lock_sec_rec_modify_check_and_lock(0, rec, index, thr)); + return(lock_sec_rec_modify_check_and_lock(flags, rec, index, + thr)); } /* Check if we have to wait for a lock: enqueue an explicit lock diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h index dd989982743..f5e0a88231f 100644 --- a/innobase/include/row0upd.h +++ b/innobase/include/row0upd.h @@ -292,7 +292,7 @@ row_upd_index_parse( /* Update vector field */ struct upd_field_struct{ ulint field_no; /* field number in an index, usually - the clustered index, but in upadating + the clustered index, but in updating a secondary index record in btr0cur.c this is the position in the secondary index */ diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic index a9b511a7593..c11cc0d196e 100644 --- a/innobase/include/sync0sync.ic +++ b/innobase/include/sync0sync.ic @@ -257,8 +257,6 @@ mutex_enter_func( mutex->file_name = file_name; mutex->line = line; - mutex->thread_id = os_thread_get_curr_id(); - return; /* Succeeded! */ } diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index b22e494f891..34c3aaf9142 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -377,8 +377,14 @@ row_undo_mod_del_mark_or_remove_sec_low( } /*************************************************************** -Delete marks or removes a secondary index entry if found. */ -UNIV_INLINE +Delete marks or removes a secondary index entry if found. +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. */ +static ulint row_undo_mod_del_mark_or_remove_sec( /*================================*/ @@ -403,20 +409,31 @@ row_undo_mod_del_mark_or_remove_sec( } /*************************************************************** -Delete unmarks a secondary index entry which must be found. */ +Delete unmarks a secondary index entry which must be found. It might not be +delete-marked at the moment, but it does not harm to unmark it anyway. We also +need to update the fields of the secondary index record if we updated its +fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'. */ static -void -row_undo_mod_del_unmark_sec( -/*========================*/ +ulint +row_undo_mod_del_unmark_sec_and_undo_update( +/*========================================*/ + /* out: DB_FAIL or DB_SUCCESS or + DB_OUT_OF_FILE_SPACE */ + ulint mode, /* in: search mode: BTR_MODIFY_LEAF or + BTR_MODIFY_TREE */ undo_node_t* node, /* in: row undo node */ que_thr_t* thr, /* in: query thread */ dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry */ { + mem_heap_t* heap; btr_pcur_t pcur; btr_cur_t* btr_cur; - ulint err; + upd_t* update; + rec_t* rec; + ulint err = DB_SUCCESS; ibool found; + big_rec_t* dummy_big_rec; mtr_t mtr; char err_buf[1000]; @@ -425,8 +442,8 @@ row_undo_mod_del_unmark_sec( log_free_check(); mtr_start(&mtr); - found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur, - &mtr); + found = row_search_index_entry(index, entry, mode, &pcur, &mtr); + if (!found) { fprintf(stderr, "InnoDB: error in sec index entry del undo in\n" @@ -443,17 +460,47 @@ row_undo_mod_del_unmark_sec( "%s\nInnoDB: Make a detailed bug report and send it\n", err_buf); fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); - } else { btr_cur = btr_pcur_get_btr_cur(&pcur); + rec = btr_cur_get_rec(btr_cur); + err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, btr_cur, FALSE, thr, &mtr); - ut_ad(err == DB_SUCCESS); + ut_a(err == DB_SUCCESS); + heap = mem_heap_create(100); + + update = row_upd_build_sec_rec_difference_binary(index, entry, + rec, heap); + if (upd_get_n_fields(update) == 0) { + + /* Do nothing */ + + } else if (mode == BTR_MODIFY_LEAF) { + /* Try an optimistic updating of the record, keeping + changes within the page */ + + err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG + | BTR_NO_LOCKING_FLAG, + btr_cur, update, 0, thr, &mtr); + if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { + err = DB_FAIL; + } + } else { + ut_a(mode == BTR_MODIFY_TREE); + err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG + | BTR_NO_LOCKING_FLAG, + btr_cur, &dummy_big_rec, + update, 0, thr, &mtr); + } + + mem_heap_free(heap); } btr_pcur_close(&pcur); mtr_commit(&mtr); + + return(err); } /*************************************************************** @@ -501,13 +548,14 @@ static ulint row_undo_mod_del_mark_sec( /*======================*/ - /* out: DB_SUCCESS */ + /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ undo_node_t* node, /* in: row undo node */ que_thr_t* thr) /* in: query thread */ { mem_heap_t* heap; dtuple_t* entry; dict_index_t* index; + ulint err; heap = mem_heap_create(1024); @@ -516,7 +564,21 @@ row_undo_mod_del_mark_sec( entry = row_build_index_entry(node->row, index, heap); - row_undo_mod_del_unmark_sec(node, thr, index, entry); + err = row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_LEAF, + node, thr, index, entry); + if (err == DB_FAIL) { + err = row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_TREE, + node, thr, index, entry); + } + + if (err != DB_SUCCESS) { + + mem_heap_free(heap); + + return(err); + } node->index = dict_table_get_next_index(node->index); } @@ -532,7 +594,7 @@ static ulint row_undo_mod_upd_exist_sec( /*=======================*/ - /* out: DB_SUCCESS or error code */ + /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ undo_node_t* node, /* in: row undo node */ que_thr_t* thr) /* in: query thread */ { @@ -558,22 +620,48 @@ row_undo_mod_upd_exist_sec( /* Build the newest version of the index entry */ entry = row_build_index_entry(node->row, index, heap); + /* 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); + index, entry); if (err != DB_SUCCESS) { mem_heap_free(heap); return(err); } - + /* We may have to update the delete mark in the secondary index record of the previous version of - the row */ + the row. We also need to update the fields of + the secondary index record if we updated its fields + but alphabetically they stayed the same, e.g., + 'abc' -> 'aBc'. */ row_upd_index_replace_new_col_vals(entry, index, node->update, NULL); + err = row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_LEAF, + node, thr, index, entry); + if (err == DB_FAIL) { + err = + row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_TREE, + node, thr, index, entry); + } - row_undo_mod_del_unmark_sec(node, thr, index, entry); + if (err != DB_SUCCESS) { + mem_heap_free(heap); + + return(err); + } } node->index = dict_table_get_next_index(node->index); |