summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2022-02-17 12:43:29 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2022-02-17 12:43:29 +0100
commiteb25f47423d64bc038e67bf7895bc6663ee4f1c3 (patch)
treeada8e2b039df322e3cf89216324f177f09824a9b
parent8251a9fb93075a72074bd7fd10faee5165014b7f (diff)
parent38a8ac19510b08ecea0b33cba887775b47a58267 (diff)
downloadmariadb-git-eb25f47423d64bc038e67bf7895bc6663ee4f1c3.tar.gz
Merge branch '10.7' into 10.8
# Conflicts: # storage/innobase/btr/btr0pcur.cc # storage/innobase/log/log0log.cc
-rw-r--r--mysql-test/suite/innodb/r/cursor-restore-locking.result35
-rw-r--r--mysql-test/suite/innodb/t/cursor-restore-locking.test79
-rw-r--r--storage/innobase/btr/btr0cur.cc8
-rw-r--r--storage/innobase/btr/btr0defragment.cc2
-rw-r--r--storage/innobase/btr/btr0pcur.cc189
-rw-r--r--storage/innobase/dict/dict0load.cc4
-rw-r--r--storage/innobase/fts/fts0fts.cc11
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc3
-rw-r--r--storage/innobase/include/btr0pcur.h54
-rw-r--r--storage/innobase/log/log0log.cc10
-rw-r--r--storage/innobase/log/log0sync.cc27
-rw-r--r--storage/innobase/row/row0import.cc7
-rw-r--r--storage/innobase/row/row0ins.cc4
-rw-r--r--storage/innobase/row/row0merge.cc9
-rw-r--r--storage/innobase/row/row0mysql.cc6
-rw-r--r--storage/innobase/row/row0purge.cc4
-rw-r--r--storage/innobase/row/row0sel.cc68
-rw-r--r--storage/innobase/row/row0uins.cc28
-rw-r--r--storage/innobase/row/row0umod.cc29
-rw-r--r--storage/innobase/row/row0upd.cc5
-rw-r--r--win/packaging/extra.wxs.in10
22 files changed, 366 insertions, 228 deletions
diff --git a/mysql-test/suite/innodb/r/cursor-restore-locking.result b/mysql-test/suite/innodb/r/cursor-restore-locking.result
new file mode 100644
index 00000000000..bc1127f57b3
--- /dev/null
+++ b/mysql-test/suite/innodb/r/cursor-restore-locking.result
@@ -0,0 +1,35 @@
+CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
+connect prevent_purge,localhost,root,,;
+start transaction with consistent snapshot;
+connect con_del_1,localhost,root,,;
+INSERT INTO t VALUES (20,20);
+SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
+DELETE FROM t WHERE b = 20;
+connect con_ins_1,localhost,root,,;
+SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
+SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL first_ins_locked';
+SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
+INSERT INTO t VALUES(10, 20);
+connect con_del_2,localhost,root,,;
+SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
+SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL second_del_locked';
+DELETE FROM t WHERE b = 20;
+connection default;
+SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
+SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
+SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
+connection con_del_1;
+connection default;
+disconnect prevent_purge;
+InnoDB 0 transactions not purged
+SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
+connection con_del_2;
+connection con_ins_1;
+connection default;
+INSERT INTO t VALUES(30, 20);
+disconnect con_ins_1;
+disconnect con_del_1;
+disconnect con_del_2;
+connection default;
+SET DEBUG_SYNC = 'RESET';
+DROP TABLE t;
diff --git a/mysql-test/suite/innodb/t/cursor-restore-locking.test b/mysql-test/suite/innodb/t/cursor-restore-locking.test
new file mode 100644
index 00000000000..d032d8a8def
--- /dev/null
+++ b/mysql-test/suite/innodb/t/cursor-restore-locking.test
@@ -0,0 +1,79 @@
+--source include/have_innodb.inc
+--source include/count_sessions.inc
+source include/have_debug.inc;
+source include/have_debug_sync.inc;
+
+CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
+
+--connect(prevent_purge,localhost,root,,)
+start transaction with consistent snapshot;
+
+--connect(con_del_1,localhost,root,,)
+INSERT INTO t VALUES (20,20);
+SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
+--send DELETE FROM t WHERE b = 20
+
+--connect(con_ins_1,localhost,root,,)
+SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
+# It's supposed the following INSERT will be suspended just after
+# lock_wait_suspend_thread_enter syncpoint, and will be awaken
+# after the previous DELETE commits. ib_after_row_insert will be executed
+# after the INSERT is woken up. The previous DELETE will wait for
+# first_del_cont signal before commit, and this signal will be sent later.
+# So it's safe to use two signals in a row here, it's guaranted the first
+# signal will be received before the second signal is sent.
+SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL first_ins_locked';
+SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
+--send INSERT INTO t VALUES(10, 20)
+
+--connect(con_del_2,localhost,root,,)
+SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
+SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL second_del_locked';
+###############################################################################
+# This DELETE is locked by the previous DELETE, after that DELETE is
+# committed, it will still be locked by the next INSERT on delete-marked
+# heap_no 2 record. After that INSERT inserted the record with heap_no 3,
+# and after heap_no 2 record is purged, this DELETE will be unlocked and
+# must restore persistent cursor position at heap_no 3 record, as it has the
+# same secondary key value as former heap_no 2 record. Then it must be blocked
+# by the previous INSERT, and after the INSERT is committed, it must
+# delete the record, inserted by the previous INSERT, and the last INSERT(see
+# below) must be finished without error. But instead this DELETE restores
+# persistent cursor position to supremum, as a result, it does not delete the
+# record, inserted by the previous INSERT, and the last INSERT is finished with
+# duplicate key check error.
+###############################################################################
+--send DELETE FROM t WHERE b = 20
+
+--connection default
+SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
+SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
+SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
+--connection con_del_1
+--reap
+
+--connection default
+--disconnect prevent_purge
+--source include/wait_all_purged.inc
+SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
+
+--connection con_del_2
+--reap
+
+--connection con_ins_1
+--reap
+
+--connection default
+###############################################################################
+# Duplicate key error is expected if the bug is not fixed.
+###############################################################################
+INSERT INTO t VALUES(30, 20);
+
+--disconnect con_ins_1
+--disconnect con_del_1
+--disconnect con_del_2
+--connection default
+
+SET DEBUG_SYNC = 'RESET';
+DROP TABLE t;
+--source include/wait_until_count_sessions.inc
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 5f6562e5394..5185b90b137 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -6834,11 +6834,9 @@ struct btr_blob_log_check_t {
m_pcur->btr_cur.page_cur.block->page.unfix();
} else {
ut_ad(m_pcur->rel_pos == BTR_PCUR_ON);
- bool ret = btr_pcur_restore_position(
- BTR_MODIFY_LEAF | BTR_MODIFY_EXTERNAL,
- m_pcur, m_mtr);
-
- ut_a(ret);
+ ut_a(m_pcur->restore_position(
+ BTR_MODIFY_LEAF | BTR_MODIFY_EXTERNAL,
+ m_mtr) == btr_pcur_t::SAME_ALL);
}
*m_block = btr_pcur_get_block(m_pcur);
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index f8b5d42bb57..8823bab572d 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -672,7 +672,7 @@ processed:
mtr_x_lock_index(index, &mtr);
/* This will acquire index->lock SX-latch, which per WL#6363 is allowed
when we are already holding the X-latch. */
- btr_pcur_restore_position(BTR_MODIFY_TREE, item->pcur, &mtr);
+ item->pcur->restore_position(BTR_MODIFY_TREE, &mtr);
buf_block_t* first_block = btr_pcur_get_block(item->pcur);
if (buf_block_t *last_block =
btr_defragment_n_pages(first_block, index,
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index 9c32236db9c..c2c5440d0fd 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -259,26 +259,29 @@ struct optimistic_latch_leaves
}
};
-/**************************************************************//**
-Restores the stored position of a persistent cursor bufferfixing the page and
-obtaining the specified latches. If the cursor position was saved when the
-(1) cursor was positioned on a user record: this function restores the position
-to the last record LESS OR EQUAL to the stored record;
-(2) cursor was positioned on a page infimum record: restores the position to
-the last record LESS than the user record which was the successor of the page
-infimum;
-(3) cursor was positioned on the page supremum: restores to the first record
-GREATER than the user record which was the predecessor of the supremum.
-(4) cursor was positioned before the first or after the last in an empty tree:
-restores to before first or after the last in the tree.
-@return TRUE if the cursor position was stored when it was on a user
-record and it can be restored on a user record whose ordering fields
-are identical to the ones of the original user record */
-ibool
-btr_pcur_restore_position(
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
- btr_pcur_t* cursor, /*!< in: detached persistent cursor */
- mtr_t* mtr) /*!< in: mtr */
+/** Restores the stored position of a persistent cursor bufferfixing
+the page and obtaining the specified latches. If the cursor position
+was saved when the
+(1) cursor was positioned on a user record: this function restores the
+position to the last record LESS OR EQUAL to the stored record;
+(2) cursor was positioned on a page infimum record: restores the
+position to the last record LESS than the user record which was the
+successor of the page infimum;
+(3) cursor was positioned on the page supremum: restores to the first
+record GREATER than the user record which was the predecessor of the
+supremum.
+(4) cursor was positioned before the first or after the last in an
+empty tree: restores to before first or after the last in the tree.
+@param restore_latch_mode BTR_SEARCH_LEAF, ...
+@param mtr mtr
+@return btr_pcur_t::SAME_ALL cursor position on user rec and points on
+the record with the same field values as in the stored record,
+btr_pcur_t::SAME_UNIQ cursor position is on user rec and points on the
+record with the same unique field values as in the stored record,
+btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
+the record with not the samebuniq field values as in the stored */
+btr_pcur_t::restore_status
+btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
{
dict_index_t* index;
dtuple_t* tuple;
@@ -288,97 +291,97 @@ btr_pcur_restore_position(
ut_ad(mtr->is_active());
//ut_ad(cursor->old_stored);
- ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
- || cursor->pos_state == BTR_PCUR_IS_POSITIONED);
+ ut_ad(pos_state == BTR_PCUR_WAS_POSITIONED
+ || pos_state == BTR_PCUR_IS_POSITIONED);
- index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
+ index = btr_cur_get_index(&btr_cur);
if (UNIV_UNLIKELY
- (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
- || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
+ (rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
+ || rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
dberr_t err = DB_SUCCESS;
/* In these cases we do not try an optimistic restoration,
but always do a search */
err = btr_cur_open_at_index_side(
- cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
- index, latch_mode,
- btr_pcur_get_btr_cur(cursor), 0, mtr);
+ rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
+ index, restore_latch_mode,
+ &btr_cur, 0, mtr);
if (err != DB_SUCCESS) {
ib::warn() << " Error code: " << err
- << " btr_pcur_restore_position "
+ << " btr_pcur_t::restore_position "
<< " table: " << index->table->name
<< " index: " << index->name;
}
- cursor->latch_mode =
- BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
- cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- cursor->block_when_stored.clear();
+ latch_mode =
+ BTR_LATCH_MODE_WITHOUT_INTENTION(restore_latch_mode);
+ pos_state = BTR_PCUR_IS_POSITIONED;
+ block_when_stored.clear();
- return(FALSE);
+ return restore_status::NOT_SAME;
}
- ut_a(cursor->old_rec);
- ut_a(cursor->old_n_core_fields);
- ut_a(cursor->old_n_core_fields <= index->n_core_fields);
- ut_a(cursor->old_n_fields);
+ ut_a(old_rec);
+ ut_a(old_n_core_fields);
+ ut_a(old_n_core_fields <= index->n_core_fields);
+ ut_a(old_n_fields);
- switch (latch_mode) {
+ switch (restore_latch_mode) {
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV:
/* Try optimistic restoration. */
- if (cursor->block_when_stored.run_with_hint(
- optimistic_latch_leaves(cursor, &latch_mode,
+ if (block_when_stored.run_with_hint(
+ optimistic_latch_leaves(this, &restore_latch_mode,
mtr))) {
- cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- cursor->latch_mode = latch_mode;
+ pos_state = BTR_PCUR_IS_POSITIONED;
+ latch_mode = restore_latch_mode;
- if (cursor->rel_pos == BTR_PCUR_ON) {
+ if (rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
const rec_t* rec;
rec_offs offsets1_[REC_OFFS_NORMAL_SIZE];
rec_offs offsets2_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets1 = offsets1_;
rec_offs* offsets2 = offsets2_;
- rec = btr_pcur_get_rec(cursor);
+ rec = btr_pcur_get_rec(this);
rec_offs_init(offsets1_);
rec_offs_init(offsets2_);
heap = mem_heap_create(256);
- ut_ad(cursor->old_n_core_fields
+ ut_ad(old_n_core_fields
== index->n_core_fields);
offsets1 = rec_get_offsets(
- cursor->old_rec, index, offsets1,
- cursor->old_n_core_fields,
- cursor->old_n_fields, &heap);
+ old_rec, index, offsets1,
+ old_n_core_fields,
+ old_n_fields, &heap);
offsets2 = rec_get_offsets(
rec, index, offsets2,
index->n_core_fields,
- cursor->old_n_fields, &heap);
+ old_n_fields, &heap);
- ut_ad(!cmp_rec_rec(cursor->old_rec,
+ ut_ad(!cmp_rec_rec(old_rec,
rec, offsets1, offsets2,
index));
mem_heap_free(heap);
#endif /* UNIV_DEBUG */
- return(TRUE);
+ return restore_status::SAME_ALL;
}
/* This is the same record as stored,
may need to be adjusted for BTR_PCUR_BEFORE/AFTER,
depending on search mode and direction. */
- if (btr_pcur_is_on_user_rec(cursor)) {
- cursor->pos_state
+ if (btr_pcur_is_on_user_rec(this)) {
+ pos_state
= BTR_PCUR_IS_POSITIONED_OPTIMISTIC;
}
- return(FALSE);
+ return restore_status::NOT_SAME;
}
}
@@ -386,19 +389,19 @@ btr_pcur_restore_position(
heap = mem_heap_create(256);
- tuple = dtuple_create(heap, cursor->old_n_fields);
+ tuple = dtuple_create(heap, old_n_fields);
- dict_index_copy_types(tuple, index, cursor->old_n_fields);
+ dict_index_copy_types(tuple, index, old_n_fields);
- rec_copy_prefix_to_dtuple(tuple, cursor->old_rec, index,
- cursor->old_n_core_fields,
- cursor->old_n_fields, heap);
+ rec_copy_prefix_to_dtuple(tuple, old_rec, index,
+ old_n_core_fields,
+ old_n_fields, heap);
ut_ad(dtuple_check_typed(tuple));
/* Save the old search mode of the cursor */
- old_mode = cursor->search_mode;
+ old_mode = search_mode;
- switch (cursor->rel_pos) {
+ switch (rel_pos) {
case BTR_PCUR_ON:
mode = PAGE_CUR_LE;
break;
@@ -413,41 +416,45 @@ btr_pcur_restore_position(
mode = PAGE_CUR_UNSUPP;
}
- btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
- cursor,
+ btr_pcur_open_with_no_init_func(index, tuple, mode, restore_latch_mode,
+ this,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
mtr);
/* Restore the old search mode */
- cursor->search_mode = old_mode;
+ search_mode = old_mode;
- ut_ad(cursor->rel_pos == BTR_PCUR_ON
- || cursor->rel_pos == BTR_PCUR_BEFORE
- || cursor->rel_pos == BTR_PCUR_AFTER);
+ ut_ad(rel_pos == BTR_PCUR_ON
+ || rel_pos == BTR_PCUR_BEFORE
+ || rel_pos == BTR_PCUR_AFTER);
rec_offs offsets[REC_OFFS_NORMAL_SIZE];
rec_offs_init(offsets);
- if (cursor->rel_pos == BTR_PCUR_ON
- && btr_pcur_is_on_user_rec(cursor)
- && !cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), index,
- rec_get_offsets(btr_pcur_get_rec(cursor),
- index, offsets,
- index->n_core_fields,
- ULINT_UNDEFINED, &heap))) {
-
- /* We have to store the NEW value for the modify clock,
- since the cursor can now be on a different page!
- But we can retain the value of old_rec */
-
- cursor->block_when_stored.store(btr_pcur_get_block(cursor));
- cursor->modify_clock = buf_block_get_modify_clock(
- cursor->block_when_stored.block());
- cursor->old_stored = true;
-
- mem_heap_free(heap);
-
- return(TRUE);
+ restore_status ret_val= restore_status::NOT_SAME;
+ if (rel_pos == BTR_PCUR_ON && btr_pcur_is_on_user_rec(this)) {
+ ulint n_matched_fields= 0;
+ if (!cmp_dtuple_rec_with_match(
+ tuple, btr_pcur_get_rec(this), index,
+ rec_get_offsets(btr_pcur_get_rec(this), index, offsets,
+ index->n_core_fields, ULINT_UNDEFINED, &heap),
+ &n_matched_fields)) {
+
+ /* We have to store the NEW value for the modify clock,
+ since the cursor can now be on a different page!
+ But we can retain the value of old_rec */
+
+ block_when_stored.store(btr_pcur_get_block(this));
+ modify_clock= buf_block_get_modify_clock(
+ block_when_stored.block());
+ old_stored= true;
+
+ mem_heap_free(heap);
+
+ return restore_status::SAME_ALL;
+ }
+ if (n_matched_fields >= index->n_uniq)
+ ret_val= restore_status::SAME_UNIQ;
}
mem_heap_free(heap);
@@ -456,9 +463,9 @@ btr_pcur_restore_position(
to the cursor because it can now be on a different page, the record
under it may have been removed, etc. */
- btr_pcur_store_position(cursor, mtr);
+ btr_pcur_store_position(this, mtr);
- return(FALSE);
+ return ret_val;
}
/*********************************************************//**
@@ -567,7 +574,7 @@ btr_pcur_move_backward_from_page(
mtr_start(mtr);
- btr_pcur_restore_position(latch_mode2, cursor, mtr);
+ cursor->restore_position(latch_mode2, mtr);
page = btr_pcur_get_page(cursor);
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 0b73e8452a6..bcc63a5e38a 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -227,7 +227,7 @@ dict_getnext_system(
const rec_t* rec;
/* Restore the position */
- btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ pcur->restore_position(BTR_SEARCH_LEAF, mtr);
/* Get the next record */
rec = dict_getnext_system_low(pcur, mtr);
@@ -3024,7 +3024,7 @@ loop:
mtr_start(&mtr);
- btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
+ pcur.restore_position(BTR_SEARCH_LEAF, &mtr);
next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index ee7f18f7ba5..cc4e3299436 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -3448,7 +3448,6 @@ fts_add_doc_by_id(
get_doc, clust_index, doc_pcur, offsets, &doc);
if (doc.found) {
- ibool success MY_ATTRIBUTE((unused));
btr_pcur_store_position(doc_pcur, &mtr);
mtr_commit(&mtr);
@@ -3507,12 +3506,10 @@ fts_add_doc_by_id(
mtr_start(&mtr);
if (i < num_idx - 1) {
-
- success = btr_pcur_restore_position(
- BTR_SEARCH_LEAF, doc_pcur,
- &mtr);
-
- ut_ad(success);
+ ut_d(auto status=)
+ doc_pcur->restore_position(
+ BTR_SEARCH_LEAF, &mtr);
+ ut_ad(status == btr_pcur_t::SAME_ALL);
}
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 4953c65b5fc..6a9814fc081 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -2047,7 +2047,7 @@ fail:
os_file_close(d);
mtr.start();
- btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
+ pcur.restore_position(BTR_SEARCH_LEAF, &mtr);
}
btr_pcur_close(&pcur);
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 413d0ccef90..07d18815c8a 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -4008,7 +4008,8 @@ ibuf_restore_pos(
ut_ad(mode == BTR_MODIFY_LEAF
|| BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE);
- if (UNIV_LIKELY(btr_pcur_restore_position(mode, pcur, mtr))) {
+ if (UNIV_LIKELY(pcur->restore_position(mode, mtr) ==
+ btr_pcur_t::SAME_ALL)) {
return true;
}
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index 56e482d55cc..f6636816e72 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -238,26 +238,6 @@ btr_pcur_store_position(
/*====================*/
btr_pcur_t* cursor, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in: mtr */
-/**************************************************************//**
-Restores the stored position of a persistent cursor bufferfixing the page and
-obtaining the specified latches. If the cursor position was saved when the
-(1) cursor was positioned on a user record: this function restores the position
-to the last record LESS OR EQUAL to the stored record;
-(2) cursor was positioned on a page infimum record: restores the position to
-the last record LESS than the user record which was the successor of the page
-infimum;
-(3) cursor was positioned on the page supremum: restores to the first record
-GREATER than the user record which was the predecessor of the supremum.
-(4) cursor was positioned before the first or after the last in an empty tree:
-restores to before first or after the last in the tree.
-@return TRUE if the cursor position was stored when it was on a user
-record and it can be restored on a user record whose ordering fields
-are identical to the ones of the original user record */
-ibool
-btr_pcur_restore_position(
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
- btr_pcur_t* cursor, /*!< in: detached persistent cursor */
- mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Gets the rel_pos field for a cursor whose position has been stored.
@return BTR_PCUR_ON, ... */
@@ -419,6 +399,18 @@ enum pcur_pos_t {
selects, updates, and deletes. */
struct btr_pcur_t{
+ /** Return value of restore_position() */
+ enum restore_status {
+ /** cursor position on user rec and points on the record with
+ the same field values as in the stored record */
+ SAME_ALL,
+ /** cursor position is on user rec and points on the record with
+ the same unique field values as in the stored record */
+ SAME_UNIQ,
+ /** cursor position is not on user rec or points on the record
+ with not the same uniq field values as in the stored record */
+ NOT_SAME
+ };
/** a B-tree cursor */
btr_cur_t btr_cur;
/** see TODO note below!
@@ -476,6 +468,28 @@ struct btr_pcur_t{
/** Return the index of this persistent cursor */
dict_index_t* index() const { return(btr_cur.index); }
+ /** Restores the stored position of a persistent cursor bufferfixing
+ the page and obtaining the specified latches. If the cursor position
+ was saved when the
+ (1) cursor was positioned on a user record: this function restores the
+ position to the last record LESS OR EQUAL to the stored record;
+ (2) cursor was positioned on a page infimum record: restores the
+ position to the last record LESS than the user record which was the
+ successor of the page infimum;
+ (3) cursor was positioned on the page supremum: restores to the first
+ record GREATER than the user record which was the predecessor of the
+ supremum.
+ (4) cursor was positioned before the first or after the last in an
+ empty tree: restores to before first or after the last in the tree.
+ @param restore_latch_mode BTR_SEARCH_LEAF, ...
+ @param mtr mtr
+ @return btr_pcur_t::SAME_ALL cursor position on user rec and points on
+ the record with the same field values as in the stored record,
+ btr_pcur_t::SAME_UNIQ cursor position is on user rec and points on the
+ record with the same unique field values as in the stored record,
+ btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
+ the record with not the samebuniq field values as in the stored */
+ restore_status restore_position(ulint latch_mode, mtr_t *mtr);
};
inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index b7254ef2baa..29bf9bd17bc 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -652,9 +652,13 @@ void log_write_up_to(lsn_t lsn, bool durable,
#endif
repeat:
- if (durable &&
- flush_lock.acquire(lsn, callback) != group_commit_lock::ACQUIRED)
- return;
+ if (durable)
+ {
+ if (flush_lock.acquire(lsn, callback) != group_commit_lock::ACQUIRED)
+ return;
+ flush_lock.set_pending(log_sys.get_lsn());
+ }
+
lsn_t pending_write_lsn= 0, pending_flush_lsn= 0;
diff --git a/storage/innobase/log/log0sync.cc b/storage/innobase/log/log0sync.cc
index 65cc1d0633c..6b14d1d3591 100644
--- a/storage/innobase/log/log0sync.cc
+++ b/storage/innobase/log/log0sync.cc
@@ -222,7 +222,7 @@ group_commit_lock::lock_return_code group_commit_lock::acquire(value_type num, c
thread_local_waiter.m_value = num;
thread_local_waiter.m_group_commit_leader= false;
std::unique_lock<std::mutex> lk(m_mtx, std::defer_lock);
- while (num > value())
+ while (num > value() || thread_local_waiter.m_group_commit_leader)
{
lk.lock();
@@ -232,11 +232,9 @@ group_commit_lock::lock_return_code group_commit_lock::acquire(value_type num, c
{
lk.unlock();
do_completion_callback(callback);
- thread_local_waiter.m_group_commit_leader=false;
return lock_return_code::EXPIRED;
}
- thread_local_waiter.m_group_commit_leader= false;
if (!m_lock)
{
/* Take the lock, become group commit leader.*/
@@ -249,17 +247,23 @@ group_commit_lock::lock_return_code group_commit_lock::acquire(value_type num, c
return lock_return_code::ACQUIRED;
}
- if (callback && m_waiters_list)
+ if (callback && (m_waiters_list || num <= pending()))
{
/*
- We need to have at least one waiter,
- so it can become the new group commit leader.
+ If num > pending(), we have a good candidate for the next group
+ commit lead, that will be taking over the lock after current owner
+ releases it. We put current thread into waiter's list so it sleeps
+ and can be signaled and marked as group commit lead during lock release.
+
+ For this to work well, pending() must deliver a good approximation for N
+ in the next call to group_commit_lock::release(N).
*/
m_pending_callbacks.push_back({num, *callback});
return lock_return_code::CALLBACK_QUEUED;
}
/* Add yourself to waiters list.*/
+ thread_local_waiter.m_group_commit_leader= false;
thread_local_waiter.m_next = m_waiters_list;
m_waiters_list = &thread_local_waiter;
lk.unlock();
@@ -369,6 +373,17 @@ group_commit_lock::value_type group_commit_lock::release(value_type num)
lk.unlock();
+ /*
+ Release designated next group commit lead first,
+ to minimize spurious wakeups.
+ */
+ if (wakeup_list && wakeup_list->m_group_commit_leader)
+ {
+ next = wakeup_list->m_next;
+ wakeup_list->m_sema.wake();
+ wakeup_list= next;
+ }
+
for (size_t i = 0; i < callback_count; i++)
callbacks[i].m_callback(callbacks[i].m_param);
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 868f44e2bef..6cf099e204e 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -1563,7 +1563,7 @@ IndexPurge::next() UNIV_NOTHROW
mtr_set_log_mode(&m_mtr, MTR_LOG_NO_REDO);
- btr_pcur_restore_position(BTR_MODIFY_LEAF, &m_pcur, &m_mtr);
+ m_pcur.restore_position(BTR_MODIFY_LEAF, &m_mtr);
/* The following is based on btr_pcur_move_to_next_user_rec(). */
m_pcur.old_stored = false;
ut_ad(m_pcur.latch_mode == BTR_MODIFY_LEAF);
@@ -1639,8 +1639,7 @@ IndexPurge::purge_pessimistic_delete() UNIV_NOTHROW
{
dberr_t err;
- btr_pcur_restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
- &m_pcur, &m_mtr);
+ m_pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &m_mtr);
ut_ad(rec_get_deleted_flag(
btr_pcur_get_rec(&m_pcur),
@@ -1668,7 +1667,7 @@ IndexPurge::purge() UNIV_NOTHROW
mtr_set_log_mode(&m_mtr, MTR_LOG_NO_REDO);
- btr_pcur_restore_position(BTR_MODIFY_LEAF, &m_pcur, &m_mtr);
+ m_pcur.restore_position(BTR_MODIFY_LEAF, &m_mtr);
}
/** Adjust the BLOB reference for a single column that is externally stored
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index cf108753180..a72af516f08 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1350,7 +1350,7 @@ row_ins_foreign_check_on_constraint(
/* Restore pcur position */
- btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ pcur->restore_position(BTR_SEARCH_LEAF, mtr);
if (tmp_heap) {
mem_heap_free(tmp_heap);
@@ -1369,7 +1369,7 @@ nonstandard_exit_func:
mtr_commit(mtr);
mtr_start(mtr);
- btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ pcur->restore_position(BTR_SEARCH_LEAF, mtr);
DBUG_RETURN(err);
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index d4ffe9f2b30..da8f62177cb 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -2175,8 +2175,8 @@ scan_next:
/* Restore position on the record, or its
predecessor if the record was purged
meanwhile. */
- btr_pcur_restore_position(
- BTR_SEARCH_LEAF, &pcur, &mtr);
+ pcur.restore_position(
+ BTR_SEARCH_LEAF, &mtr);
/* Move to the successor of the
original record. */
if (!btr_pcur_move_to_next_user_rec(
@@ -2719,9 +2719,8 @@ write_buffers:
overflow). */
mtr.start();
mtr_started = true;
- btr_pcur_restore_position(
- BTR_SEARCH_LEAF, &pcur,
- &mtr);
+ pcur.restore_position(
+ BTR_SEARCH_LEAF, &mtr);
buf = row_merge_buf_empty(buf);
merge_buf[i] = buf;
/* Restart the outer loop on the
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 7594877d80e..480f38926c1 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1818,7 +1818,7 @@ row_unlock_for_mysql(
/* Restore the cursor position and find the record */
if (!has_latches_on_recs) {
- btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr);
+ pcur->restore_position(BTR_SEARCH_LEAF, &mtr);
}
rec = btr_pcur_get_rec(pcur);
@@ -1829,8 +1829,8 @@ row_unlock_for_mysql(
in the clustered index. */
if (!has_latches_on_recs) {
- btr_pcur_restore_position(BTR_SEARCH_LEAF,
- clust_pcur, &mtr);
+ clust_pcur->restore_position(BTR_SEARCH_LEAF,
+ &mtr);
}
rec = btr_pcur_get_rec(clust_pcur);
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 937a8481b47..f0043ab5c85 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -75,7 +75,9 @@ row_purge_reposition_pcur(
if (node->found_clust) {
ut_ad(node->validate_pcur());
- node->found_clust = btr_pcur_restore_position(mode, &node->pcur, mtr);
+ node->found_clust =
+ node->pcur.restore_position(mode, mtr) ==
+ btr_pcur_t::SAME_ALL;
} else {
node->found_clust = row_search_on_row_ref(
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index c3d3411c3c3..a599c387e60 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -1438,8 +1438,9 @@ row_sel_restore_pcur_pos(
relative_position = btr_pcur_get_rel_pos(&(plan->pcur));
- equal_position = btr_pcur_restore_position(BTR_SEARCH_LEAF,
- &(plan->pcur), mtr);
+ equal_position =
+ plan->pcur.restore_position(BTR_SEARCH_LEAF, mtr) ==
+ btr_pcur_t::SAME_ALL;
/* If the cursor is traveling upwards, and relative_position is
@@ -3592,36 +3593,28 @@ err_exit:
return(err);
}
-/********************************************************************//**
-Restores cursor position after it has been stored. We have to take into
+/** Restores cursor position after it has been stored. We have to take into
account that the record cursor was positioned on may have been deleted.
Then we may have to move the cursor one step up or down.
+@param[out] same_user_rec true if we were able to restore the cursor on a user
+record with the same ordering prefix in in the B-tree index
+@param[in] latch_mode latch mode wished in restoration
+@param[in] pcur cursor whose position has been stored
+@param[in] moves_up true if the cursor moves up in the index
+@param[in] mtr mtr; CAUTION: may commit mtr temporarily!
+@param[in] select_lock_type select lock type
@return true if we may need to process the record the cursor is now
positioned on (i.e. we should not go to the next record yet) */
-static
-bool
-sel_restore_position_for_mysql(
-/*===========================*/
- ibool* same_user_rec, /*!< out: TRUE if we were able to restore
- the cursor on a user record with the
- same ordering prefix in in the
- B-tree index */
- ulint latch_mode, /*!< in: latch mode wished in
- restoration */
- btr_pcur_t* pcur, /*!< in: cursor whose position
- has been stored */
- ibool moves_up, /*!< in: TRUE if the cursor moves up
- in the index */
- mtr_t* mtr) /*!< in: mtr; CAUTION: may commit
- mtr temporarily! */
+static bool sel_restore_position_for_mysql(bool *same_user_rec,
+ ulint latch_mode, btr_pcur_t *pcur,
+ bool moves_up, mtr_t *mtr,
+ lock_mode select_lock_type)
{
- ibool success;
-
- success = btr_pcur_restore_position(latch_mode, pcur, mtr);
+ auto status = pcur->restore_position(latch_mode, mtr);
- *same_user_rec = success;
+ *same_user_rec = status == btr_pcur_t::SAME_ALL;
- ut_ad(!success || pcur->rel_pos == BTR_PCUR_ON);
+ ut_ad(!*same_user_rec || pcur->rel_pos == BTR_PCUR_ON);
#ifdef UNIV_DEBUG
if (pcur->pos_state == BTR_PCUR_IS_POSITIONED_OPTIMISTIC) {
ut_ad(pcur->rel_pos == BTR_PCUR_BEFORE
@@ -3637,7 +3630,10 @@ sel_restore_position_for_mysql(
switch (pcur->rel_pos) {
case BTR_PCUR_ON:
- if (!success && moves_up) {
+ if (!*same_user_rec && moves_up) {
+ if (status == btr_pcur_t::SAME_UNIQ
+ && select_lock_type != LOCK_NONE)
+ return true;
next:
if (btr_pcur_move_to_next(pcur, mtr)
&& rec_is_metadata(btr_pcur_get_rec(pcur),
@@ -3647,7 +3643,7 @@ next:
return true;
}
- return(!success);
+ return(!*same_user_rec);
case BTR_PCUR_AFTER_LAST_IN_TREE:
case BTR_PCUR_BEFORE_FIRST_IN_TREE:
return true;
@@ -4330,12 +4326,12 @@ row_search_mvcc(
Row_sel_get_clust_rec_for_mysql row_sel_get_clust_rec_for_mysql;
ibool unique_search = FALSE;
ibool mtr_has_extra_clust_latch = FALSE;
- ibool moves_up = FALSE;
+ bool moves_up = false;
/* if the returned record was locked and we did a semi-consistent
read (fetch the newest committed version), then this is set to
TRUE */
ulint next_offs;
- ibool same_user_rec;
+ bool same_user_rec;
ibool table_lock_waited = FALSE;
byte* next_buf = 0;
bool spatial_search = false;
@@ -4648,10 +4644,10 @@ aborted:
if (UNIV_UNLIKELY(direction == 0)) {
if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G
|| mode >= PAGE_CUR_CONTAIN) {
- moves_up = TRUE;
+ moves_up = true;
}
} else if (direction == ROW_SEL_NEXT) {
- moves_up = TRUE;
+ moves_up = true;
}
thr = que_fork_get_first_thr(prebuilt->sel_graph);
@@ -4701,7 +4697,7 @@ wait_table_again:
bool need_to_process = sel_restore_position_for_mysql(
&same_user_rec, BTR_SEARCH_LEAF,
- pcur, moves_up, &mtr);
+ pcur, moves_up, &mtr, prebuilt->select_lock_type);
if (UNIV_UNLIKELY(need_to_process)) {
if (UNIV_UNLIKELY(prebuilt->row_read_type
@@ -4952,7 +4948,7 @@ rec_loop:
if (UNIV_UNLIKELY(next_offs >= srv_page_size - PAGE_DIR)) {
wrong_offs:
- if (srv_force_recovery == 0 || moves_up == FALSE) {
+ if (srv_force_recovery == 0 || moves_up == false) {
ib::error() << "Rec address "
<< static_cast<const void*>(rec)
<< ", buf block fix count "
@@ -5764,7 +5760,9 @@ next_rec:
if (sel_restore_position_for_mysql(&same_user_rec,
BTR_SEARCH_LEAF,
- pcur, moves_up, &mtr)) {
+ pcur, moves_up, &mtr,
+ prebuilt->select_lock_type)
+ ) {
goto rec_loop;
}
}
@@ -5848,7 +5846,7 @@ lock_table_wait:
if (!dict_index_is_spatial(index)) {
sel_restore_position_for_mysql(
&same_user_rec, BTR_SEARCH_LEAF, pcur,
- moves_up, &mtr);
+ moves_up, &mtr, prebuilt->select_lock_type);
}
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index c826d632969..173ae9a98f9 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -66,7 +66,6 @@ row_undo_ins_remove_clust_rec(
/*==========================*/
undo_node_t* node) /*!< in: undo node */
{
- ibool success;
dberr_t err;
ulint n_tries = 0;
mtr_t mtr;
@@ -112,14 +111,12 @@ restart:
We must log the removal, so that the row will be correctly
purged. However, we can log the removal out of sync with the
B-tree modification. */
-
- success = btr_pcur_restore_position(
- online
- ? BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED
- : (node->rec_type == TRX_UNDO_INSERT_METADATA)
- ? BTR_MODIFY_TREE : BTR_MODIFY_LEAF, &node->pcur, &mtr);
- ut_a(success);
-
+ ut_a(node->pcur.restore_position(
+ online ? BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED
+ : (node->rec_type == TRX_UNDO_INSERT_METADATA)
+ ? BTR_MODIFY_TREE
+ : BTR_MODIFY_LEAF,
+ &mtr) == btr_pcur_t::SAME_ALL);
rec_t* rec = btr_pcur_get_rec(&node->pcur);
ut_ad(rec_get_trx_id(rec, index) == node->trx->id
@@ -214,9 +211,8 @@ restart:
}
mtr.start();
- success = btr_pcur_restore_position(
- BTR_MODIFY_LEAF, &node->pcur, &mtr);
- ut_a(success);
+ ut_a(node->pcur.restore_position(
+ BTR_MODIFY_LEAF, &mtr) == btr_pcur_t::SAME_ALL);
}
}
@@ -234,11 +230,9 @@ retry:
} else {
index->set_modified(mtr);
}
-
- success = btr_pcur_restore_position(
- BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
- &node->pcur, &mtr);
- ut_a(success);
+ ut_a(
+ node->pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+ &mtr) == btr_pcur_t::SAME_ALL);
btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true,
&mtr);
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index c16676f5f84..494a23eaf0a 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -95,19 +95,14 @@ row_undo_mod_clust_low(
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
dberr_t err;
-#ifdef UNIV_DEBUG
- ibool success;
-#endif /* UNIV_DEBUG */
pcur = &node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
-#ifdef UNIV_DEBUG
- success =
-#endif /* UNIV_DEBUG */
- btr_pcur_restore_position(mode, pcur, mtr);
+ ut_d(auto pcur_restore_result =)
+ pcur->restore_position(mode, mtr);
- ut_ad(success);
+ ut_ad(pcur_restore_result == btr_pcur_t::SAME_ALL);
ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur),
btr_cur_get_index(btr_cur))
== thr_get_trx(thr)->id
@@ -381,7 +376,8 @@ row_undo_mod_clust(
ut_ad(node->new_trx_id);
mtr.start();
- if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, &mtr)) {
+ if (pcur->restore_position(BTR_MODIFY_LEAF, &mtr) !=
+ btr_pcur_t::SAME_ALL) {
goto mtr_commit_exit;
}
@@ -412,9 +408,9 @@ row_undo_mod_clust(
}
mtr.start();
- if (!btr_pcur_restore_position(
- BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
- pcur, &mtr)) {
+ if (pcur->restore_position(
+ BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &mtr) !=
+ btr_pcur_t::SAME_ALL) {
goto mtr_commit_exit;
}
@@ -447,7 +443,8 @@ row_undo_mod_clust(
longer accessible by any active read view. */
mtr.start();
- if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, &mtr)) {
+ if (pcur->restore_position(BTR_MODIFY_LEAF, &mtr)
+ != btr_pcur_t::SAME_ALL) {
goto mtr_commit_exit;
}
rec_t* rec = btr_pcur_get_rec(pcur);
@@ -554,7 +551,6 @@ row_undo_mod_del_mark_or_remove_sec_low(
{
btr_pcur_t pcur;
btr_cur_t* btr_cur;
- ibool success;
dberr_t err = DB_SUCCESS;
mtr_t mtr;
mtr_t mtr_vers;
@@ -626,9 +622,8 @@ row_undo_mod_del_mark_or_remove_sec_low(
mtr_vers.start();
- success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur),
- &mtr_vers);
- ut_a(success);
+ ut_a(node->pcur.restore_position(BTR_SEARCH_LEAF, &mtr_vers) ==
+ btr_pcur_t::SAME_ALL);
/* For temporary table, we can skip to check older version of
clustered index entry, because there is no MVCC or purge. */
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index bf6a2b1be61..4d364c19540 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -2553,7 +2553,8 @@ row_upd_clust_rec(
the same transaction do not modify the record in the meantime.
Therefore we can assert that the restoration of the cursor succeeds. */
- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
+ ut_a(pcur->restore_position(BTR_MODIFY_TREE, mtr) ==
+ btr_pcur_t::SAME_ALL);
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(index->table)));
@@ -2756,7 +2757,7 @@ row_upd_clust_step(
mode = BTR_MODIFY_LEAF;
}
- if (!btr_pcur_restore_position(mode, pcur, &mtr)) {
+ if (pcur->restore_position(mode, &mtr) != btr_pcur_t::SAME_ALL) {
err = DB_RECORD_NOT_FOUND;
goto exit_func;
}
diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in
index 44e45951d4a..056a7ec43ab 100644
--- a/win/packaging/extra.wxs.in
+++ b/win/packaging/extra.wxs.in
@@ -652,15 +652,15 @@
<CustomAction Id='ErrorDataDir'
Error='Invalid data directory, choose a different one. Error : [DATADIRERROR]'/>
- <CustomAction Id="ErrorInstallDir"
- Error="[INSTALLDIRERROR]" />
+ <CustomAction Id="ErrorInstallDir"
+ Error="[INSTALLDIRERROR]" />
<InstallExecuteSequence>
<Custom Action="CheckDataDirectory" After="CostFinalize">
<![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]>
</Custom>
- <Custom Action="ErrorDataDir" After="CheckDataDirectory">DATADIRERROR</Custom>
- <Custom Action="CheckInstallDirectory" After="CostFinalize">
- NOT Installed
+ <Custom Action="ErrorDataDir" After="CheckDataDirectory">DATADIRERROR</Custom>
+ <Custom Action="CheckInstallDirectory" After="CostFinalize">
+ NOT Installed AND OLDERVERSIONBEINGUPGRADED=""
</Custom>
<Custom Action="ErrorInstallDir" After="CheckInstallDirectory">INSTALLDIRERROR</Custom>
<Custom Action="CheckDatabaseProperties" Before="CreateDatabaseCommand">SERVICENAME</Custom>