diff --git a/src/storage/compaction/ob_tenant_tablet_scheduler.cpp b/src/storage/compaction/ob_tenant_tablet_scheduler.cpp index efee1c329..7acedb939 100644 --- a/src/storage/compaction/ob_tenant_tablet_scheduler.cpp +++ b/src/storage/compaction/ob_tenant_tablet_scheduler.cpp @@ -154,6 +154,20 @@ void ObFastFreezeChecker::check_tombstone_need_fast_freeze( try_update_tablet_threshold(ObTabletStatKey(ls_id, tablet_id), mt_stat, memtable.get_timestamp(), adaptive_threshold); need_fast_freeze = (mt_stat.update_row_count_ + mt_stat.delete_row_count_) >= adaptive_threshold; + + if (!need_fast_freeze) { + need_fast_freeze = + // tombstoned row count(empty ObMvccRow) is larger than 1000(hardcoded) + (mt_stat.empty_mvcc_row_count_ >= EMPTY_MVCC_ROW_COUNT) + // tombstoned row precentage(empty ObMvccRow) is larger than 50%(hardcoded) + && (mt_stat.empty_mvcc_row_count_ >= INT64_MAX / 100 // prevent numerical overflow + || mt_stat.empty_mvcc_row_count_ * 100 / memtable.get_physical_row_cnt() + >= EMPTY_MVCC_ROW_PERCENTAGE); + if (need_fast_freeze) { + LOG_INFO("[FastFreeze] trigger by empty mvcc row tombstone", K(memtable), K(mt_stat), + K(memtable.get_physical_row_cnt())); + } + } } } diff --git a/src/storage/compaction/ob_tenant_tablet_scheduler.h b/src/storage/compaction/ob_tenant_tablet_scheduler.h index b8cf85cac..089898489 100644 --- a/src/storage/compaction/ob_tenant_tablet_scheduler.h +++ b/src/storage/compaction/ob_tenant_tablet_scheduler.h @@ -77,6 +77,8 @@ private: static const int64_t FAST_FREEZE_INTERVAL_US = 300 * 1000 * 1000L; //300s static const int64_t PRINT_LOG_INVERVAL = 2 * 60 * 1000 * 1000L; // 2m static const int64_t TOMBSTONE_DEFAULT_ROW_COUNT = 250000; + static const int64_t EMPTY_MVCC_ROW_COUNT = 1000; + static const int64_t EMPTY_MVCC_ROW_PERCENTAGE = 50; static const int64_t TOMBSTONE_MAX_ROW_COUNT = 500000; static const int64_t TOMBSTONE_STEP_ROW_COUNT = 50000; static const int64_t FAST_FREEZE_TABLET_STAT_KEY_BUCKET_NUM = OB_MAX_LS_NUM_PER_TENANT_PER_SERVER * 1024; diff --git a/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.cpp b/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.cpp index f2d2b38df..87699e09e 100644 --- a/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.cpp +++ b/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.cpp @@ -1939,6 +1939,13 @@ int ObMvccRowCallback::trans_abort() ObRowLatchGuard guard(value_.latch_); if (NULL != tnode_) { + if (NULL == tnode_->prev_ && NULL == tnode_->next_) { + // If after the abort, the ObMvccRow is empty, we recorded it for later + // possible fast freeze. You can read check_tombstone_need_fast_freeze for + // detailed strategy. + memtable_->get_mt_stat().empty_mvcc_row_count_++; + } + if (!(tnode_->is_committed() || tnode_->is_aborted())) { tnode_->trans_abort(ctx_.get_tx_end_scn()); wakeup_row_waiter_if_need_(); diff --git a/src/storage/memtable/ob_memtable.h b/src/storage/memtable/ob_memtable.h index 071a66230..8affcb838 100644 --- a/src/storage/memtable/ob_memtable.h +++ b/src/storage/memtable/ob_memtable.h @@ -62,12 +62,20 @@ struct ObMtStat ObMtStat() { reset(); } ~ObMtStat() = default; void reset() { memset(this, 0, sizeof(*this));} - TO_STRING_KV(K_(insert_row_count), K_(update_row_count), K_(delete_row_count), - K_(frozen_time), K_(ready_for_flush_time), K_(create_flush_dag_time), - K_(release_time), K_(last_print_time), K_(row_size)); + TO_STRING_KV(K_(insert_row_count), + K_(update_row_count), + K_(delete_row_count), + K_(empty_mvcc_row_count), + K_(frozen_time), + K_(ready_for_flush_time), + K_(create_flush_dag_time), + K_(release_time), + K_(last_print_time), + K_(row_size)); int64_t insert_row_count_; int64_t update_row_count_; int64_t delete_row_count_; + int64_t empty_mvcc_row_count_; int64_t frozen_time_; int64_t ready_for_flush_time_; int64_t create_flush_dag_time_; @@ -396,6 +404,7 @@ public: int set_freezer(storage::ObFreezer *handler); storage::ObFreezer *get_freezer() { return freezer_; } int get_ls_id(share::ObLSID &ls_id); + ObLSHandle &get_ls_handle() { return ls_handle_; } int set_memtable_mgr_(storage::ObTabletMemtableMgr *mgr); storage::ObTabletMemtableMgr *get_memtable_mgr_(); void set_freeze_clock(const uint32_t freeze_clock) { ATOMIC_STORE(&freeze_clock_, freeze_clock); }