diff --git a/components/engine_rocks/src/properties.rs b/components/engine_rocks/src/properties.rs index dadf4a643df..bdc7c87db0b 100644 --- a/components/engine_rocks/src/properties.rs +++ b/components/engine_rocks/src/properties.rs @@ -400,6 +400,7 @@ impl TablePropertiesCollectorFactory for RangePropertiesCollectorFactory { } } +/// Can only be used for write CF. pub struct MvccPropertiesCollector { props: MvccProperties, last_row: Vec, @@ -506,6 +507,7 @@ impl TablePropertiesCollector for MvccPropertiesCollector { } } +/// Can only be used for write CF. #[derive(Default)] pub struct MvccPropertiesCollectorFactory {} diff --git a/components/engine_rocks/src/table_properties.rs b/components/engine_rocks/src/table_properties.rs index e083e3324f6..097a9a3b643 100644 --- a/components/engine_rocks/src/table_properties.rs +++ b/components/engine_rocks/src/table_properties.rs @@ -9,7 +9,7 @@ use engine_traits::{ TableProperties, TablePropertiesCollectionIter, TablePropertiesKey, UserCollectedProperties, }; use engine_traits::{TablePropertiesCollection, TablePropertiesExt}; -use rocksdb::table_properties_rc as raw; +use rocksdb::table_properties_rc as rc; use std::ops::Deref; impl TablePropertiesExt for RocksEngine { @@ -35,10 +35,10 @@ impl TablePropertiesExt for RocksEngine { } } -pub struct RocksTablePropertiesCollection(raw::TablePropertiesCollection); +pub struct RocksTablePropertiesCollection(rc::TablePropertiesCollection); impl RocksTablePropertiesCollection { - fn from_raw(raw: raw::TablePropertiesCollection) -> RocksTablePropertiesCollection { + fn from_raw(raw: rc::TablePropertiesCollection) -> RocksTablePropertiesCollection { RocksTablePropertiesCollection(raw) } } @@ -60,7 +60,7 @@ impl } } -pub struct RocksTablePropertiesCollectionIter(raw::TablePropertiesCollectionIter); +pub struct RocksTablePropertiesCollectionIter(rc::TablePropertiesCollectionIter); impl TablePropertiesCollectionIter< @@ -81,7 +81,7 @@ impl Iterator for RocksTablePropertiesCollectionIter { } } -pub struct RocksTablePropertiesKey(raw::TablePropertiesKey); +pub struct RocksTablePropertiesKey(rc::TablePropertiesKey); impl TablePropertiesKey for RocksTablePropertiesKey {} @@ -93,7 +93,7 @@ impl Deref for RocksTablePropertiesKey { } } -pub struct RocksTableProperties(raw::TableProperties); +pub struct RocksTableProperties(rc::TableProperties); impl TableProperties for RocksTableProperties { fn num_entries(&self) -> u64 { @@ -105,7 +105,8 @@ impl TableProperties for RocksTableProperties { } } -pub struct RocksUserCollectedProperties(raw::UserCollectedProperties); +#[repr(transparent)] +pub struct RocksUserCollectedProperties(rc::UserCollectedProperties); impl UserCollectedProperties for RocksUserCollectedProperties { fn get(&self, index: &[u8]) -> Option<&[u8]> { @@ -123,3 +124,13 @@ impl DecodeProperties for RocksUserCollectedProperties { .ok_or(tikv_util::codec::Error::KeyNotFound) } } + +#[repr(transparent)] +pub struct RocksUserCollectedPropertiesNoRc(rocksdb::UserCollectedProperties); +impl DecodeProperties for RocksUserCollectedPropertiesNoRc { + fn decode(&self, k: &str) -> tikv_util::codec::Result<&[u8]> { + self.0 + .get(k.as_bytes()) + .ok_or(tikv_util::codec::Error::KeyNotFound) + } +} diff --git a/components/engine_traits/src/mvcc_properties.rs b/components/engine_traits/src/mvcc_properties.rs index 8bf1c9d2a4a..bdc334db9c1 100644 --- a/components/engine_traits/src/mvcc_properties.rs +++ b/components/engine_traits/src/mvcc_properties.rs @@ -3,7 +3,7 @@ use std::cmp; use txn_types::TimeStamp; -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct MvccProperties { pub min_ts: TimeStamp, // The minimal timestamp. pub max_ts: TimeStamp, // The maximal timestamp. diff --git a/src/server/gc_worker/compaction_filter.rs b/src/server/gc_worker/compaction_filter.rs index 28873b0a068..701bedf3520 100644 --- a/src/server/gc_worker/compaction_filter.rs +++ b/src/server/gc_worker/compaction_filter.rs @@ -7,15 +7,18 @@ use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use super::{GcConfig, GcWorkerConfigManager}; -use crate::storage::mvcc::{GC_DELETE_VERSIONS_HISTOGRAM, MVCC_VERSIONS_HISTOGRAM}; +use crate::storage::mvcc::{check_need_gc, GC_DELETE_VERSIONS_HISTOGRAM, MVCC_VERSIONS_HISTOGRAM}; use engine_rocks::raw::{ new_compaction_filter_raw, CompactionFilter, CompactionFilterContext, CompactionFilterFactory, DBCompactionFilter, DB, }; -use engine_rocks::{RocksEngine, RocksEngineIterator, RocksWriteBatch}; +use engine_rocks::{ + RocksEngine, RocksEngineIterator, RocksMvccProperties, RocksUserCollectedPropertiesNoRc, + RocksWriteBatch, +}; use engine_traits::{ - IterOptions, Iterable, Iterator, MiscExt, Mutable, SeekKey, WriteBatchExt, WriteOptions, - CF_WRITE, + IterOptions, Iterable, Iterator, MiscExt, Mutable, MvccProperties, SeekKey, WriteBatchExt, + WriteOptions, CF_WRITE, }; use pd_client::ClusterVersion; use txn_types::{Key, WriteRef, WriteType}; @@ -23,6 +26,7 @@ use txn_types::{Key, WriteRef, WriteType}; const DEFAULT_DELETE_BATCH_SIZE: usize = 256 * 1024; const DEFAULT_DELETE_BATCH_COUNT: usize = 128; const NEAR_SEEK_LIMIT: usize = 16; +const SINGLE_SST_RATIO_THRESHOLD_ADJUST: f64 = 0.2; // The default version that can enable compaction filter for GC. This is necessary because after // compaction filter is enabled, it's impossible to fallback to ealier version which modifications @@ -92,14 +96,50 @@ impl CompactionFilterFactory for WriteCompactionFilterFactory { let safe_point = gc_context.safe_point.load(Ordering::Relaxed); if safe_point == 0 { + debug!("skip gc in compaction filter because of no safe point"); // Safe point has not been initialized yet. return std::ptr::null_mut(); } - if !is_compaction_filter_allowd( - &*gc_context.cfg_tracker.value(), - &gc_context.cluster_version, - ) { + let (enable, skip_vcheck, ratio_threshold) = { + let value = &*gc_context.cfg_tracker.value(); + ( + value.enable_compaction_filter, + value.compaction_filter_skip_version_check, + value.ratio_threshold, + ) + }; + debug!( + "creating compaction filter"; "feature_enable" => enable, + "skip_version_check" => skip_vcheck, + "ratio_threshold" => ratio_threshold, + ); + + if !do_check_allowed(enable, skip_vcheck, &gc_context.cluster_version) { + debug!("skip gc in compaction filter because it's not allowed"); + return std::ptr::null_mut(); + } + + let (mut needs_gc, mut mvcc_props) = (false, MvccProperties::new()); + for i in 0..context.file_numbers().len() { + let table_props = context.table_properties(i); + let user_props = unsafe { + &*(table_props.user_collected_properties() as *const _ + as *const RocksUserCollectedPropertiesNoRc) + }; + if let Ok(props) = RocksMvccProperties::decode(user_props) { + mvcc_props.add(&props); + let sst_ratio = ratio_threshold + SINGLE_SST_RATIO_THRESHOLD_ADJUST; + if check_need_gc(safe_point.into(), sst_ratio, &props) { + needs_gc = true; + break; + } + } + } + if !needs_gc && !check_need_gc(safe_point.into(), ratio_threshold, &mvcc_props) { + // NOTE: here we don't treat the bottommost level specially. + // Maybe it's necessary to make a green channel for it. + debug!("skip gc in compaction filter because it's not necessary"); return std::ptr::null_mut(); } @@ -132,9 +172,13 @@ struct WriteCompactionFilter { } impl WriteCompactionFilter { - fn new(db: Arc, safe_point: u64, _context: &CompactionFilterContext) -> Self { + fn new(db: Arc, safe_point: u64, context: &CompactionFilterContext) -> Self { // Safe point must have been initialized. assert!(safe_point > 0); + debug!( + "gc in compaction filter"; + "safe_point" => safe_point, "files" => ?context.file_numbers(), + ); let engine = RocksEngine::from_db(db.clone()); let write_batch = RocksWriteBatch::with_capacity(db, DEFAULT_DELETE_BATCH_SIZE); @@ -362,8 +406,16 @@ fn parse_write(value: &[u8]) -> WriteRef { } pub fn is_compaction_filter_allowd(cfg_value: &GcConfig, cluster_version: &ClusterVersion) -> bool { - cfg_value.enable_compaction_filter - && (cfg_value.compaction_filter_skip_version_check || { + do_check_allowed( + cfg_value.enable_compaction_filter, + cfg_value.compaction_filter_skip_version_check, + cluster_version, + ) +} + +fn do_check_allowed(enable: bool, skip_vcheck: bool, cluster_version: &ClusterVersion) -> bool { + enable + && (skip_vcheck || { cluster_version.get().map_or(false, |cluster_version| { let minimal = semver::Version::parse(COMPACTION_FILTER_MINIMAL_VERSION).unwrap(); cluster_version >= minimal @@ -389,6 +441,13 @@ pub mod tests { static ref LOCK: Mutex<()> = std::sync::Mutex::new(()); } + fn compact_options() -> CompactOptions { + let mut compact_opts = CompactOptions::new(); + compact_opts.set_exclusive_manual_compaction(false); + compact_opts.set_max_subcompactions(1); + compact_opts + } + fn do_gc_by_compact( engine: &RocksEngine, start: Option<&[u8]>, @@ -397,6 +456,7 @@ pub mod tests { target_level: Option, ) { let _guard = LOCK.lock().unwrap(); + let safe_point = Arc::new(AtomicU64::new(safe_point)); let cfg = GcWorkerConfigManager(Arc::new(Default::default())); cfg.0.update(|v| v.enable_compaction_filter = true); @@ -405,10 +465,7 @@ pub mod tests { let db = engine.as_inner(); let handle = get_cf_handle(db, CF_WRITE).unwrap(); - - let mut compact_opts = CompactOptions::new(); - compact_opts.set_exclusive_manual_compaction(false); - compact_opts.set_max_subcompactions(1); + let mut compact_opts = compact_options(); if let Some(target_level) = target_level { compact_opts.set_change_level(true); compact_opts.set_target_level(target_level as i32); @@ -416,10 +473,31 @@ pub mod tests { db.compact_range_cf_opt(handle, &compact_opts, start, end); } + fn do_gc_by_compact_with_ratio_threshold( + engine: &RocksEngine, + safe_point: u64, + ratio_threshold: f64, + ) { + let _guard = LOCK.lock().unwrap(); + + let safe_point = Arc::new(AtomicU64::new(safe_point)); + let cfg = GcWorkerConfigManager(Arc::new(Default::default())); + cfg.0.update(|v| { + v.enable_compaction_filter = true; + v.ratio_threshold = ratio_threshold; + }); + let cluster_version = ClusterVersion::new(semver::Version::new(5, 0, 0)); + engine.init_compaction_filter(safe_point, cfg, cluster_version); + + let db = engine.as_inner(); + let handle = get_cf_handle(db, CF_WRITE).unwrap(); + db.compact_range_cf_opt(handle, &compact_options(), None, None); + } + pub fn gc_by_compact(engine: &StorageRocksEngine, _: &[u8], safe_point: u64) { let engine = engine.get_rocksdb(); // Put a new key-value pair to ensure compaction can be triggered correctly. - engine.delete_cf("write", b"not-exists-key").unwrap(); + engine.delete_cf("write", b"znot-exists-key").unwrap(); do_gc_by_compact(&engine, None, None, safe_point, None); } @@ -457,26 +535,26 @@ pub mod tests { let value = vec![b'v'; 512]; // GC can't delete keys after the given safe point. - must_prewrite_put(&engine, b"key", &value, b"key", 100); - must_commit(&engine, b"key", 100, 110); + must_prewrite_put(&engine, b"zkey", &value, b"zkey", 100); + must_commit(&engine, b"zkey", 100, 110); do_gc_by_compact(&raw_engine, None, None, 50, None); - must_get(&engine, b"key", 110, &value); + must_get(&engine, b"zkey", 110, &value); // GC can't delete keys before the safe ponit if they are latest versions. do_gc_by_compact(&raw_engine, None, None, 200, None); - must_get(&engine, b"key", 110, &value); + must_get(&engine, b"zkey", 110, &value); - must_prewrite_put(&engine, b"key", &value, b"key", 120); - must_commit(&engine, b"key", 120, 130); + must_prewrite_put(&engine, b"zkey", &value, b"zkey", 120); + must_commit(&engine, b"zkey", 120, 130); // GC can't delete the latest version before the safe ponit. do_gc_by_compact(&raw_engine, None, None, 115, None); - must_get(&engine, b"key", 110, &value); + must_get(&engine, b"zkey", 110, &value); // GC a version will also delete the key on default CF. do_gc_by_compact(&raw_engine, None, None, 200, None); - must_get_none(&engine, b"key", 110); - let default_key = Key::from_encoded_slice(b"key").append_ts(100.into()); + must_get_none(&engine, b"zkey", 110); + let default_key = Key::from_encoded_slice(b"zkey").append_ts(100.into()); let default_key = default_key.into_encoded(); assert!(raw_engine.get_value(&default_key).unwrap().is_none()); } @@ -488,21 +566,41 @@ pub mod tests { let value = vec![b'v'; 512]; // Delete mark and masked versions can be handled in `drop`. - must_prewrite_put(&engine, b"key", &value, b"key", 100); - must_commit(&engine, b"key", 100, 110); - must_prewrite_delete(&engine, b"key", b"key", 120); - must_commit(&engine, b"key", 120, 130); + must_prewrite_put(&engine, b"zkey", &value, b"zkey", 100); + must_commit(&engine, b"zkey", 100, 110); + must_prewrite_delete(&engine, b"zkey", b"zkey", 120); + must_commit(&engine, b"zkey", 120, 130); do_gc_by_compact(&raw_engine, None, None, 200, None); - must_get_none(&engine, b"key", 110); - - must_prewrite_put(&engine, b"key", &value, b"key", 100); - must_commit(&engine, b"key", 100, 110); - must_prewrite_delete(&engine, b"key", b"key", 120); - must_commit(&engine, b"key", 120, 130); - must_prewrite_put(&engine, b"key1", &value, b"key1", 120); - must_commit(&engine, b"key1", 120, 130); + must_get_none(&engine, b"zkey", 110); + + must_prewrite_put(&engine, b"zkey", &value, b"zkey", 100); + must_commit(&engine, b"zkey", 100, 110); + must_prewrite_delete(&engine, b"zkey", b"zkey", 120); + must_commit(&engine, b"zkey", 120, 130); + must_prewrite_put(&engine, b"zkey1", &value, b"zkey1", 120); + must_commit(&engine, b"zkey1", 120, 130); do_gc_by_compact(&raw_engine, None, None, 200, None); - must_get_none(&engine, b"key", 110); + must_get_none(&engine, b"zkey", 110); + } + + #[test] + fn test_mvcc_properties() { + let engine = TestEngineBuilder::new().build().unwrap(); + let raw_engine = engine.get_rocksdb(); + let value = vec![b'v'; 512]; + + for start_ts in &[100, 110, 120, 130] { + must_prewrite_put(&engine, b"zkey", &value, b"zkey", *start_ts); + must_commit(&engine, b"zkey", *start_ts, *start_ts + 5); + } + must_prewrite_delete(&engine, b"zkey", b"zkey", 140); + must_commit(&engine, b"zkey", 140, 145); + + // Can't GC stale versions because of the threshold. + do_gc_by_compact_with_ratio_threshold(&raw_engine, 200, 10.0); + for commit_ts in &[105, 115, 125, 135] { + must_get(&engine, b"zkey", commit_ts, &value); + } } // Test a key can be GCed correctly if its MVCC versions cover multiple SST files. @@ -514,29 +612,29 @@ pub mod tests { let engine = TestEngineBuilder::new().build().unwrap(); let raw_engine = engine.get_rocksdb(); - let split_key = Key::from_raw(b"key") + let split_key = Key::from_raw(b"zkey") .append_ts(TimeStamp::from(135)) .into_encoded(); // So the construction of SST files will be: // L6: |key_110| - must_prewrite_put(&engine, b"key", b"value", b"key", 100); - must_commit(&engine, b"key", 100, 110); + must_prewrite_put(&engine, b"zkey", b"zvalue", b"zkey", 100); + must_commit(&engine, b"zkey", 100, 110); do_gc_by_compact(&raw_engine, None, None, 50, None); assert_eq!(rocksdb_level_file_counts(&raw_engine, CF_WRITE)[6], 1); // So the construction of SST files will be: // L6: |key_140, key_130|, |key_110| - must_prewrite_put(&engine, b"key", b"value", b"key", 120); - must_commit(&engine, b"key", 120, 130); - must_prewrite_delete(&engine, b"key", b"key", 140); - must_commit(&engine, b"key", 140, 140); + must_prewrite_put(&engine, b"zkey", b"zvalue", b"zkey", 120); + must_commit(&engine, b"zkey", 120, 130); + must_prewrite_delete(&engine, b"zkey", b"zkey", 140); + must_commit(&engine, b"zkey", 140, 140); do_gc_by_compact(&raw_engine, None, Some(&split_key), 50, None); assert_eq!(rocksdb_level_file_counts(&raw_engine, CF_WRITE)[6], 2); // Put more key/value pairs so that 1 file in L0 and 1 file in L6 can be merged. - must_prewrite_put(&engine, b"kex", b"value", b"kex", 100); - must_commit(&engine, b"kex", 100, 110); + must_prewrite_put(&engine, b"zkex", b"zvalue", b"zkex", 100); + must_commit(&engine, b"zkex", 100, 110); do_gc_by_compact(&raw_engine, None, Some(&split_key), 200, None); @@ -545,7 +643,7 @@ pub mod tests { // Although the SST files is not involved in the last compaction, // all versions of "key" should be cleared. - let key = Key::from_raw(b"key") + let key = Key::from_raw(b"zkey") .append_ts(TimeStamp::from(110)) .into_encoded(); let x = raw_engine.get_value_cf(CF_WRITE, &key).unwrap(); @@ -561,39 +659,39 @@ pub mod tests { // So the construction of SST files will be: // L6: |AAAAA_101, CCCCC_111| - must_prewrite_put(&engine, b"AAAAA", b"value", b"key", 100); - must_commit(&engine, b"AAAAA", 100, 101); - must_prewrite_put(&engine, b"CCCCC", b"value", b"key", 110); - must_commit(&engine, b"CCCCC", 110, 111); + must_prewrite_put(&engine, b"zAAAAA", b"zvalue", b"zkey", 100); + must_commit(&engine, b"zAAAAA", 100, 101); + must_prewrite_put(&engine, b"zCCCCC", b"zvalue", b"zkey", 110); + must_commit(&engine, b"zCCCCC", 110, 111); do_gc_by_compact(&raw_engine, None, None, 50, Some(6)); assert_eq!(rocksdb_level_file_counts(&raw_engine, CF_WRITE)[6], 1); // So the construction of SST files will be: // L0: |BBBB_101, DDDDD_101| // L6: |AAAAA_101, CCCCC_111| - must_prewrite_put(&engine, b"BBBBB", b"value", b"key", 100); - must_commit(&engine, b"BBBBB", 100, 101); - must_prewrite_put(&engine, b"DDDDD", b"value", b"key", 100); - must_commit(&engine, b"DDDDD", 100, 101); + must_prewrite_put(&engine, b"zBBBBB", b"zvalue", b"zkey", 100); + must_commit(&engine, b"zBBBBB", 100, 101); + must_prewrite_put(&engine, b"zDDDDD", b"zvalue", b"zkey", 100); + must_commit(&engine, b"zDDDDD", 100, 101); raw_engine.flush_cf(CF_WRITE, true).unwrap(); assert_eq!(rocksdb_level_file_counts(&raw_engine, CF_WRITE)[0], 1); // So the construction of SST files will be: // L0: |AAAAA_111, BBBBB_111|, |BBBB_101, DDDDD_101| // L6: |AAAAA_101, CCCCC_111| - must_prewrite_put(&engine, b"AAAAA", b"value", b"key", 110); - must_commit(&engine, b"AAAAA", 110, 111); - must_prewrite_delete(&engine, b"BBBBB", b"BBBBB", 110); - must_commit(&engine, b"BBBBB", 110, 111); + must_prewrite_put(&engine, b"zAAAAA", b"zvalue", b"zkey", 110); + must_commit(&engine, b"zAAAAA", 110, 111); + must_prewrite_delete(&engine, b"zBBBBB", b"zBBBBB", 110); + must_commit(&engine, b"zBBBBB", 110, 111); raw_engine.flush_cf(CF_WRITE, true).unwrap(); assert_eq!(rocksdb_level_file_counts(&raw_engine, CF_WRITE)[0], 2); // Compact |AAAAA_111, BBBBB_111| at L0 and |AAAA_101, CCCCC_111| at L6. - let start = Key::from_raw(b"AAAAA").into_encoded(); - let end = Key::from_raw(b"AAAAAA").into_encoded(); + let start = Key::from_raw(b"zAAAAA").into_encoded(); + let end = Key::from_raw(b"zAAAAAA").into_encoded(); do_gc_by_compact(&raw_engine, Some(&start), Some(&end), 200, Some(6)); - must_get_none(&engine, b"BBBBB", 101); + must_get_none(&engine, b"zBBBBB", 101); } } } diff --git a/src/server/gc_worker/gc_manager.rs b/src/server/gc_worker/gc_manager.rs index db6ae5f4800..8bd10f7fc45 100644 --- a/src/server/gc_worker/gc_manager.rs +++ b/src/server/gc_worker/gc_manager.rs @@ -17,7 +17,7 @@ use super::config::GcWorkerConfigManager; use super::gc_worker::{sync_gc, GcSafePointProvider, GcTask}; use super::{is_compaction_filter_allowd, Result}; -const POLL_SAFE_POINT_INTERVAL_SECS: u64 = 60; +const POLL_SAFE_POINT_INTERVAL_SECS: u64 = 10; const BEGIN_KEY: &[u8] = b""; @@ -425,9 +425,7 @@ impl GcManager { // Records how many region we have GC-ed. let mut processed_regions = 0; - info!( - "gc_worker: start auto gc"; "safe_point" => self.curr_safe_point() - ); + info!("gc_worker: auto gc starts"; "safe_point" => self.curr_safe_point()); // The following loop iterates all regions whose leader is on this TiKV and does GC on them. // At the same time, check whether safe_point is updated periodically. If it's updated, @@ -442,9 +440,7 @@ impl GcManager { // We have worked to the end and we need to rewind. Restart from beginning. progress = Some(Key::from_encoded(BEGIN_KEY.to_vec())); need_rewind = false; - info!( - "gc_worker: auto gc rewinds"; "processed_regions" => processed_regions - ); + info!("gc_worker: auto gc rewinds"; "processed_regions" => processed_regions); processed_regions = 0; // Set the metric to zero to show that rewinding has happened. @@ -465,9 +461,7 @@ impl GcManager { if finished { // We have worked to the end of the TiKV or our progress has reached `end`, and we // don't need to rewind. In this case, the round of GC has finished. - info!( - "gc_worker: finished auto gc"; "processed_regions" => processed_regions - ); + info!("gc_worker: auto gc finishes"; "processed_regions" => processed_regions); return Ok(()); } } diff --git a/src/server/gc_worker/gc_worker.rs b/src/server/gc_worker/gc_worker.rs index 339914f8c88..66ad9a74c8a 100644 --- a/src/server/gc_worker/gc_worker.rs +++ b/src/server/gc_worker/gc_worker.rs @@ -180,7 +180,7 @@ where Some(c) => c, None => return true, }; - check_need_gc(safe_point, self.cfg.ratio_threshold, props) + check_need_gc(safe_point, self.cfg.ratio_threshold, &props) } /// Cleans up outdated data. diff --git a/src/storage/mvcc/reader/reader.rs b/src/storage/mvcc/reader/reader.rs index 684888d31c3..7561bc35994 100644 --- a/src/storage/mvcc/reader/reader.rs +++ b/src/storage/mvcc/reader/reader.rs @@ -430,7 +430,7 @@ impl MvccReader { // Returns true if it needs gc. // This is for optimization purpose, does not mean to be accurate. -pub fn check_need_gc(safe_point: TimeStamp, ratio_threshold: f64, props: MvccProperties) -> bool { +pub fn check_need_gc(safe_point: TimeStamp, ratio_threshold: f64, props: &MvccProperties) -> bool { // Always GC. if ratio_threshold < 1.0 { return true; @@ -747,7 +747,7 @@ mod tests { .c() .get_mvcc_properties_cf(CF_WRITE, safe_point, &start, &end); if let Some(props) = props.as_ref() { - assert_eq!(check_need_gc(safe_point, 1.0, props.clone()), need_gc); + assert_eq!(check_need_gc(safe_point, 1.0, &props), need_gc); } props } diff --git a/src/storage/mvcc/txn.rs b/src/storage/mvcc/txn.rs index 6819790f33e..7ecb26ea7f8 100644 --- a/src/storage/mvcc/txn.rs +++ b/src/storage/mvcc/txn.rs @@ -1062,13 +1062,13 @@ mod tests { fn test_gc_with_compaction_filter() { use crate::server::gc_worker::gc_by_compact; - test_gc_imp(b"k1", b"v1", b"v2", b"v3", b"v4", gc_by_compact); + test_gc_imp(b"zk1", b"v1", b"v2", b"v3", b"v4", gc_by_compact); let v1 = "x".repeat(SHORT_VALUE_MAX_LEN + 1).into_bytes(); let v2 = "y".repeat(SHORT_VALUE_MAX_LEN + 1).into_bytes(); let v3 = "z".repeat(SHORT_VALUE_MAX_LEN + 1).into_bytes(); let v4 = "v".repeat(SHORT_VALUE_MAX_LEN + 1).into_bytes(); - test_gc_imp(b"k2", &v1, &v2, &v3, &v4, gc_by_compact); + test_gc_imp(b"zk2", &v1, &v2, &v3, &v4, gc_by_compact); } fn test_write_imp(k: &[u8], v: &[u8], k2: &[u8]) { diff --git a/src/storage/txn/commands/prewrite.rs b/src/storage/txn/commands/prewrite.rs index 6b390682bc4..50c11a1694b 100644 --- a/src/storage/txn/commands/prewrite.rs +++ b/src/storage/txn/commands/prewrite.rs @@ -459,7 +459,7 @@ mod tests { let pri_key = &[pri_key_number]; for i in 0..40 { mutations.push(Mutation::Insert(( - Key::from_raw(&[i as u8]), + Key::from_raw(&[b'z', i as u8]), b"100".to_vec(), ))); }