Import wiredtiger: 0164fd130bf034bb3414db97ce6f1258ecc53103 from branch mongodb-8.2 (#42541)

Co-authored-by: wt-vendoring-bot <wt-vendoring-bot@mongodb.com>
GitOrigin-RevId: d9fead707d6235197072320acdc3916d9ba837b1
This commit is contained in:
wt-vendoring-bot[bot] 2025-10-13 13:26:44 +11:00 committed by MongoDB Bot
parent 40180020c2
commit 3facd5a845
24 changed files with 1185 additions and 494 deletions

View File

@ -622,6 +622,18 @@ connection_runtime_config = [
Use legacy page visit strategy for eviction. Using this option is highly discouraged
as it will re-introduce the bug described in WT-9121.''',
type='boolean'),
Config('prefer_scrub_eviction', 'false',
r'''Change the eviction strategy to scrub eviction when the cache usage is under
half way between the target limit to the trigger limit.''',
type='boolean'),
Config('cache_tolerance_for_app_eviction', '0', r'''
This setting establishes a tolerance level for the configured
\c eviction_dirty_trigger and \c eviction_update_trigger.
The value is a percentage between 0 and 100, with 0 treating
\c eviction_dirty_trigger and \c eviction_update_trigger as hard limit.
The configured percentage will be taken in increments of 10 only,
by applying the floor to the given percentage value. ''',
min='0', max='100'),
]),
Config('eviction_checkpoint_target', '1', r'''
perform eviction at the beginning of checkpoints to bring the dirty content in cache

View File

@ -2,5 +2,5 @@
"vendor": "wiredtiger",
"github": "wiredtiger/wiredtiger",
"branch": "mongodb-8.2",
"commit": "a300655f291261468d87ed8461494be5c78ddcdb"
"commit": "0164fd130bf034bb3414db97ce6f1258ecc53103"
}

View File

@ -650,18 +650,7 @@ __wt_btcur_search_prepared(WT_CURSOR *cursor, WT_UPDATE **updp)
F_CLR(&cbt->iface, WT_CURSTD_KEY_ONLY);
/*
* The following assertion relies on the fact that for every prepared update there must be an
* associated key. However this is only true if we pin the page to prevent eviction. By calling
* into the standard search function we avoid releasing our hazard pointer between update chain
* resolutions. It also depends on sorting the transaction modifications by key, if we didn't do
* that we would unpin the page between searches and later come back to the same key. We rely on
* resolving all updates for a single key in sequence.
*
* This is a complex scenario, suppose we have two updates to the same key by our transaction,
* and are resolving the prepared updates. The first pass resolves the update chain, now if we
* let eviction run it could evict the page and it will treat the update chain as a regular non
* prepared update chain. If we were rolling back the transaction the key may not exist after
* eviction, similarly if we wrote a globally visible tombstone. Thus our second attempt at
* resolution would fail as it wouldn't find a key.
* associated key and we only resolve the same key once.
*/
WT_ASSERT_ALWAYS(
CUR2S(cursor), ret == 0, "A valid key must exist when resolving prepared updates.");

File diff suppressed because it is too large Load Diff

View File

@ -190,12 +190,14 @@ __evict_validate_config(WT_SESSION_IMPL *session, const char *cfg[])
int
__wt_evict_config(WT_SESSION_IMPL *session, const char *cfg[], bool reconfig)
{
WT_CACHE *cache;
WT_CONFIG_ITEM cval;
WT_CONNECTION_IMPL *conn;
WT_EVICT *evict;
uint32_t evict_threads_max, evict_threads_min;
conn = S2C(session);
cache = conn->cache;
evict = conn->evict;
WT_ASSERT(session, evict != NULL);
@ -238,6 +240,24 @@ __wt_evict_config(WT_SESSION_IMPL *session, const char *cfg[], bool reconfig)
WT_RET(__wt_config_gets(session, cfg, "cache_stuck_timeout_ms", &cval));
evict->cache_stuck_timeout_ms = (uint64_t)cval.val;
WT_RET(__wt_config_gets(session, cfg, "eviction.prefer_scrub_eviction", &cval));
if (cval.val != 0)
F_SET_ATOMIC_16(&(cache->cache_eviction_controls), WT_CACHE_PREFER_SCRUB_EVICTION);
/*
* The cache tolerance is a percentage value with range 0 - 100, inclusive.
* Given input percentage is considered in multiples of 10 only, by applying floor().
* 00 < value < 10 -> 00
* 10 < value < 20 -> 10
* 20 < value < 30 -> 20
* ...
* 90 < value < 100 -> 90
* value is 100 -> 100
*/
WT_RET(__wt_config_gets(session, cfg, "eviction.cache_tolerance_for_app_eviction", &cval));
__wt_atomic_store8(&cache->cache_eviction_controls.cache_tolerance_for_app_eviction,
(((uint8_t)cval.val / 10) * 10));
/*
* Resize the thread group if reconfiguring, otherwise the thread group will be initialized as
* part of creating the connection workers.

View File

@ -610,6 +610,113 @@ __evict_check_user_ok_with_eviction(WT_SESSION_IMPL *session, bool interruptible
return (true);
}
/* !!!
* __evict_is_session_cache_trigger_tolerant --
* Check if the session is cache tolerant for the configured trigger values. If tolerant,
* session will not perform eviction.
*
* Cache tolerance is cache's ability to let application threads perform workload operations above
* trigger levels. Cache tolerance is applicable only for dirty_trigger and updates_trigger.
* Cache tolerance is expressed in % with respect to the trigger level. If cache tolerance is
* configured as 20%, and dirty trigger is 20%, then application threads will be incrementally
* involve in eviction as dirty content increases from 20% - 24%.
*
* All the application threads will perform eviction only when the dirty content reaches 24% of
* cache.
*
* Based on the % of cache usage above trigger level with respect to tolerance level,
* incrementally involve the app threads for eviction.
*
* Usage between 00% - 20% --> No application threads involve in eviction.
* Usage between 20% - 40% --> 20% of application threads involve in eviction.
* Usage between 40% - 60% --> 40% of application threads involve in eviction.
* Usage between 60% - 80% --> 60% of application threads involve in eviction.
* Usage between 80% - 100% --> 80% of application threads involve in eviction.
* Usage >= 100%, above tolerance level --> involve all application threads.
*/
static WT_INLINE bool
__evict_is_session_cache_trigger_tolerant(WT_SESSION_IMPL *session, uint8_t cache_tolerance)
{
double dirty_trigger = S2C(session)->evict->eviction_dirty_trigger;
uint64_t bytes_dirty_trigger = 0, bytes_max = 0;
uint64_t bytes_dirty = 0, bytes_dirty_tolerance = 0, bytes_over_dirty_trigger = 0;
bytes_max = S2C(session)->cache_size + 1;
bytes_dirty = __wt_cache_dirty_leaf_inuse(S2C(session)->cache);
bytes_dirty_trigger = (uint64_t)(dirty_trigger * bytes_max) / 100;
/*
* bytes_dirty_tolerance = number of bytes over the dirty trigger based on configured
* cache_tolerance
*/
bytes_dirty_tolerance = (uint64_t)(bytes_dirty_trigger * cache_tolerance) / 100;
if (bytes_dirty > bytes_dirty_trigger) {
/* Dirty content is more than dirty trigger. */
bytes_over_dirty_trigger = bytes_dirty - bytes_dirty_trigger;
if (bytes_over_dirty_trigger > bytes_dirty_tolerance) {
/* More than 100% of tolerance level. 100% of the app threads are non-tolerant. */
return (false);
} else if (bytes_over_dirty_trigger * 5 > bytes_dirty_tolerance * 4) {
/* 80% - 100% of tolerance level. 80% of app threads are non-tolerant. */
if ((session->id % 5) > 0)
return (false);
} else if (bytes_over_dirty_trigger * 5 > bytes_dirty_tolerance * 3) {
/* 60% - 80% of tolerance level. 60% of app threads are non-tolerant. */
if ((session->id % 5) > 1)
return (false);
} else if (bytes_over_dirty_trigger * 5 > bytes_dirty_tolerance * 2) {
/* 40% - 60% of tolerance level. 40% of app threads are non-tolerant. */
if ((session->id % 5) > 2)
return (false);
} else if (bytes_over_dirty_trigger * 5 > bytes_dirty_tolerance * 1) {
/* 20% - 40% of tolerance level. 20% of app threads are non-tolerant. */
if ((session->id % 5) > 3)
return (false);
}
}
double updates_trigger = S2C(session)->evict->eviction_updates_trigger;
uint64_t bytes_updates_trigger = 0;
uint64_t bytes_updates = 0, bytes_updates_tolerance = 0, bytes_over_updates_trigger = 0;
bytes_updates = __wt_cache_bytes_updates(S2C(session)->cache);
bytes_updates_trigger = (uint64_t)(updates_trigger * bytes_max) / 100;
/*
* bytes_updates_tolerance = number of bytes over the update trigger based on configured
* cache_tolerance
*/
bytes_updates_tolerance = (uint64_t)(bytes_updates_trigger * cache_tolerance) / 100;
if (bytes_updates > bytes_updates_trigger) {
/* Updates content is more than update trigger. */
bytes_over_updates_trigger = bytes_dirty - bytes_dirty_trigger;
if (bytes_over_updates_trigger > bytes_updates_tolerance) {
/* More than 100% of tolerance level. 100% of the app threads are non-tolerant. */
return (false);
} else if (bytes_over_updates_trigger * 5 > bytes_updates_tolerance * 4) {
/* 80% - 100% of tolerance level. 80% of app threads are non-tolerant. */
if ((session->id % 5) > 0)
return (false);
} else if (bytes_over_updates_trigger * 5 > bytes_updates_tolerance * 3) {
/* 60% - 80% of tolerance level. 60% of app threads are non-tolerant. */
if ((session->id % 5) > 1)
return (false);
} else if (bytes_over_updates_trigger * 5 > bytes_updates_tolerance * 2) {
/* 40% - 60% of tolerance level. 40% of app threads are non-tolerant. */
if ((session->id % 5) > 2)
return (false);
} else if (bytes_over_updates_trigger * 5 > bytes_updates_tolerance * 1) {
/* 20% - 40% of tolerance level. 20% of app threads are non-tolerant. */
if ((session->id % 5) > 3)
return (false);
}
}
/* session is tolerant for both the dirty trigger and update trigger. */
return (true);
}
/* !!!
* __wt_evict_app_assist_worker_check --
* Check if eviction trigger thresholds have reached to determine whether application threads
@ -719,6 +826,19 @@ __wt_evict_app_assist_worker_check(
if (!__evict_check_user_ok_with_eviction(session, interruptible))
return (0);
/*
* If the cache tolerance is configured, check if the session can be tolerant. if tolerant,
* don't involve in eviction.
*/
WT_EVICT *evict = conn->evict;
if (pct_full <= evict->eviction_trigger) {
uint8_t cache_tolerance =
__wt_atomic_load8(&conn->cache->cache_eviction_controls.cache_tolerance_for_app_eviction);
if ((cache_tolerance != 0) &&
(__evict_is_session_cache_trigger_tolerant(session, cache_tolerance)))
return (0);
}
/*
* Some callers (those waiting for slow operations), will sleep if there was no cache work to
* do. After this point, let them skip the sleep.

View File

@ -761,11 +761,18 @@ __evict_update_work(WT_SESSION_IMPL *session)
/*
* Scrub dirty pages and keep them in cache if we are less than half way to the clean, dirty or
* updates triggers.
*
* WT_CACHE_PREFER_SCRUB_EVICTION that can be turned on to enable scrub eviction
* as long as overall cache usage is under half way to the trigger limit.
*/
if (bytes_inuse < (uint64_t)((target + trigger) * bytes_max) / 200) {
if (bytes_dirty < (uint64_t)((dirty_target + dirty_trigger) * bytes_max) / 200 &&
bytes_updates < (uint64_t)((updates_target + updates_trigger) * bytes_max) / 200)
if (F_ISSET_ATOMIC_16(
&(conn->cache->cache_eviction_controls), WT_CACHE_PREFER_SCRUB_EVICTION)) {
LF_SET(WT_EVICT_CACHE_SCRUB);
} else if (bytes_dirty < (uint64_t)((dirty_target + dirty_trigger) * bytes_max) / 200 &&
bytes_updates < (uint64_t)((updates_target + updates_trigger) * bytes_max) / 200) {
LF_SET(WT_EVICT_CACHE_SCRUB);
}
} else
LF_SET(WT_EVICT_CACHE_NOKEEP);

View File

@ -2256,15 +2256,16 @@ __wt_btcur_skip_page(
/*
* Otherwise, check the timestamp information. We base this decision on the aggregate stop
* point added to the page during the last reconciliation.
* point added to the page during the last reconciliation. Never skip a page with prepared
* transaction data.
*/
if (WT_TIME_AGGREGATE_HAS_STOP(&addr.ta) &&
if (WT_TIME_AGGREGATE_HAS_STOP(&addr.ta) && !addr.ta.prepare &&
__wt_txn_snap_min_visible(session, addr.ta.newest_stop_txn, addr.ta.newest_stop_ts,
addr.ta.newest_stop_durable_ts)) {
*skipp = true;
walk_skip_stats->total_del_pages_skipped++;
}
} else if (clean_page && __wt_get_page_modify_ta(session, ref->page, &ta) &&
} else if (clean_page && __wt_get_page_modify_ta(session, ref->page, &ta) && !ta->prepare &&
__wt_txn_snap_min_visible(
session, ta->newest_stop_txn, ta->newest_stop_ts, ta->newest_stop_durable_ts)) {
/*

View File

@ -18,6 +18,19 @@ typedef enum __wt_cache_op {
#define WT_HS_FILE_MIN (100 * WT_MEGABYTE)
/*
* WT_CACHE_EVICTION_CONTROLS --
* Cache eviction controls configuration.
* WT_CACHE_PREFER_SCRUB_EVICTION: Change the eviction strategy to scrub eviction when the
* cache usage is under half way between the target limit to the trigger limit.
*/
struct __wt_cache_eviction_controls {
wt_shared uint8_t cache_tolerance_for_app_eviction; /* cache tolerance for app eviction.*/
/* cache eviction controls bit positions */
#define WT_CACHE_PREFER_SCRUB_EVICTION 0x1u
wt_shared uint16_t flags_atomic;
};
/*
* WiredTiger cache structure.
*/
@ -41,6 +54,7 @@ struct __wt_cache {
wt_shared uint64_t bytes_updates; /* Bytes of updates to pages */
wt_shared uint64_t bytes_written;
WT_CACHE_EVICTION_CONTROLS cache_eviction_controls; /* various cache eviction controls */
/*
* History store cache usage. TODO: The values for these variables are cached and potentially
* outdated.

View File

@ -142,7 +142,7 @@ WT_CONF_API_DECLARE(WT_CONNECTION, debug_info, 1, 7);
WT_CONF_API_DECLARE(WT_CONNECTION, load_extension, 1, 4);
WT_CONF_API_DECLARE(WT_CONNECTION, open_session, 3, 9);
WT_CONF_API_DECLARE(WT_CONNECTION, query_timestamp, 1, 1);
WT_CONF_API_DECLARE(WT_CONNECTION, reconfigure, 19, 107);
WT_CONF_API_DECLARE(WT_CONNECTION, reconfigure, 19, 109);
WT_CONF_API_DECLARE(WT_CONNECTION, rollback_to_stable, 1, 2);
WT_CONF_API_DECLARE(WT_CONNECTION, set_timestamp, 1, 4);
WT_CONF_API_DECLARE(WT_CURSOR, bound, 1, 3);
@ -171,10 +171,10 @@ WT_CONF_API_DECLARE(object, meta, 6, 67);
WT_CONF_API_DECLARE(table, meta, 2, 13);
WT_CONF_API_DECLARE(tier, meta, 6, 68);
WT_CONF_API_DECLARE(tiered, meta, 6, 70);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open, 24, 177);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open_all, 24, 178);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open_basecfg, 24, 172);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open_usercfg, 24, 171);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open, 24, 179);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open_all, 24, 180);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open_basecfg, 24, 174);
WT_CONF_API_DECLARE(GLOBAL, wiredtiger_open_usercfg, 24, 173);
#define WT_CONF_API_ELEMENTS 53

View File

@ -26,36 +26,36 @@
#define WT_CONF_ID_Disaggregated 202ULL
#define WT_CONF_ID_Encryption 19ULL
#define WT_CONF_ID_Eviction 204ULL
#define WT_CONF_ID_File_manager 218ULL
#define WT_CONF_ID_File_manager 220ULL
#define WT_CONF_ID_Flush_tier 148ULL
#define WT_CONF_ID_Hash 282ULL
#define WT_CONF_ID_Heuristic_controls 223ULL
#define WT_CONF_ID_History_store 227ULL
#define WT_CONF_ID_Hash 284ULL
#define WT_CONF_ID_Heuristic_controls 225ULL
#define WT_CONF_ID_History_store 229ULL
#define WT_CONF_ID_Import 87ULL
#define WT_CONF_ID_Incremental 106ULL
#define WT_CONF_ID_Io_capacity 229ULL
#define WT_CONF_ID_Io_capacity 231ULL
#define WT_CONF_ID_Live_restore 60ULL
#define WT_CONF_ID_Log 36ULL
#define WT_CONF_ID_Operation_tracking 239ULL
#define WT_CONF_ID_Prefetch 261ULL
#define WT_CONF_ID_Rollback_to_stable 241ULL
#define WT_CONF_ID_Operation_tracking 241ULL
#define WT_CONF_ID_Prefetch 263ULL
#define WT_CONF_ID_Rollback_to_stable 243ULL
#define WT_CONF_ID_Roundup_timestamps 140ULL
#define WT_CONF_ID_Shared_cache 243ULL
#define WT_CONF_ID_Statistics_log 247ULL
#define WT_CONF_ID_Shared_cache 245ULL
#define WT_CONF_ID_Statistics_log 249ULL
#define WT_CONF_ID_Tiered_storage 47ULL
#define WT_CONF_ID_Transaction_sync 302ULL
#define WT_CONF_ID_Transaction_sync 304ULL
#define WT_CONF_ID_access_pattern_hint 12ULL
#define WT_CONF_ID_action 76ULL
#define WT_CONF_ID_allocation_size 13ULL
#define WT_CONF_ID_app_metadata 0ULL
#define WT_CONF_ID_append 73ULL
#define WT_CONF_ID_archive 233ULL
#define WT_CONF_ID_archive 235ULL
#define WT_CONF_ID_auth_token 48ULL
#define WT_CONF_ID_available 294ULL
#define WT_CONF_ID_available 296ULL
#define WT_CONF_ID_background 80ULL
#define WT_CONF_ID_background_compact 185ULL
#define WT_CONF_ID_backup 152ULL
#define WT_CONF_ID_backup_restore_target 263ULL
#define WT_CONF_ID_backup_restore_target 265ULL
#define WT_CONF_ID_bitmap 61ULL
#define WT_CONF_ID_blkcache_eviction_aggression 162ULL
#define WT_CONF_ID_block_allocation 14ULL
@ -63,12 +63,12 @@
#define WT_CONF_ID_bound 77ULL
#define WT_CONF_ID_bucket 49ULL
#define WT_CONF_ID_bucket_prefix 50ULL
#define WT_CONF_ID_buckets 283ULL
#define WT_CONF_ID_buffer_alignment 264ULL
#define WT_CONF_ID_builtin_extension_config 265ULL
#define WT_CONF_ID_buckets 285ULL
#define WT_CONF_ID_buffer_alignment 266ULL
#define WT_CONF_ID_builtin_extension_config 267ULL
#define WT_CONF_ID_bulk 99ULL
#define WT_CONF_ID_cache 153ULL
#define WT_CONF_ID_cache_cursors 257ULL
#define WT_CONF_ID_cache_cursors 259ULL
#define WT_CONF_ID_cache_directory 51ULL
#define WT_CONF_ID_cache_max_wait_ms 170ULL
#define WT_CONF_ID_cache_on_checkpoint 160ULL
@ -77,48 +77,49 @@
#define WT_CONF_ID_cache_resident 16ULL
#define WT_CONF_ID_cache_size 172ULL
#define WT_CONF_ID_cache_stuck_timeout_ms 173ULL
#define WT_CONF_ID_capacity 267ULL
#define WT_CONF_ID_cache_tolerance_for_app_eviction 211ULL
#define WT_CONF_ID_capacity 269ULL
#define WT_CONF_ID_checkpoint 56ULL
#define WT_CONF_ID_checkpoint_backup_info 57ULL
#define WT_CONF_ID_checkpoint_cleanup 145ULL
#define WT_CONF_ID_checkpoint_cleanup_obsolete_tw_pages_dirty_max 224ULL
#define WT_CONF_ID_checkpoint_cleanup_obsolete_tw_pages_dirty_max 226ULL
#define WT_CONF_ID_checkpoint_crash_point 146ULL
#define WT_CONF_ID_checkpoint_fail_before_turtle_update 258ULL
#define WT_CONF_ID_checkpoint_fail_before_turtle_update 260ULL
#define WT_CONF_ID_checkpoint_lsn 58ULL
#define WT_CONF_ID_checkpoint_read_timestamp 102ULL
#define WT_CONF_ID_checkpoint_retention 187ULL
#define WT_CONF_ID_checkpoint_sync 266ULL
#define WT_CONF_ID_checkpoint_sync 268ULL
#define WT_CONF_ID_checkpoint_use_history 100ULL
#define WT_CONF_ID_checkpoint_wait 93ULL
#define WT_CONF_ID_checksum 17ULL
#define WT_CONF_ID_chunk 244ULL
#define WT_CONF_ID_chunk_cache 231ULL
#define WT_CONF_ID_chunk_cache_evict_trigger 268ULL
#define WT_CONF_ID_chunk_size 269ULL
#define WT_CONF_ID_chunk 246ULL
#define WT_CONF_ID_chunk_cache 233ULL
#define WT_CONF_ID_chunk_cache_evict_trigger 270ULL
#define WT_CONF_ID_chunk_size 271ULL
#define WT_CONF_ID_claim_prepared_id 134ULL
#define WT_CONF_ID_close_handle_minimum 219ULL
#define WT_CONF_ID_close_idle_time 220ULL
#define WT_CONF_ID_close_scan_interval 221ULL
#define WT_CONF_ID_close_handle_minimum 221ULL
#define WT_CONF_ID_close_idle_time 222ULL
#define WT_CONF_ID_close_scan_interval 223ULL
#define WT_CONF_ID_colgroups 69ULL
#define WT_CONF_ID_collator 6ULL
#define WT_CONF_ID_columns 7ULL
#define WT_CONF_ID_commit_timestamp 2ULL
#define WT_CONF_ID_compare_timestamp 88ULL
#define WT_CONF_ID_compile_configuration_count 274ULL
#define WT_CONF_ID_compressor 288ULL
#define WT_CONF_ID_config 253ULL
#define WT_CONF_ID_config_base 275ULL
#define WT_CONF_ID_compile_configuration_count 276ULL
#define WT_CONF_ID_compressor 290ULL
#define WT_CONF_ID_config 255ULL
#define WT_CONF_ID_config_base 277ULL
#define WT_CONF_ID_configuration 188ULL
#define WT_CONF_ID_consolidate 107ULL
#define WT_CONF_ID_corruption_abort 186ULL
#define WT_CONF_ID_create 276ULL
#define WT_CONF_ID_create 278ULL
#define WT_CONF_ID_cursor_copy 189ULL
#define WT_CONF_ID_cursor_reposition 190ULL
#define WT_CONF_ID_cursors 154ULL
#define WT_CONF_ID_default 295ULL
#define WT_CONF_ID_dhandle_buckets 284ULL
#define WT_CONF_ID_default 297ULL
#define WT_CONF_ID_dhandle_buckets 286ULL
#define WT_CONF_ID_dictionary 18ULL
#define WT_CONF_ID_direct_io 277ULL
#define WT_CONF_ID_direct_io 279ULL
#define WT_CONF_ID_do_not_clear_txn_id 122ULL
#define WT_CONF_ID_drop 147ULL
#define WT_CONF_ID_dryrun 81ULL
@ -133,65 +134,65 @@
#define WT_CONF_ID_dump_tree_shape 130ULL
#define WT_CONF_ID_dump_version 103ULL
#define WT_CONF_ID_durable_timestamp 3ULL
#define WT_CONF_ID_early_load 254ULL
#define WT_CONF_ID_early_load 256ULL
#define WT_CONF_ID_enabled 37ULL
#define WT_CONF_ID_entry 255ULL
#define WT_CONF_ID_entry 257ULL
#define WT_CONF_ID_error_prefix 203ULL
#define WT_CONF_ID_evict_sample_inmem 207ULL
#define WT_CONF_ID_evict_use_softptr 208ULL
#define WT_CONF_ID_eviction 191ULL
#define WT_CONF_ID_eviction_checkpoint_target 210ULL
#define WT_CONF_ID_eviction_checkpoint_target 212ULL
#define WT_CONF_ID_eviction_checkpoint_ts_ordering 201ULL
#define WT_CONF_ID_eviction_dirty_target 211ULL
#define WT_CONF_ID_eviction_dirty_trigger 212ULL
#define WT_CONF_ID_eviction_obsolete_tw_pages_dirty_max 225ULL
#define WT_CONF_ID_eviction_target 213ULL
#define WT_CONF_ID_eviction_trigger 214ULL
#define WT_CONF_ID_eviction_updates_target 215ULL
#define WT_CONF_ID_eviction_updates_trigger 216ULL
#define WT_CONF_ID_eviction_dirty_target 213ULL
#define WT_CONF_ID_eviction_dirty_trigger 214ULL
#define WT_CONF_ID_eviction_obsolete_tw_pages_dirty_max 227ULL
#define WT_CONF_ID_eviction_target 215ULL
#define WT_CONF_ID_eviction_trigger 216ULL
#define WT_CONF_ID_eviction_updates_target 217ULL
#define WT_CONF_ID_eviction_updates_trigger 218ULL
#define WT_CONF_ID_exclude 82ULL
#define WT_CONF_ID_exclusive 86ULL
#define WT_CONF_ID_exclusive_refreshed 79ULL
#define WT_CONF_ID_extensions 280ULL
#define WT_CONF_ID_extra_diagnostics 217ULL
#define WT_CONF_ID_extensions 282ULL
#define WT_CONF_ID_extra_diagnostics 219ULL
#define WT_CONF_ID_file 108ULL
#define WT_CONF_ID_file_extend 281ULL
#define WT_CONF_ID_file_max 228ULL
#define WT_CONF_ID_file_extend 283ULL
#define WT_CONF_ID_file_max 230ULL
#define WT_CONF_ID_file_metadata 89ULL
#define WT_CONF_ID_file_wait_ms 179ULL
#define WT_CONF_ID_final_flush 150ULL
#define WT_CONF_ID_flush_time 67ULL
#define WT_CONF_ID_flush_timestamp 68ULL
#define WT_CONF_ID_flushed_data_cache_insertion 271ULL
#define WT_CONF_ID_flushed_data_cache_insertion 273ULL
#define WT_CONF_ID_force 94ULL
#define WT_CONF_ID_force_stop 109ULL
#define WT_CONF_ID_force_write_wait 289ULL
#define WT_CONF_ID_force_write_wait 291ULL
#define WT_CONF_ID_format 22ULL
#define WT_CONF_ID_free_space_target 83ULL
#define WT_CONF_ID_full_target 163ULL
#define WT_CONF_ID_generation_drain_timeout_ms 222ULL
#define WT_CONF_ID_generation_drain_timeout_ms 224ULL
#define WT_CONF_ID_get 121ULL
#define WT_CONF_ID_granularity 110ULL
#define WT_CONF_ID_handles 155ULL
#define WT_CONF_ID_hashsize 165ULL
#define WT_CONF_ID_hazard_max 285ULL
#define WT_CONF_ID_hazard_max 287ULL
#define WT_CONF_ID_huffman_key 23ULL
#define WT_CONF_ID_huffman_value 24ULL
#define WT_CONF_ID_id 59ULL
#define WT_CONF_ID_ignore_cache_size 260ULL
#define WT_CONF_ID_ignore_cache_size 262ULL
#define WT_CONF_ID_ignore_in_memory_cache_size 25ULL
#define WT_CONF_ID_ignore_prepare 135ULL
#define WT_CONF_ID_immutable 66ULL
#define WT_CONF_ID_in_memory 286ULL
#define WT_CONF_ID_in_memory 288ULL
#define WT_CONF_ID_inclusive 78ULL
#define WT_CONF_ID_internal_item_max 26ULL
#define WT_CONF_ID_internal_key_max 27ULL
#define WT_CONF_ID_internal_key_truncate 28ULL
#define WT_CONF_ID_internal_page_max 29ULL
#define WT_CONF_ID_interval 301ULL
#define WT_CONF_ID_interval 303ULL
#define WT_CONF_ID_isolation 136ULL
#define WT_CONF_ID_json 248ULL
#define WT_CONF_ID_json_output 232ULL
#define WT_CONF_ID_json 250ULL
#define WT_CONF_ID_json_output 234ULL
#define WT_CONF_ID_key_format 30ULL
#define WT_CONF_ID_key_gap 31ULL
#define WT_CONF_ID_keyid 21ULL
@ -212,9 +213,9 @@
#define WT_CONF_ID_memory_page_max 39ULL
#define WT_CONF_ID_metadata_file 90ULL
#define WT_CONF_ID_method 178ULL
#define WT_CONF_ID_mmap 291ULL
#define WT_CONF_ID_mmap_all 292ULL
#define WT_CONF_ID_multiprocess 293ULL
#define WT_CONF_ID_mmap 293ULL
#define WT_CONF_ID_mmap_all 294ULL
#define WT_CONF_ID_multiprocess 295ULL
#define WT_CONF_ID_name 20ULL
#define WT_CONF_ID_nbits 62ULL
#define WT_CONF_ID_next_random 113ULL
@ -223,107 +224,108 @@
#define WT_CONF_ID_no_timestamp 137ULL
#define WT_CONF_ID_nvram_path 167ULL
#define WT_CONF_ID_object_target_size 53ULL
#define WT_CONF_ID_obsolete_tw_btree_max 226ULL
#define WT_CONF_ID_obsolete_tw_btree_max 228ULL
#define WT_CONF_ID_oldest 71ULL
#define WT_CONF_ID_oldest_timestamp 262ULL
#define WT_CONF_ID_on_close 249ULL
#define WT_CONF_ID_oldest_timestamp 264ULL
#define WT_CONF_ID_on_close 251ULL
#define WT_CONF_ID_operation_timeout_ms 138ULL
#define WT_CONF_ID_os_cache_dirty_max 40ULL
#define WT_CONF_ID_os_cache_dirty_pct 234ULL
#define WT_CONF_ID_os_cache_dirty_pct 236ULL
#define WT_CONF_ID_os_cache_max 41ULL
#define WT_CONF_ID_overwrite 74ULL
#define WT_CONF_ID_page_log 278ULL
#define WT_CONF_ID_page_log 280ULL
#define WT_CONF_ID_panic_corrupt 91ULL
#define WT_CONF_ID_path 240ULL
#define WT_CONF_ID_path 242ULL
#define WT_CONF_ID_percent_file_in_dram 168ULL
#define WT_CONF_ID_pinned 181ULL
#define WT_CONF_ID_prealloc 235ULL
#define WT_CONF_ID_prealloc_init_count 236ULL
#define WT_CONF_ID_prealloc 237ULL
#define WT_CONF_ID_prealloc_init_count 238ULL
#define WT_CONF_ID_prefer_scrub_eviction 210ULL
#define WT_CONF_ID_prefix_compression 42ULL
#define WT_CONF_ID_prefix_compression_min 43ULL
#define WT_CONF_ID_prefix_search 75ULL
#define WT_CONF_ID_prepare_timestamp 143ULL
#define WT_CONF_ID_prepared 141ULL
#define WT_CONF_ID_prepared_id 144ULL
#define WT_CONF_ID_preserve_prepared 296ULL
#define WT_CONF_ID_preserve_prepared 298ULL
#define WT_CONF_ID_priority 139ULL
#define WT_CONF_ID_quota 245ULL
#define WT_CONF_ID_quota 247ULL
#define WT_CONF_ID_raw 116ULL
#define WT_CONF_ID_read 142ULL
#define WT_CONF_ID_read_corrupt 131ULL
#define WT_CONF_ID_read_once 117ULL
#define WT_CONF_ID_read_size 287ULL
#define WT_CONF_ID_read_size 289ULL
#define WT_CONF_ID_read_timestamp 4ULL
#define WT_CONF_ID_readonly 63ULL
#define WT_CONF_ID_realloc_exact 193ULL
#define WT_CONF_ID_realloc_malloc 194ULL
#define WT_CONF_ID_recover 290ULL
#define WT_CONF_ID_recover 292ULL
#define WT_CONF_ID_release 183ULL
#define WT_CONF_ID_release_evict 104ULL
#define WT_CONF_ID_release_evict_page 259ULL
#define WT_CONF_ID_remove 237ULL
#define WT_CONF_ID_release_evict_page 261ULL
#define WT_CONF_ID_remove 239ULL
#define WT_CONF_ID_remove_files 96ULL
#define WT_CONF_ID_remove_shared 97ULL
#define WT_CONF_ID_repair 92ULL
#define WT_CONF_ID_require_max 272ULL
#define WT_CONF_ID_require_min 273ULL
#define WT_CONF_ID_reserve 246ULL
#define WT_CONF_ID_require_max 274ULL
#define WT_CONF_ID_require_min 275ULL
#define WT_CONF_ID_reserve 248ULL
#define WT_CONF_ID_rollback_error 195ULL
#define WT_CONF_ID_run_once 84ULL
#define WT_CONF_ID_salvage 297ULL
#define WT_CONF_ID_secretkey 279ULL
#define WT_CONF_ID_session_max 298ULL
#define WT_CONF_ID_session_scratch_max 299ULL
#define WT_CONF_ID_session_table_cache 300ULL
#define WT_CONF_ID_salvage 299ULL
#define WT_CONF_ID_secretkey 281ULL
#define WT_CONF_ID_session_max 300ULL
#define WT_CONF_ID_session_scratch_max 301ULL
#define WT_CONF_ID_session_table_cache 302ULL
#define WT_CONF_ID_sessions 157ULL
#define WT_CONF_ID_shared 54ULL
#define WT_CONF_ID_size 164ULL
#define WT_CONF_ID_skip_sort_check 118ULL
#define WT_CONF_ID_slow_checkpoint 196ULL
#define WT_CONF_ID_source 8ULL
#define WT_CONF_ID_sources 250ULL
#define WT_CONF_ID_sources 252ULL
#define WT_CONF_ID_split_deepen_min_child 44ULL
#define WT_CONF_ID_split_deepen_per_child 45ULL
#define WT_CONF_ID_split_pct 46ULL
#define WT_CONF_ID_src_id 111ULL
#define WT_CONF_ID_stable_timestamp 132ULL
#define WT_CONF_ID_statistics 119ULL
#define WT_CONF_ID_storage_path 270ULL
#define WT_CONF_ID_storage_path 272ULL
#define WT_CONF_ID_stress_skiplist 197ULL
#define WT_CONF_ID_strict 133ULL
#define WT_CONF_ID_sync 98ULL
#define WT_CONF_ID_system_ram 169ULL
#define WT_CONF_ID_table_logging 198ULL
#define WT_CONF_ID_target 120ULL
#define WT_CONF_ID_terminate 256ULL
#define WT_CONF_ID_terminate 258ULL
#define WT_CONF_ID_this_id 112ULL
#define WT_CONF_ID_threads 242ULL
#define WT_CONF_ID_threads 244ULL
#define WT_CONF_ID_threads_max 205ULL
#define WT_CONF_ID_threads_min 206ULL
#define WT_CONF_ID_tiered_flush_error_continue 199ULL
#define WT_CONF_ID_tiered_object 64ULL
#define WT_CONF_ID_tiers 72ULL
#define WT_CONF_ID_timeout 85ULL
#define WT_CONF_ID_timestamp 251ULL
#define WT_CONF_ID_timing_stress_for_test 252ULL
#define WT_CONF_ID_total 230ULL
#define WT_CONF_ID_timestamp 253ULL
#define WT_CONF_ID_timing_stress_for_test 254ULL
#define WT_CONF_ID_total 232ULL
#define WT_CONF_ID_txn 158ULL
#define WT_CONF_ID_type 9ULL
#define WT_CONF_ID_update_restore_evict 200ULL
#define WT_CONF_ID_use_environment 303ULL
#define WT_CONF_ID_use_environment_priv 304ULL
#define WT_CONF_ID_use_environment 305ULL
#define WT_CONF_ID_use_environment_priv 306ULL
#define WT_CONF_ID_use_timestamp 149ULL
#define WT_CONF_ID_value_format 55ULL
#define WT_CONF_ID_verbose 10ULL
#define WT_CONF_ID_verify_metadata 305ULL
#define WT_CONF_ID_verify_metadata 307ULL
#define WT_CONF_ID_version 65ULL
#define WT_CONF_ID_wait 176ULL
#define WT_CONF_ID_write_through 306ULL
#define WT_CONF_ID_write_through 308ULL
#define WT_CONF_ID_write_timestamp 5ULL
#define WT_CONF_ID_write_timestamp_usage 11ULL
#define WT_CONF_ID_zero_fill 238ULL
#define WT_CONF_ID_zero_fill 240ULL
#define WT_CONF_ID_COUNT 307
#define WT_CONF_ID_COUNT 309
/*
* API configuration keys: END
*/
@ -413,9 +415,11 @@ static const struct {
uint64_t secretkey;
} Encryption;
struct {
uint64_t cache_tolerance_for_app_eviction;
uint64_t evict_sample_inmem;
uint64_t evict_use_softptr;
uint64_t legacy_page_visit_strategy;
uint64_t prefer_scrub_eviction;
uint64_t threads_max;
uint64_t threads_min;
} Eviction;
@ -775,9 +779,11 @@ static const struct {
WT_CONF_ID_Encryption | (WT_CONF_ID_secretkey << 16),
},
{
WT_CONF_ID_Eviction | (WT_CONF_ID_cache_tolerance_for_app_eviction << 16),
WT_CONF_ID_Eviction | (WT_CONF_ID_evict_sample_inmem << 16),
WT_CONF_ID_Eviction | (WT_CONF_ID_evict_use_softptr << 16),
WT_CONF_ID_Eviction | (WT_CONF_ID_legacy_page_visit_strategy << 16),
WT_CONF_ID_Eviction | (WT_CONF_ID_prefer_scrub_eviction << 16),
WT_CONF_ID_Eviction | (WT_CONF_ID_threads_max << 16),
WT_CONF_ID_Eviction | (WT_CONF_ID_threads_min << 16),
},

View File

@ -2200,22 +2200,31 @@ struct __wt_connection {
* @config{error_prefix, prefix string for error messages., a string; default empty.}
* @config{eviction = (, eviction configuration options., a set of related configuration options
* defined as follows.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;evict_sample_inmem, If no in-memory ref
* is found on the root page\, attempt to locate a random in-memory page by examining all
* entries on the root page., a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;
* legacy_page_visit_strategy, Use legacy page visit strategy for eviction. Using this option
* is highly discouraged as it will re-introduce the bug described in WT-9121., a boolean flag;
* default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_max, maximum number of threads
* WiredTiger will start to help evict pages from cache. The number of threads started will
* vary depending on the current eviction load. Each eviction worker thread uses a session from
* the configured session_max., an integer between \c 1 and \c 20; default \c 8.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_min, minimum number of threads WiredTiger will start
* to help evict pages from cache. The number of threads currently running will vary depending
* on the current eviction load., an integer between \c 1 and \c 20; default \c 1.}
* @config{
* ),,}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;cache_tolerance_for_app_eviction, This
* setting establishes a tolerance level for the configured \c eviction_dirty_trigger and \c
* eviction_update_trigger. The value is a percentage between 0 and 100\, with 0 treating \c
* eviction_dirty_trigger and \c eviction_update_trigger as hard limit. The configured
* percentage will be taken in increments of 10 only\, by applying the floor to the given
* percentage value., an integer between \c 0 and \c 100; default \c 0.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;evict_sample_inmem, If no in-memory ref is found on the root
* page\, attempt to locate a random in-memory page by examining all entries on the root page.,
* a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;legacy_page_visit_strategy,
* Use legacy page visit strategy for eviction. Using this option is highly discouraged as it
* will re-introduce the bug described in WT-9121., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;prefer_scrub_eviction, Change the eviction strategy to scrub
* eviction when the cache usage is under half way between the target limit to the trigger
* limit., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_max,
* maximum number of threads WiredTiger will start to help evict pages from cache. The number
* of threads started will vary depending on the current eviction load. Each eviction worker
* thread uses a session from the configured session_max., an integer between \c 1 and \c 20;
* default \c 8.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_min, minimum number of threads
* WiredTiger will start to help evict pages from cache. The number of threads currently
* running will vary depending on the current eviction load., an integer between \c 1 and \c 20;
* default \c 1.}
* @config{ ),,}
* @config{eviction_checkpoint_target, perform eviction at the beginning of checkpoints to bring
* the dirty content in cache to this level. It is a percentage of the cache size if the value
* is within the range of 0 to 100 or an absolute size when greater than 100. The value is not
@ -3069,21 +3078,29 @@ struct __wt_connection {
* @config{error_prefix, prefix string for error messages., a string; default empty.}
* @config{eviction = (, eviction configuration options., a set of related configuration options
* defined as follows.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;evict_sample_inmem, If no in-memory ref is
* found on the root page\, attempt to locate a random in-memory page by examining all entries on
* the root page., a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;cache_tolerance_for_app_eviction, This
* setting establishes a tolerance level for the configured \c eviction_dirty_trigger and \c
* eviction_update_trigger. The value is a percentage between 0 and 100\, with 0 treating \c
* eviction_dirty_trigger and \c eviction_update_trigger as hard limit. The configured percentage
* will be taken in increments of 10 only\, by applying the floor to the given percentage value., an
* integer between \c 0 and \c 100; default \c 0.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;
* legacy_page_visit_strategy, Use legacy page visit strategy for eviction. Using this option is
* highly discouraged as it will re-introduce the bug described in WT-9121., a boolean flag; default
* \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_max, maximum number of threads WiredTiger will
* start to help evict pages from cache. The number of threads started will vary depending on the
* current eviction load. Each eviction worker thread uses a session from the configured
* session_max., an integer between \c 1 and \c 20; default \c 8.}
* evict_sample_inmem, If no in-memory ref is found on the root page\, attempt to locate a random
* in-memory page by examining all entries on the root page., a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;legacy_page_visit_strategy, Use legacy page visit strategy for
* eviction. Using this option is highly discouraged as it will re-introduce the bug described in
* WT-9121., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;
* threads_min, minimum number of threads WiredTiger will start to help evict pages from cache. The
* number of threads currently running will vary depending on the current eviction load., an integer
* between \c 1 and \c 20; default \c 1.}
* prefer_scrub_eviction, Change the eviction strategy to scrub eviction when the cache usage is
* under half way between the target limit to the trigger limit., a boolean flag; default \c false.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_max, maximum number of threads WiredTiger will start to
* help evict pages from cache. The number of threads started will vary depending on the current
* eviction load. Each eviction worker thread uses a session from the configured session_max., an
* integer between \c 1 and \c 20; default \c 8.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;threads_min,
* minimum number of threads WiredTiger will start to help evict pages from cache. The number of
* threads currently running will vary depending on the current eviction load., an integer between
* \c 1 and \c 20; default \c 1.}
* @config{ ),,}
* @config{eviction_checkpoint_target, perform eviction at the beginning of checkpoints to bring the
* dirty content in cache to this level. It is a percentage of the cache size if the value is

View File

@ -109,6 +109,8 @@ struct __wt_bucket_storage;
typedef struct __wt_bucket_storage WT_BUCKET_STORAGE;
struct __wt_cache;
typedef struct __wt_cache WT_CACHE;
struct __wt_cache_eviction_controls;
typedef struct __wt_cache_eviction_controls WT_CACHE_EVICTION_CONTROLS;
struct __wt_cache_pool;
typedef struct __wt_cache_pool WT_CACHE_POOL;
struct __wt_capacity;

View File

@ -296,7 +296,12 @@ __wt_time_aggregate_validate(
*
*/
if (ta->oldest_start_ts > ta->newest_stop_ts)
/*
* Although timestamped truncates are supported in MongoDB, it is still possible for MongoDB to
* do truncate operations without a timestamp. In this case, validate needs to handle page
* deleted structures with a zero timestamp.
*/
if (ta->newest_stop_ts != WT_TS_NONE && ta->oldest_start_ts > ta->newest_stop_ts)
WT_TIME_VALIDATE_RET(session,
"aggregate time window has an oldest start time after its newest stop time; time "
"aggregate %s",
@ -325,8 +330,14 @@ __wt_time_aggregate_validate(
* start durable timestamp may be larger than newest stop timestamp. Check whether start and
* stop are equal first and then check the newest start durable timestamp against newest stop
* durable timestamp if all the data on the page are deleted.
*
*
* Although timestamped truncates are supported in MongoDB, it is still possible for MongoDB to
* do truncate operations without a timestamp. In this case, validate needs to handle page
* deleted structures with a zero timestamp.
*/
if (ta->newest_start_durable_ts != ta->newest_stop_durable_ts &&
if (ta->newest_stop_durable_ts != WT_TS_NONE &&
ta->newest_start_durable_ts != ta->newest_stop_durable_ts &&
ta->newest_stop_ts != WT_TS_MAX && ta->newest_start_durable_ts > ta->newest_stop_durable_ts)
WT_TIME_VALIDATE_RET(session,
"aggregate time window has a newest start durable time after its newest stop durable "

View File

@ -1667,9 +1667,11 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
/*
* Release our snapshot in case it is keeping data pinned (this is particularly important for
* checkpoints). Before releasing our snapshot, copy values into any positioned cursors so they
* don't point to updates that could be freed once we don't have a snapshot. If this transaction
* is prepared, then copying values would have been done during prepare.
* checkpoints). This will not make the updates visible to other threads because we haven't
* removed the transaction id from the global transaction table. Before releasing our snapshot,
* copy values into any positioned cursors so they don't point to updates that could be freed
* once we don't have a snapshot. If this transaction is prepared, then copying values would
* have been done during prepare.
*/
if (session->ncursors > 0 && !prepare) {
WT_DIAGNOSTIC_YIELD;
@ -1684,55 +1686,6 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
if (prepare)
__wt_qsort(txn->mod, txn->mod_count, sizeof(WT_TXN_OP), __txn_mod_compare);
/* If we are logging, write a commit log record. */
if (txn->logrec != NULL) {
/* Assert environment and tree are logging compatible, the fast-check is short-hand. */
WT_ASSERT(
session, !F_ISSET(conn, WT_CONN_RECOVERING) && F_ISSET(&conn->log_mgr, WT_LOG_ENABLED));
/*
* The default sync setting is inherited from the connection, but can be overridden by an
* explicit "sync" setting for this transaction.
*/
WT_ERR(__wt_config_gets_def(session, cfg, "sync", 0, &cval));
/*
* If the user chose the default setting, check whether sync is enabled for this transaction
* (either inherited or via begin_transaction). If sync is disabled, clear the field to
* avoid the log write being flushed.
*
* Otherwise check for specific settings. We don't need to check for "on" because that is
* the default inherited from the connection. If the user set anything in begin_transaction,
* we only override with an explicit setting.
*/
if (cval.len == 0) {
if (!FLD_ISSET(txn->txn_logsync, WT_LOG_SYNC_ENABLED) && !F_ISSET(txn, WT_TXN_SYNC_SET))
txn->txn_logsync = 0;
} else {
/*
* If the caller already set sync on begin_transaction then they should not be using
* sync on commit_transaction. Flag that as an error.
*/
if (F_ISSET(txn, WT_TXN_SYNC_SET))
WT_ERR_MSG(session, EINVAL, "sync already set during begin_transaction");
if (WT_CONFIG_LIT_MATCH("off", cval))
txn->txn_logsync = 0;
/*
* We don't need to check for "on" here because that is the default to inherit from the
* connection setting.
*/
}
/*
* We hold the visibility lock for reading from the time we write our log record until the
* time we release our transaction so that the LSN any checkpoint gets will always reflect
* visible data.
*/
__wt_readlock(session, &txn_global->visibility_rwlock);
locked = true;
WT_ERR(__wti_txn_log_commit(session));
}
/* Process updates. */
for (i = 0, op = txn->mod; i < txn->mod_count; i++, op++) {
switch (op->type) {
@ -1838,6 +1791,63 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR(__txn_check_if_stable_has_moved_ahead_commit_ts(session));
}
/*
* If we are logging, write a commit log record after we have finished committing the updates
* in-memory. Otherwise, we may still rollback if we fail.
*/
if (txn->logrec != NULL) {
/* Assert environment and tree are logging compatible, the fast-check is short-hand. */
WT_ASSERT(
session, !F_ISSET(conn, WT_CONN_RECOVERING) && F_ISSET(&conn->log_mgr, WT_LOG_ENABLED));
/*
* The default sync setting is inherited from the connection, but can be overridden by an
* explicit "sync" setting for this transaction.
*/
WT_ERR(__wt_config_gets_def(session, cfg, "sync", 0, &cval));
/*
* If the user chose the default setting, check whether sync is enabled for this transaction
* (either inherited or via begin_transaction). If sync is disabled, clear the field to
* avoid the log write being flushed.
*
* Otherwise check for specific settings. We don't need to check for "on" because that is
* the default inherited from the connection. If the user set anything in begin_transaction,
* we only override with an explicit setting.
*/
if (cval.len == 0) {
if (!FLD_ISSET(txn->txn_logsync, WT_LOG_SYNC_ENABLED) && !F_ISSET(txn, WT_TXN_SYNC_SET))
txn->txn_logsync = 0;
} else {
/*
* If the caller already set sync on begin_transaction then they should not be using
* sync on commit_transaction. Flag that as an error.
*/
if (F_ISSET(txn, WT_TXN_SYNC_SET))
WT_ERR_MSG(session, EINVAL, "sync already set during begin_transaction");
if (WT_CONFIG_LIT_MATCH("off", cval))
txn->txn_logsync = 0;
/*
* We don't need to check for "on" here because that is the default to inherit from the
* connection setting.
*/
}
/*
* We hold the visibility lock for reading from the time we write our log record until the
* time we release our transaction so that the LSN any checkpoint gets will always reflect
* visible data.
*/
__wt_readlock(session, &txn_global->visibility_rwlock);
locked = true;
WT_ERR(__wti_txn_log_commit(session));
}
/*
* !!!WARNING: Don't add anything that can fail here. We cannot fail after we have logged the
* transaction.
*/
/*
* Note: we're going to commit: nothing can fail after this point. Set a check, it's too easy to
* call an error handling macro between here and the end of the function.
@ -2030,6 +2040,12 @@ __wt_txn_prepare(WT_SESSION_IMPL *session, const char *cfg[])
WT_DIAGNOSTIC_YIELD;
WT_RET(__wt_session_copy_values(session));
}
/*
* Release our snapshot in case it is keeping data pinned. This will not make the updates
* visible to other threads until we remove the transaction id from the global transaction table
* at the end of the function.
*/
__wt_txn_release_snapshot(session);
for (i = 0, op = txn->mod; i < txn->mod_count; i++, op++) {
/* Assert it's not an update to the history store file. */
@ -2082,13 +2098,21 @@ __wt_txn_prepare(WT_SESSION_IMPL *session, const char *cfg[])
* truncation pages, they aren't linked into the transaction's modify list and so can't
* be considered.
*/
for (tmp = upd->next; tmp != NULL && tmp->txnid == upd->txnid; tmp = tmp->next)
for (tmp = upd->next; tmp != NULL; tmp = tmp->next) {
/* We may see aborted reserve updates in between the prepared updates. */
if (tmp->txnid == WT_TXN_ABORTED)
continue;
if (tmp->txnid != upd->txnid)
break;
if (tmp->type != WT_UPDATE_RESERVE &&
!F_ISSET(tmp, WT_UPDATE_RESTORED_FAST_TRUNCATE)) {
F_SET(op, WT_TXN_OP_KEY_REPEATED);
++prepared_updates_key_repeated;
break;
}
}
break;
case WT_TXN_OP_REF_DELETE:
__wt_txn_op_delete_apply_prepare_state(session, op->u.ref, false);
@ -2108,9 +2132,6 @@ __wt_txn_prepare(WT_SESSION_IMPL *session, const char *cfg[])
/* Set transaction state to prepare. */
F_SET(session->txn, WT_TXN_PREPARE);
/* Release our snapshot in case it is keeping data pinned. */
__wt_txn_release_snapshot(session);
/*
* Clear the transaction's ID from the global table, to facilitate prepared data visibility, but
* not from local transaction structure.
@ -2152,6 +2173,13 @@ __wt_txn_rollback(WT_SESSION_IMPL *session, const char *cfg[])
/* Configure the timeout for this rollback operation. */
WT_TRET(__txn_config_operation_timeout(session, cfg, true));
/*
* Release our snapshot in case it is keeping data pinned. This will not make the updates
* visible to other threads because we haven't removed the transaction id from the global
* transaction table at the end of the function.
*/
__wt_txn_release_snapshot(session);
/*
* Resolving prepared updates is expensive. Sort prepared modifications so all updates for each
* page within each file are done at the same time.

View File

@ -30,6 +30,7 @@ bflag()
{
# Return if the branch's format command takes the -B flag for backward compatibility.
test "$1" = "develop" && echo "-B "
test "$1" = "mongodb-8.2" && echo "-B"
test "$1" = "mongodb-8.0" && echo "-B"
test "$1" = "mongodb-7.0" && echo "-B "
test "$1" = "mongodb-6.0" && echo "-B "
@ -178,6 +179,7 @@ create_configs()
echo "runs.type=row" >> $file_name # WT-7379 - Temporarily disable column store tests
echo "btree.huffman_value=0" >> $file_name # WT-12456 - Never used, removed from newer releases
echo "btree.prefix=0" >> $file_name # WT-7579 - Prefix testing isn't portable between releases
echo "btree.prefix_len=0" >> $file_name # WT-15548 - Not supported by older releases
echo "cache=80" >> $file_name # Medium cache so there's eviction
echo "checksum=on" >> $file_name # WT-7851 Fix illegal checksum configuration
echo "checkpoints=1" >> $file_name # Force periodic writes
@ -192,6 +194,8 @@ create_configs()
echo "leak_memory=1" >> $file_name # Faster runs
echo "logging=1" >> $file_name # Test log compatibility
echo "logging_compression=snappy" >> $file_name # We only built with snappy, force the choice
echo "obsolete_cleanup.method=off" >> $file_name # WT-14142 - Not supported by older releases
echo "obsolete_cleanup.wait=0" >> $file_name # WT-14142 - Not supported by older releases
echo "prefetch=0" >> $file_name # WT-12978 - Not supported by older releases
echo "rows=1000000" >> $file_name
echo "salvage=0" >> $file_name # Faster runs

View File

@ -229,7 +229,7 @@ CONFIG configuration_list[] = {
{"obsolete_cleanup.method", "obsolete cleanup strategy", C_IGNORE | C_STRING, 0, 0, 0}
{"obsolete_cleanup.wait", "obsolete cleanup interval in seconds", 0x0, 1, 3600, 100000}
{"obsolete_cleanup.wait", "obsolete cleanup interval in seconds", 0x0, 0, 3600, 100000}
{"ops.alter", "configure table alterations", C_BOOL, 10, 0, 0}

View File

@ -229,7 +229,7 @@ CONFIG configuration_list[] = {{"assert.read_timestamp", "assert read_timestamp"
{"obsolete_cleanup.method", "obsolete cleanup strategy", C_IGNORE | C_STRING, 0, 0, 0,
V_GLOBAL_OBSOLETE_CLEANUP_METHOD},
{"obsolete_cleanup.wait", "obsolete cleanup interval in seconds", 0x0, 1, 3600, 100000,
{"obsolete_cleanup.wait", "obsolete cleanup interval in seconds", 0x0, 0, 3600, 100000,
V_GLOBAL_OBSOLETE_CLEANUP_WAIT},
{"ops.alter", "configure table alterations", C_BOOL, 10, 0, 0, V_GLOBAL_OPS_ALTER},

View File

@ -389,6 +389,14 @@ configure_prefetch(char **p, size_t max)
static void
configure_obsolete_cleanup(char **p, size_t max)
{
/*
* If it's all off, don't even generate the outer checkpoint_cleanup config. It's not compatible
* with older branches, so take both options being configured off as a proxy for the whole
* feature being turned off.
*/
if (strcmp(GVS(OBSOLETE_CLEANUP_METHOD), "off") == 0 && GV(OBSOLETE_CLEANUP_WAIT) == 0)
return;
CONFIG_APPEND(*p, ",checkpoint_cleanup=[");
/* Strategy. */
@ -396,7 +404,8 @@ configure_obsolete_cleanup(char **p, size_t max)
CONFIG_APPEND(*p, "method=%s", (char *)GVS(OBSOLETE_CLEANUP_METHOD));
/* Interval. */
CONFIG_APPEND(*p, ",wait=%" PRIu32, GV(OBSOLETE_CLEANUP_WAIT));
if (GV(OBSOLETE_CLEANUP_WAIT) != 0)
CONFIG_APPEND(*p, ",wait=%" PRIu32, GV(OBSOLETE_CLEANUP_WAIT));
CONFIG_APPEND(*p, "]");
}

View File

@ -0,0 +1,80 @@
#!/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.
import wiredtiger
import wttest
# For now, this is just making sure the flags are set without errors
# Test that cache eviction controls can be reconfigured dynamically
# and do not require a connection restart.
class test_cache_evict_config01(wttest.WiredTigerTestCase):
conn_config = "cache_size=50MB,statistics=(all)"
uri = "table:eviction01"
def test_cache_eviction_reconfig(self):
# Create a table and insert baseline data
self.session.create(self.uri, "key_format=i,value_format=S")
cursor = self.session.open_cursor(self.uri)
for i in range(5):
cursor[i] = "init" + str(i)
cursor.close()
# Try different eviction reconfigurations.
configs = [
"eviction=[prefer_scrub_eviction=true,cache_tolerance_for_app_eviction=0]",
"eviction=[prefer_scrub_eviction=false,cache_tolerance_for_app_eviction=100]",
"eviction=[prefer_scrub_eviction=false,cache_tolerance_for_app_eviction=25]",
"eviction=[prefer_scrub_eviction=true,cache_tolerance_for_app_eviction=20]",
]
# Try different eviction failure reconfigurations.
failure_configs = [
"eviction=[cache_tolerance_for_app_eviction=-1]",
"eviction=[cache_tolerance_for_app_eviction=110]",
]
for cfg in configs:
self.conn.reconfigure(cfg)
# Verify the connection is still alive by inserting more rows
cursor = self.session.open_cursor(self.uri)
for i in range(5, 10):
cursor[i] = "postreconfig_" + str(i)
cursor.close()
# Ensure rows can be read
cursor = self.session.open_cursor(self.uri)
count = sum(1 for _ in cursor)
self.assertGreaterEqual(count, 5)
cursor.close()
for cfg in failure_configs:
self.assertRaisesException(wiredtiger.WiredTigerError,
lambda: self.conn.reconfigure(cfg), 'Invalid argument')
self.ignoreStderrPatternIfExists('Invalid argument')

View File

@ -0,0 +1,73 @@
#!/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.
import wttest
from wiredtiger import stat
# Test that cache eviction controls can be reconfigured dynamically
# and that WT_CACHE_PREFER_SCRUB_EVICTION behaves correctly.
class test_cache_evict_config02(wttest.WiredTigerTestCase):
conn_config = "cache_size=5MB,statistics=(all),eviction=[prefer_scrub_eviction=false]"
uri = "table:eviction02"
def test_cache_eviction_reconfig_and_scrub(self):
self.session.create(self.uri, "key_format=i,value_format=S")
cursor = self.session.open_cursor(self.uri)
# Repeatedly update 100 keys to fill cache usage with dirty / updates
val = "x" * 5000
for i in range(50000):
cursor[i % 100] = val
cursor.close()
# Baseline eviction stats before enabling scrub
stat_cursor = self.session.open_cursor("statistics:")
pages_scrubbed_baseline = stat_cursor[stat.conn.cache_write_restore][2]
stat_cursor.close()
# Enable prefer_scrub_eviction flag
self.conn.reconfigure(
"eviction=[prefer_scrub_eviction=true]"
)
cursor = self.session.open_cursor(self.uri)
for i in range(50000):
cursor[i % 100] = val
cursor.close()
# Check eviction stats after enabling scrub
stat_cursor = self.session.open_cursor("statistics:")
pages_scrubbed_with_flag = stat_cursor[stat.conn.cache_write_restore][2]
stat_cursor.close()
# Check that by enabling scrub-under-target flag, more pages were scrub evicted
self.assertGreater(
pages_scrubbed_with_flag,
pages_scrubbed_baseline,
"Scrub eviction should increase restored updates when enabled"
)

View File

@ -0,0 +1,97 @@
#!/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.
import wttest
from wtscenario import make_scenarios
# Test that prepared transactions are properly handled during page eviction and checkpointing.
# Verify that pages with prepared tombstones are not incorrectly skipped during walks when opening a cursor
class test_prepare43(wttest.WiredTigerTestCase):
uri = 'table:test_prepare43'
format_values = [
('column-fix', dict(key_format='r', value_format='8t')),
('column', dict(key_format='r', value_format='S')),
('row', dict(key_format='r', value_format='S')),
]
ckpt_precision = [
('fuzzy', dict(ckpt_config='precise_checkpoint=false')),
('precise', dict(ckpt_config='precise_checkpoint=true,preserve_prepared=true')),
]
scenarios = make_scenarios(format_values, ckpt_precision)
def test_prepare43(self):
self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(20))
self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(10))
create_params = 'key_format=' + self.key_format + ',value_format=' + self.value_format
self.session.create(self.uri, create_params)
# Insert a value and commit for keys 1-19
cursor = self.session.open_cursor(self.uri)
self.session.begin_transaction()
for i in range(1, 100):
value = i if self.value_format == '8t' else "commit_value"
cursor[i] = value
self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(21))
cursor = self.session.open_cursor(self.uri)
self.session.begin_transaction()
for i in range(1, 100):
cursor.set_key(i)
cursor.remove()
self.session.prepare_transaction(f"prepare_timestamp={self.timestamp_str(25)}")
# move the stable ts to be past prepare ts
self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(26))
session2 = self.conn.open_session()
session2.checkpoint()
# Force the page to be evicted, checkpoint will write the tombstone as prepared
session_evict = self.conn.open_session("debug=(release_evict_page=true)")
session_evict.begin_transaction("ignore_prepare=true")
evict_cursor = session_evict.open_cursor(self.uri, None, None)
for i in range(1, 100):
evict_cursor.set_key(i)
evict_cursor.search()
evict_cursor.reset()
session_evict.rollback_transaction()
# Check that we can open a checkpoint cursor and find all keys
cursor = session2.open_cursor(
self.uri, None, "checkpoint=WiredTigerCheckpoint")
i = 1
while True:
ret = cursor.next()
if ret != 0:
break
self.assertEqual(cursor.get_key(), i)
self.assertEqual(cursor.get_value(), i if self.value_format == '8t' else "commit_value")
i += 1
self.assertEqual(i, 100)

View File

@ -0,0 +1,100 @@
#!/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.
import random
import string
import wttest
from wiredtiger import stat
from wtscenario import make_scenarios
from wtdataset import SimpleDataSet
# test_truncate29.py
# Test that verify handles timestamp usage checks correctly after timestamped fast truncate operations were enabled.
class test_truncate29(wttest.WiredTigerTestCase):
uri = 'file:test_truncate29'
conn_config = 'statistics=(all)'
nrows = 10000
def generate_random_string(self, length):
characters = string.ascii_letters + string.digits
random_string = ''.join(random.choices(characters, k=length))
return random_string
def get_fast_truncated_pages(self):
stat_cursor = self.session.open_cursor('statistics:', None, None)
pages = stat_cursor[stat.conn.rec_page_delete_fast][2]
stat_cursor.close()
return pages
def test_truncate29(self):
ds = SimpleDataSet(self, self.uri, 0, key_format='i', value_format='S')
ds.populate()
val1 = self.generate_random_string(12345)
val2 = self.generate_random_string(12345)
# Insert a large amount of data.
cursor = self.session.open_cursor(self.uri)
for i in range(1, self.nrows):
self.session.begin_transaction()
cursor[ds.key(i)] = str(val1)
self.session.commit_transaction(f'commit_timestamp={self.timestamp_str(30)}')
# Insert some more data at a later timestamp.
for i in range(1, self.nrows):
self.session.begin_transaction()
cursor[ds.key(i)] = str(val2)
self.session.commit_transaction(f'commit_timestamp={self.timestamp_str(50)}')
# Make the data globally visible.
self.conn.set_timestamp(f'stable_timestamp={self.timestamp_str(50)},oldest_timestamp={self.timestamp_str(50)}')
self.reopen_conn()
# Have a long-running transaction. Don't commit or roll this back.
s1 = self.conn.open_session()
s1.begin_transaction()
pinned_cursor = s1.open_cursor(self.uri, None)
pinned_cursor.set_key(ds.key(100))
pinned_cursor.search()
# Truncate everything.
self.session.begin_transaction('no_timestamp=true')
self.session.truncate(self.uri, None, None, None)
self.session.commit_transaction()
fast_truncates_pages = self.get_fast_truncated_pages()
self.assertGreater(fast_truncates_pages, 0)
# Do a checkpoint.
self.session.checkpoint()
pinned_cursor.close()
s1.rollback_transaction()
self.session.verify(self.uri, None)

View File

@ -0,0 +1,87 @@
#!/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.
import wiredtiger, wttest
from helper import simulate_crash_restart
# test_txn29.py
# Test that transaction cannot be rolled back after being logged.
class test_txn29(wttest.WiredTigerTestCase):
conn_config = "log=(enabled=true)"
def test_transaction_logging(self):
if wiredtiger.diagnostic_build():
self.skipTest('requires a non-diagnostic build')
# Create a logged table
uri1 = "file:txn29-1"
self.session.create(uri1, 'key_format=i,value_format=S')
# Create a non-logged table
uri2 = "file:txn29-2"
self.session.create(uri2, 'key_format=i,value_format=S,log=(enabled=false)')
# Do an update on the logged table and the non-logged table
self.session.begin_transaction()
cursor1 = self.session.open_cursor(uri1)
cursor1[1] = "aaaa"
cursor1.reset()
cursor2 = self.session.open_cursor(uri2)
cursor2[1] = "aaaa"
cursor2.reset()
self.session.commit_transaction(f'sync=on,commit_timestamp={self.timestamp_str(20)}')
# Do an update on the logged table and the non-logged table
self.session.begin_transaction()
cursor1 = self.session.open_cursor(uri1)
cursor1[1] = "bbbb"
cursor1.reset()
cursor2 = self.session.open_cursor(uri2)
cursor2[1] = "bbbb"
cursor2.reset()
self.assertRaisesException(wiredtiger.WiredTigerError,
lambda: self.session.commit_transaction(f'sync=on,commit_timestamp={self.timestamp_str(10)}'))
simulate_crash_restart(self, ".", "RESTART")
# Should not see bbbb.
self.session.begin_transaction()
cursor2 = self.session.open_cursor(uri2)
cursor2.set_key(1)
self.assertEqual(cursor2.search(), wiredtiger.WT_NOTFOUND)
cursor2.close()
cursor1 = self.session.open_cursor(uri1)
cursor1.set_key(1)
cursor1.search()
value = cursor1.get_value()
self.assertEqual(value, 'aaaa')
cursor1.close()
self.session.rollback_transaction()
self.ignoreStderrPatternIfExists('unexpected timestamp usage')