summaryrefslogtreecommitdiff
path: root/storage/xtradb/row/row0ins.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/row/row0ins.c')
-rw-r--r--storage/xtradb/row/row0ins.c73
1 files changed, 65 insertions, 8 deletions
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index efcea62f212..0e62185c02e 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -345,9 +345,9 @@ row_ins_clust_index_entry_by_modify(
return(DB_LOCK_TABLE_FULL);
}
- err = btr_cur_pessimistic_update(0, cursor,
- heap, big_rec, update,
- 0, thr, mtr);
+ err = btr_cur_pessimistic_update(
+ BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update,
+ 0, thr, mtr);
}
return(err);
@@ -1512,6 +1512,11 @@ exit_func:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
+ if (trx->fake_changes) {
+ err = DB_SUCCESS;
+ }
+
return(err);
}
@@ -1992,6 +1997,7 @@ row_ins_index_entry_low(
ulint modify = 0; /* remove warning */
rec_t* insert_rec;
rec_t* rec;
+ ulint* offsets;
ulint err;
ulint n_unique;
big_rec_t* big_rec = NULL;
@@ -2013,7 +2019,7 @@ row_ins_index_entry_low(
}
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
- mode | BTR_INSERT | ignore_sec_unique,
+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT | ignore_sec_unique),
&cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
@@ -2073,7 +2079,7 @@ row_ins_index_entry_low(
btr_cur_search_to_nth_level(index, 0, entry,
PAGE_CUR_LE,
- mode | BTR_INSERT,
+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
&cursor, 0,
__FILE__, __LINE__, &mtr);
}
@@ -2097,6 +2103,42 @@ row_ins_index_entry_low(
err = row_ins_clust_index_entry_by_modify(
mode, &cursor, &heap, &big_rec, entry,
thr, &mtr);
+
+ if (big_rec) {
+ ut_a(err == DB_SUCCESS);
+ /* Write out the externally stored
+ columns while still x-latching
+ index->lock and block->lock. We have
+ to mtr_commit(mtr) first, so that the
+ redo log will be written in the
+ correct order. Otherwise, we would run
+ into trouble on crash recovery if mtr
+ freed B-tree pages on which some of
+ the big_rec fields will be written. */
+ btr_cur_mtr_commit_and_start(&cursor, &mtr);
+
+ rec = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(
+ rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+
+ err = btr_store_big_rec_extern_fields(
+ index, btr_cur_get_block(&cursor),
+ rec, offsets, &mtr, FALSE, big_rec);
+ /* If writing big_rec fails (for
+ example, because of DB_OUT_OF_FILE_SPACE),
+ the record will be corrupted. Even if
+ we did not update any externally
+ stored columns, our update could cause
+ the record to grow so that a
+ non-updated column was selected for
+ external storage. This non-update
+ would not have been written to the
+ undo log, and thus the record cannot
+ be rolled back. */
+ ut_a(err == DB_SUCCESS);
+ goto stored_big_rec;
+ }
} else {
ut_ad(!n_ext);
err = row_ins_sec_index_entry_by_modify(
@@ -2125,8 +2167,22 @@ function_exit:
mtr_commit(&mtr);
if (UNIV_LIKELY_NULL(big_rec)) {
- rec_t* rec;
- ulint* offsets;
+
+ if (thr_get_trx(thr)->fake_changes) {
+ /* skip store extern */
+ if (modify) {
+ dtuple_big_rec_free(big_rec);
+ } else {
+ dtuple_convert_back_big_rec(index, entry, big_rec);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
+ return(err);
+ }
+
mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
@@ -2140,6 +2196,7 @@ function_exit:
index, btr_cur_get_block(&cursor),
rec, offsets, &mtr, FALSE, big_rec);
+stored_big_rec:
if (modify) {
dtuple_big_rec_free(big_rec);
} else {