diff options
author | Luke Chen <luke.chen@mongodb.com> | 2021-12-30 14:14:27 +1100 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-12-30 03:47:13 +0000 |
commit | cc52f65e6c3ee782857e079e1dbea1fcf2a549ce (patch) | |
tree | d75b3c58eb8dfeaee3a265984030030caea98f16 | |
parent | 426c70b1c4733e411a3dc5fa3bed354b19b94a7d (diff) | |
download | mongo-cc52f65e6c3ee782857e079e1dbea1fcf2a549ce.tar.gz |
Import wiredtiger: 936b411d686b30f2b68d050914689ded27744ee5 from branch mongodb-5.2
ref: 7307e981cd..936b411d68
for: 5.2.0-rc4
WT-8600 Make recovery with no stable timestamp not drop history
3 files changed, 128 insertions, 7 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index f31dbc2d6bd..9cedb2a44e2 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-5.2", - "commit": "7307e981cd95ae93ce14862e73301ce121ceefa4" + "commit": "936b411d686b30f2b68d050914689ded27744ee5" } diff --git a/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c b/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c index f216c956ff3..f35fd4fe2e5 100644 --- a/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c +++ b/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c @@ -1438,9 +1438,15 @@ __rollback_to_stable_hs_final_pass(WT_SESSION_IMPL *session, wt_timestamp_t roll /* * The rollback operation should be performed on the history store file when the checkpoint - * durable start/stop timestamp is greater than the rollback timestamp. + * durable start/stop timestamp is greater than the rollback timestamp. But skip if there is no + * stable timestamp. + * + * Note that the corresponding code in __rollback_to_stable_btree_apply also checks whether + * there _are_ timestamped updates by checking max_durable_ts; that check is redundant here for + * several reasons, the most immediate being that max_durable_ts cannot be none (zero) because + * it's greater than rollback_timestamp, which is itself greater than zero. */ - if (max_durable_ts > rollback_timestamp) { + if (max_durable_ts > rollback_timestamp && rollback_timestamp != WT_TS_NONE) { __wt_verbose_multi(session, WT_VERB_RECOVERY_RTS(session), "tree rolled back with durable timestamp: %s", __wt_timestamp_to_string(max_durable_ts, ts_string[0])); @@ -1494,7 +1500,6 @@ __rollback_to_stable_btree_apply( WT_CONFIG ckptconf; WT_CONFIG_ITEM cval, value, key; WT_DECL_RET; - WT_TXN_GLOBAL *txn_global; wt_timestamp_t max_durable_ts, newest_start_durable_ts, newest_stop_durable_ts; size_t addr_size; uint64_t rollback_txnid, write_gen; @@ -1507,7 +1512,6 @@ __rollback_to_stable_btree_apply( if (!WT_BTREE_PREFIX(uri) || strcmp(uri, WT_HS_URI) == 0 || strcmp(uri, WT_METAFILE_URI) == 0) return (0); - txn_global = &S2C(session)->txn_global; addr_size = 0; rollback_txnid = 0; write_gen = 0; @@ -1574,8 +1578,7 @@ __rollback_to_stable_btree_apply( */ if ((F_ISSET(S2C(session), WT_CONN_RECOVERING) || F_ISSET(S2C(session), WT_CONN_CLOSING_TIMESTAMP)) && - (addr_size == 0 || - (txn_global->stable_timestamp == WT_TS_NONE && max_durable_ts != WT_TS_NONE))) { + (addr_size == 0 || (rollback_timestamp == WT_TS_NONE && max_durable_ts != WT_TS_NONE))) { __wt_verbose_multi(session, WT_VERB_RECOVERY_RTS(session), "skip rollback to stable on file %s because %s", uri, addr_size == 0 ? "its checkpoint address length is 0" : diff --git a/src/third_party/wiredtiger/test/suite/test_rollback_to_stable31.py b/src/third_party/wiredtiger/test/suite/test_rollback_to_stable31.py new file mode 100644 index 00000000000..c4fdef9c4df --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_rollback_to_stable31.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# +# Public Domain 2014-present MongoDB, Inc. +# Public Domain 2008-2014 WiredTiger, Inc. +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +from test_rollback_to_stable01 import test_rollback_to_stable_base +from helper import simulate_crash_restart +from wtdataset import SimpleDataSet +from wtscenario import make_scenarios + +# test_rollback_to_stable31.py +# Check what happens with RTS if you never set the stable timestamp. + +class test_rollback_to_stable31(test_rollback_to_stable_base): + session_config = 'isolation=snapshot' + + format_values = [ + ('column', dict(key_format='r', value_format='S')), + ('column_fix', dict(key_format='r', value_format='8t')), + ('integer_row', dict(key_format='i', value_format='S')), + ] + checkpoint_modes = [ + ('no-checkpoint', dict(checkpoint=False)), + ('checkpoint', dict(checkpoint=True)), + ] + rollback_modes = [ + ('runtime', dict(crash=False)), + ('recovery', dict(crash=True)), + ] + + scenarios = make_scenarios(format_values, checkpoint_modes, rollback_modes) + + def test_rollback_to_stable(self): + nrows = 10 + + # Create a table without logging. + uri = "table:rollback_to_stable31" + ds = SimpleDataSet( + self, uri, 0, key_format=self.key_format, value_format=self.value_format, + config='log=(enabled=false)') + ds.populate() + + if self.value_format == '8t': + value_a = 97 + value_b = 98 + value_c = 99 + else: + value_a = "aaaaa" * 10 + value_b = "bbbbb" * 10 + value_c = "ccccc" * 10 + + # Do not set stable. (Don't set oldest either as it can't be later than stable.) + + # Write aaaaaa to all the keys at time 10. + self.large_updates(uri, value_a, ds, nrows, False, 10) + + # Write bbbbbb to all the keys at time 20. + self.large_updates(uri, value_b, ds, nrows, False, 20) + + # Write cccccc to all the keys at time 30. + self.large_updates(uri, value_c, ds, nrows, False, 30) + + # Optionally checkpoint. + if self.checkpoint: + self.session.checkpoint() + + # Roll back, either via crashing or by explicit RTS. + if self.crash: + simulate_crash_restart(self, ".", "RESTART") + else: + self.conn.rollback_to_stable() + + if self.crash: + if self.checkpoint: + # Recovery-time RTS does nothing when no stable timestamp is set. + self.check(0, uri, 0, nrows, 5) + self.check(value_a, uri, nrows, 0, 15) + self.check(value_b, uri, nrows, 0, 25) + self.check(value_c, uri, nrows, 0, 35) + else: + # If we crashed without a checkpoint, everything should disappear entirely. + self.check(0, uri, 0, 0, 5) + self.check(value_a, uri, 0, 0, 15) + self.check(value_b, uri, 0, 0, 25) + self.check(value_c, uri, 0, 0, 35) + else: + # With an explicit runtime RTS we roll back to 0, but the end of the FLCS table + # still moves forward. + self.check(0, uri, 0, nrows, 5) + self.check(value_a, uri, 0, nrows, 15) + self.check(value_b, uri, 0, nrows, 25) + self.check(value_c, uri, 0, nrows, 35) + +if __name__ == '__main__': + wttest.run() |