diff options
author | Luke Chen <luke.chen@mongodb.com> | 2022-04-26 15:33:17 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-26 05:56:27 +0000 |
commit | 1b70d1396650b8345b51c3a36f0cc77aa937d4a5 (patch) | |
tree | 7d453399d5be34a721527d7c9acf27924676a4a6 | |
parent | 225f3122c7513a96435747a773ecc9992a791825 (diff) | |
download | mongo-1b70d1396650b8345b51c3a36f0cc77aa937d4a5.tar.gz |
Import wiredtiger: 5003f657b04bde3df73de6f655cbfbbc081cd252 from branch mongodb-6.0
ref: 7a7d6bf9ab..5003f657b0
for: 6.0.0-rc2
WT-9096 Fix search near returning wrong key/value sometimes when key doesn't exist
-rw-r--r-- | src/third_party/wiredtiger/import.data | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_curnext.c | 6 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_curprev.c | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_cursor.c | 24 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_ret.c | 11 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/row_srch.c | 19 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/txn_inline.h | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/checkpoint/workers.c | 10 |
8 files changed, 65 insertions, 15 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index addef77d1ec..31b44d598e7 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -1,6 +1,6 @@ { "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", - "branch": "mongodb-master", - "commit": "7a7d6bf9ab40cd5635ee960fac1b21edf118a007" + "branch": "mongodb-6.0", + "commit": "5003f657b04bde3df73de6f655cbfbbc081cd252" } diff --git a/src/third_party/wiredtiger/src/btree/bt_curnext.c b/src/third_party/wiredtiger/src/btree/bt_curnext.c index 6b49248bf68..234e9d4f38a 100644 --- a/src/third_party/wiredtiger/src/btree/bt_curnext.c +++ b/src/third_party/wiredtiger/src/btree/bt_curnext.c @@ -462,7 +462,12 @@ restart_read_insert: cbt->slot = cbt->row_iteration_slot / 2 - 1; restart_read_page: rip = &page->pg_row[cbt->slot]; + /* + * The saved cursor key from the slot is used later to match the prefix match or get the + * value from the history store if the on-disk data is not visible. + */ WT_RET(__cursor_row_slot_key_return(cbt, rip, &kpack)); + /* * If the cursor has prefix search configured we can early exit here if the key that we are * visiting is after our prefix. @@ -472,6 +477,7 @@ restart_read_page: WT_STAT_CONN_DATA_INCR(session, cursor_search_near_prefix_fast_paths); return (WT_NOTFOUND); } + WT_RET( __wt_txn_read(session, cbt, &cbt->iface.key, WT_RECNO_OOB, WT_ROW_UPDATE(page, rip))); if (cbt->upd_value->type == WT_UPDATE_INVALID) { diff --git a/src/third_party/wiredtiger/src/btree/bt_curprev.c b/src/third_party/wiredtiger/src/btree/bt_curprev.c index 6373874fc65..ce9a49986a7 100644 --- a/src/third_party/wiredtiger/src/btree/bt_curprev.c +++ b/src/third_party/wiredtiger/src/btree/bt_curprev.c @@ -619,6 +619,10 @@ restart_read_insert: cbt->slot = cbt->row_iteration_slot / 2 - 1; restart_read_page: rip = &page->pg_row[cbt->slot]; + /* + * The saved cursor key from the slot is used later to get the value from the history store + * if the on-disk data is not visible. + */ WT_RET(__cursor_row_slot_key_return(cbt, rip, &kpack)); if (F_ISSET(&cbt->iface, WT_CURSTD_KEY_ONLY)) diff --git a/src/third_party/wiredtiger/src/btree/bt_cursor.c b/src/third_party/wiredtiger/src/btree/bt_cursor.c index 6bf2a4e944f..ec82ae02241 100644 --- a/src/third_party/wiredtiger/src/btree/bt_cursor.c +++ b/src/third_party/wiredtiger/src/btree/bt_cursor.c @@ -321,6 +321,16 @@ __wt_cursor_valid(WT_CURSOR_BTREE *cbt, WT_ITEM *key, uint64_t recno, bool *vali /* Paranoia. */ WT_ASSERT(session, recno == WT_RECNO_OOB); + /* + * The key can be NULL only when we didn't find an exact match, copy the search found key + * into the temporary buffer for further use. + */ + if (key == NULL) { + WT_RET(__wt_row_leaf_key( + session, cbt->ref->page, &cbt->ref->page->pg_row[cbt->slot], cbt->tmp, true)); + key = cbt->tmp; + } + /* Check for an update. */ upd = (page->modify != NULL && page->modify->mod_row_update != NULL) ? page->modify->mod_row_update[cbt->slot] : @@ -681,10 +691,14 @@ __wt_btcur_search_near(WT_CURSOR_BTREE *cbt, int *exactp) * better match. This test is simplistic as we're ignoring append lists (there may be no * page slots or we might be legitimately positioned after the last page slot). Ignore those * cases, it makes things too complicated. + * + * If there's an exact match, the row-store search function built the key in the cursor's + * temporary buffer. */ if (leaf_found && (cbt->compare == 0 || (cbt->slot != 0 && cbt->slot != cbt->ref->page->entries - 1))) - WT_ERR(__wt_cursor_valid(cbt, cbt->tmp, WT_RECNO_OOB, &valid)); + WT_ERR( + __wt_cursor_valid(cbt, (cbt->compare == 0 ? cbt->tmp : NULL), WT_RECNO_OOB, &valid)); } if (!valid) { WT_ERR(__wt_cursor_func_init(cbt, true)); @@ -695,7 +709,12 @@ __wt_btcur_search_near(WT_CURSOR_BTREE *cbt, int *exactp) */ if (btree->type == BTREE_ROW) { WT_ERR(__cursor_row_search(cbt, true, NULL, NULL)); - WT_ERR(__wt_cursor_valid(cbt, cbt->tmp, WT_RECNO_OOB, &valid)); + /* + * If there's an exact match, the row-store search function built the key in the + * cursor's temporary buffer. + */ + WT_ERR( + __wt_cursor_valid(cbt, (cbt->compare == 0 ? cbt->tmp : NULL), WT_RECNO_OOB, &valid)); } else { WT_ERR(__cursor_col_search(cbt, NULL, NULL)); WT_ERR(__wt_cursor_valid(cbt, NULL, cbt->recno, &valid)); @@ -1136,7 +1155,6 @@ retry: * checking if the update is visible in __wt_cursor_valid, or we can miss conflicts. */ WT_ERR(__curfile_update_check(cbt)); - WT_WITH_UPDATE_VALUE_SKIP_BUF( ret = __wt_cursor_valid(cbt, cbt->tmp, WT_RECNO_OOB, &valid)); WT_ERR(ret); diff --git a/src/third_party/wiredtiger/src/btree/bt_ret.c b/src/third_party/wiredtiger/src/btree/bt_ret.c index b6a35e6c7bc..f8f7d45cea7 100644 --- a/src/third_party/wiredtiger/src/btree/bt_ret.c +++ b/src/third_party/wiredtiger/src/btree/bt_ret.c @@ -32,12 +32,11 @@ __key_return(WT_CURSOR_BTREE *cbt) } /* - * If not in an insert list and there's an exact match, the row-store search function built - * the key we want to return in the cursor's temporary buffer. Swap the cursor's search-key - * and temporary buffers so we can return it (it's unsafe to return the temporary buffer - * itself because our caller might do another search in this table using the key we return, - * and we'd corrupt the search key during any subsequent search that used the temporary - * buffer). + * If there's an exact match, the row-store search function built the key we want to return + * in the cursor's temporary buffer. Swap the cursor's search-key and temporary buffers so + * we can return it (it's unsafe to return the temporary buffer itself because our caller + * might do another search in this table using the key we return, and we'd corrupt the + * search key during any subsequent search that used the temporary buffer). */ if (cbt->compare == 0) { tmp = cbt->row_key; diff --git a/src/third_party/wiredtiger/src/btree/row_srch.c b/src/third_party/wiredtiger/src/btree/row_srch.c index 310659bb197..abd98bbd506 100644 --- a/src/third_party/wiredtiger/src/btree/row_srch.c +++ b/src/third_party/wiredtiger/src/btree/row_srch.c @@ -61,6 +61,16 @@ __search_insert_append(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_INSERT cbt->compare = -cmp; cbt->ins = ins; cbt->ins_head = ins_head; + + /* + * If we find an exact match, copy the key into the temporary buffer, our callers expect to + * find it there. + */ + if (cbt->compare == 0) { + cbt->tmp->data = WT_INSERT_KEY(cbt->ins); + cbt->tmp->size = WT_INSERT_KEY_SIZE(cbt->ins); + } + *donep = 1; } return (0); @@ -471,7 +481,6 @@ leaf_only: ins_head = WT_ROW_INSERT_SMALLEST(page); } else { cbt->slot = WT_ROW_SLOT(page, page->pg_row + (page->entries - 1)); - ins_head = WT_ROW_INSERT_SLOT(page, cbt->slot); } @@ -586,7 +595,8 @@ leaf_match: /* * Test for an append first when inserting onto an insert list, try to catch cursors repeatedly - * inserting at a single point. + * inserting at a single point, then search the insert list. If we find an exact match, copy the + * key into the temporary buffer, our callers expect to find it there. */ if (insert) { WT_ERR(__search_insert_append(session, cbt, ins_head, srch_key, &done)); @@ -594,7 +604,10 @@ leaf_match: return (0); } WT_ERR(__wt_search_insert(session, cbt, ins_head, srch_key)); - + if (cbt->compare == 0) { + cbt->tmp->data = WT_INSERT_KEY(cbt->ins); + cbt->tmp->size = WT_INSERT_KEY_SIZE(cbt->ins); + } return (0); err: diff --git a/src/third_party/wiredtiger/src/include/txn_inline.h b/src/third_party/wiredtiger/src/include/txn_inline.h index 25e823b661c..4c2ae063e14 100644 --- a/src/third_party/wiredtiger/src/include/txn_inline.h +++ b/src/third_party/wiredtiger/src/include/txn_inline.h @@ -969,7 +969,7 @@ retry: WT_ASSERT(session, cbt->upd_value->type == WT_UPDATE_INVALID); /* If there is no ondisk value, there can't be anything in the history store either. */ - if (cbt->ref->page->dsk == NULL || cbt->slot == UINT32_MAX) { + if (cbt->ref->page->dsk == NULL) { cbt->upd_value->type = WT_UPDATE_TOMBSTONE; return (0); } diff --git a/src/third_party/wiredtiger/test/checkpoint/workers.c b/src/third_party/wiredtiger/test/checkpoint/workers.c index 15110bb54de..5ffa8046f52 100644 --- a/src/third_party/wiredtiger/test/checkpoint/workers.c +++ b/src/third_party/wiredtiger/test/checkpoint/workers.c @@ -214,6 +214,16 @@ worker_op(WT_CURSOR *cursor, table_type type, uint64_t keyno, u_int new_val) return (WT_ROLLBACK); return (log_print_err("cursor.search_near", ret, 1)); } + + /* Retry the result of search_near again to confirm the result. */ + if (new_val % 2 == 0) { + if ((ret = cursor->search(cursor)) != 0) { + if (ret == WT_ROLLBACK) + return (WT_ROLLBACK); + return (log_print_err("cursor.search", ret, 1)); + } + } + if (cmp < 0) { /* Advance to the next key that exists. */ if ((ret = cursor->next(cursor)) != 0) { |