diff --git a/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp b/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp index e6b41e9c96..e3053ed9eb 100755 --- a/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp +++ b/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp @@ -1065,7 +1065,7 @@ void ObTenantMetaMemMgr::release_tx_data_memtable_(ObTxDataMemtable *memtable) { if (OB_NOT_NULL(memtable)) { if (0 != memtable->get_ref()) { - LOG_ERROR_RET(OB_ERR_UNEXPECTED, "ObTxDataMemtable reference count may be leak", KPC(memtable)); + LOG_ERROR_RET(OB_ERR_UNEXPECTED, "ObTxDataMemtable reference count may be leak", KP(memtable)); } else { tx_data_memtable_pool_.release(memtable); } diff --git a/src/storage/tx_table/ob_tx_data_memtable.cpp b/src/storage/tx_table/ob_tx_data_memtable.cpp index 918a85a9b0..f3c5f1eb39 100644 --- a/src/storage/tx_table/ob_tx_data_memtable.cpp +++ b/src/storage/tx_table/ob_tx_data_memtable.cpp @@ -64,6 +64,7 @@ int ObTxDataMemtable::init(const ObITable::TableKey &table_key, min_tx_scn_[i] = SCN::max_scn(); min_start_scn_[i] = SCN::max_scn(); occupied_size_[i] = 0; + total_undo_node_cnt_[i] = 0; } ls_id_ = freezer_->get_ls_id(); construct_list_done_ = false; @@ -126,6 +127,7 @@ void ObTxDataMemtable::reset() min_tx_scn_[i] = SCN::max_scn(); min_start_scn_[i] = SCN::max_scn(); occupied_size_[i] = 0; + total_undo_node_cnt_[i] = 0; } construct_list_done_ = false; pre_process_done_ = false; @@ -182,6 +184,19 @@ int ObTxDataMemtable::insert(ObTxData *tx_data) max_tx_scn_.inc_update(tx_data->end_scn_); atomic_update_(tx_data); ATOMIC_INC(&inserted_cnt_); + if (OB_UNLIKELY(tx_data->undo_status_list_.undo_node_cnt_ >= 10)) { + if (tx_data->undo_status_list_.undo_node_cnt_ == 10 || tx_data->undo_status_list_.undo_node_cnt_ % 100 == 0) { + STORAGE_LOG(INFO, + "attention! this tx write too many rollback to savepoint log", + "ls_id", get_ls_id(), + "tx_id", tx_data->tx_id_, + "state", ObTxData::get_state_string(tx_data->state_), + "undo_node_cnt", tx_data->undo_status_list_.undo_node_cnt_, + "newest_undo_node", tx_data->undo_status_list_.head_, + K(tx_data->start_scn_), + K(tx_data->end_scn_)); + } + } } return ret; @@ -194,6 +209,7 @@ void ObTxDataMemtable::atomic_update_(ObTxData *tx_data) min_start_scn_[thread_idx].dec_update(tx_data->start_scn_); int64_t tx_data_size = TX_DATA_SLICE_SIZE * (1LL + tx_data->undo_status_list_.undo_node_cnt_); ATOMIC_FAA(&occupied_size_[thread_idx], tx_data_size); + ATOMIC_FAA(&total_undo_node_cnt_[thread_idx], tx_data->undo_status_list_.undo_node_cnt_); } int ObTxDataMemtable::get_tx_data(const ObTransID &tx_id, ObTxDataGuard &tx_data_guard) @@ -612,6 +628,15 @@ int64_t ObTxDataMemtable::get_occupied_size() const return res; } +int64_t ObTxDataMemtable::get_total_undo_node_cnt() const +{ + int64_t res = 0; + for (int i = 0; i < MAX_TX_DATA_TABLE_CONCURRENCY; i++) { + res += total_undo_node_cnt_[i]; + } + return res; +} + int ObTxDataMemtable::estimate_phy_size(const ObStoreRowkey *start_key, const ObStoreRowkey *end_key, int64_t &total_bytes, @@ -1061,7 +1086,7 @@ int ObTxDataMemtable::dump2text(const char *fname) fprintf(fd, "tenant_id=%ld ls_id=%ld\n", tenant_id, ls_id); fprintf(fd, "memtable: key=%s is_inited=%d construct_list_done=%d pre_process_done=%d do_recycle_=%d min_tx_log_ts=%s max_tx_log_ts=%s " - "min_start_log_ts=%s inserted_cnt=%ld deleted_cnt=%ld write_ref=%ld occupied_size=%ld last_insert_ts=%ld " + "min_start_log_ts=%s inserted_cnt=%ld deleted_cnt=%ld write_ref=%ld occupied_size=%ld total_undo_node_cnt=%ld last_insert_ts=%ld " "state=%d\n", S(key_), is_inited_, @@ -1075,6 +1100,7 @@ int ObTxDataMemtable::dump2text(const char *fname) deleted_cnt_, write_ref_, get_occupied_size(), + get_total_undo_node_cnt(), last_insert_ts_, state_); fprintf(fd, "tx_data_count=%ld \n", tx_data_map_->count()); diff --git a/src/storage/tx_table/ob_tx_data_memtable.h b/src/storage/tx_table/ob_tx_data_memtable.h index 5fe5dae554..e679c9dbce 100644 --- a/src/storage/tx_table/ob_tx_data_memtable.h +++ b/src/storage/tx_table/ob_tx_data_memtable.h @@ -154,6 +154,7 @@ public: // ObTxDataMemtable deleted_cnt_(0), write_ref_(0), occupied_size_(), + total_undo_node_cnt_(), last_insert_ts_(0), state_(ObTxDataMemtable::State::INVALID), arena_allocator_(), @@ -214,6 +215,7 @@ public: // ObTxDataMemtable int get_iter_start_and_count(const transaction::ObTransID &tx_id, ObTxDataLinkNode *&start_node, int64_t &iterate_row_cnt); share::ObLSID get_ls_id() const; + int64_t get_total_undo_node_cnt() const; /** * @brief dump tx data memtable to file @@ -235,7 +237,8 @@ public: // ObTxDataMemtable K_(inserted_cnt), K_(deleted_cnt), K_(write_ref), - K_(occupied_size), + "occupy_size", get_occupied_size(), + "total_undo_node_cnt", get_total_undo_node_cnt(), K_(state), K_(stat_change_ts), KP_(tx_data_map), @@ -448,6 +451,7 @@ private: // ObTxDataMemtable int64_t write_ref_; int64_t occupied_size_[MAX_TX_DATA_TABLE_CONCURRENCY]; + int64_t total_undo_node_cnt_[MAX_TX_DATA_TABLE_CONCURRENCY]; int64_t last_insert_ts_; StateChangeTime stat_change_ts_;