From 9d77e24a32e88ed39610e198137f3dd1506d7443 Mon Sep 17 00:00:00 2001 From: jh0 Date: Tue, 27 Jul 2021 15:39:13 +0800 Subject: [PATCH] fix memory leak when unit migrate or del tenant happens --- src/observer/omt/ob_multi_tenant.cpp | 3 +++ .../virtual_table/ob_all_plan_cache_stat.cpp | 2 ++ src/sql/ob_sql.cpp | 2 +- src/sql/plan_cache/ob_cache_object_factory.cpp | 4 +++- src/sql/plan_cache/ob_plan_cache.cpp | 4 +++- src/sql/plan_cache/ob_plan_cache_manager.cpp | 16 +++++++++++++++- src/sql/plan_cache/ob_plan_cache_manager.h | 1 + src/sql/session/ob_sql_session_info.cpp | 2 +- 8 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/observer/omt/ob_multi_tenant.cpp b/src/observer/omt/ob_multi_tenant.cpp index ac37e58da..48619f502 100644 --- a/src/observer/omt/ob_multi_tenant.cpp +++ b/src/observer/omt/ob_multi_tenant.cpp @@ -415,6 +415,9 @@ int ObMultiTenant::add_tenant(const uint64_t tenant_id, const double min_cpu, co OB_FAIL(OTC_MGR.got_version(tenant_id, common::ObSystemConfig::INIT_VERSION))) { LOG_ERROR("failed to got version", K(tenant_id), K(ret)); #endif + } else if (OB_FAIL(GCTX.sql_engine_->get_plan_cache_manager()->validate_plan_cache(tenant_id))) { + // do nothing + LOG_WARN("failed to active plan cache", K(ret), K(tenant_id)); } else { LOG_INFO("activate tenant done", K(tenant_id), K(ret)); } diff --git a/src/observer/virtual_table/ob_all_plan_cache_stat.cpp b/src/observer/virtual_table/ob_all_plan_cache_stat.cpp index 0f03e1379..f89ab0abd 100644 --- a/src/observer/virtual_table/ob_all_plan_cache_stat.cpp +++ b/src/observer/virtual_table/ob_all_plan_cache_stat.cpp @@ -334,6 +334,8 @@ int ObAllPlanCacheStat::get_row_from_tenants() ObPlanCache* plan_cache = pcm_->get_plan_cache(tenant_id); if (OB_UNLIKELY(NULL == plan_cache)) { SERVER_LOG(WARN, "invalid plan cache", K(ret), K(tenant_id)); + } else if (!plan_cache->is_valid()) { + // do nothing } else { if (OB_FAIL(fill_cells(*plan_cache))) { SERVER_LOG(WARN, "fail to fill cells", K(ret), K(cur_row_)); diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 5bf2b1e70..91dffcb5f 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -1,4 +1,4 @@ -/** + /** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. diff --git a/src/sql/plan_cache/ob_cache_object_factory.cpp b/src/sql/plan_cache/ob_cache_object_factory.cpp index 73d140bd6..c0b24e187 100644 --- a/src/sql/plan_cache/ob_cache_object_factory.cpp +++ b/src/sql/plan_cache/ob_cache_object_factory.cpp @@ -106,7 +106,9 @@ int ObCacheObjectFactory::alloc( * then the atomicity of hashmap can ensure that only one thread does the removal action, and * only this thread gets the CacheObject pointer to do subsequent destructuring */ - if (OB_FAIL(plan_cache->get_deleted_map().set_refactored(cache_obj_id, cache_obj))) { + if (!plan_cache->is_valid()) { + // do nothing + } else if (OB_FAIL(plan_cache->get_deleted_map().set_refactored(cache_obj_id, cache_obj))) { LOG_WARN("failed to add element to hashmap", K(ret)); inner_free(cache_obj); cache_obj = NULL; diff --git a/src/sql/plan_cache/ob_plan_cache.cpp b/src/sql/plan_cache/ob_plan_cache.cpp index 914165382..1d8b47ff0 100644 --- a/src/sql/plan_cache/ob_plan_cache.cpp +++ b/src/sql/plan_cache/ob_plan_cache.cpp @@ -1080,7 +1080,9 @@ void ObPlanCache::dec_ref_count() if (ref_count > 0) { } else if (0 == ref_count) { // delete - this->~ObPlanCache(); + this->set_valid(false); + destroy(); + // this->~ObPlanCache(); } else if (ref_count < 0) { BACKTRACE(ERROR, true, "Plan Cache %p ref count < 0, ref_count = %ld", this, ref_count); } diff --git a/src/sql/plan_cache/ob_plan_cache_manager.cpp b/src/sql/plan_cache/ob_plan_cache_manager.cpp index 846ffac74..f413fbab0 100644 --- a/src/sql/plan_cache/ob_plan_cache_manager.cpp +++ b/src/sql/plan_cache/ob_plan_cache_manager.cpp @@ -109,6 +109,20 @@ ObPsCache* ObPlanCacheManager::get_ps_cache(const uint64_t tenant_id) return ps_cache; } +int ObPlanCacheManager::validate_plan_cache(const uint64_t& tenant_id) +{ + int ret = OB_SUCCESS; + + ObPlanCache* plan_cache = get_plan_cache(tenant_id); + if (OB_ISNULL(plan_cache)) { + // do nothing, and others will create this later. + } else { + plan_cache->set_valid(true); + } + + return ret; +} + // maybe get plan_cache = NULL; // this thread other thread // @@ -251,7 +265,7 @@ int ObPlanCacheManager::revert_plan_cache(const uint64_t& tenant_id) int ret = OB_SUCCESS; ObPlanCache* ppc = NULL; observer::ObReqTimeGuard req_timeinfo_guard; - int tmp_ret = pcm_.erase_refactored(tenant_id, &ppc); + int tmp_ret = pcm_.get_refactored(tenant_id, ppc); if (OB_SUCCESS == tmp_ret && NULL != ppc) { SQL_PC_LOG(INFO, "plan_cache_manager revert plan cache", "pc ref_count", ppc->get_ref_count(), K(tenant_id)); // cancel scheduled task diff --git a/src/sql/plan_cache/ob_plan_cache_manager.h b/src/sql/plan_cache/ob_plan_cache_manager.h index 483843ae4..c3db9078b 100644 --- a/src/sql/plan_cache/ob_plan_cache_manager.h +++ b/src/sql/plan_cache/ob_plan_cache_manager.h @@ -82,6 +82,7 @@ public: ObPlanCache* get_or_create_plan_cache(uint64_t tenant_id, const ObPCMemPctConf& pc_mem_conf); ObPsCache* get_or_create_ps_cache(const uint64_t tenant_id, const ObPCMemPctConf& pc_mem_conf); + int validate_plan_cache(const uint64_t& tenant_id); int revert_plan_cache(const uint64_t& tenant_id); int revert_ps_cache(const uint64_t& tenant_id); int flush_all_plan_cache(); diff --git a/src/sql/session/ob_sql_session_info.cpp b/src/sql/session/ob_sql_session_info.cpp index 114479b94..f5c1f286a 100644 --- a/src/sql/session/ob_sql_session_info.cpp +++ b/src/sql/session/ob_sql_session_info.cpp @@ -611,7 +611,7 @@ void ObSQLSessionInfo::get_session_priv_info(share::schema::ObSessionPrivInfo& s ObPlanCache* ObSQLSessionInfo::get_plan_cache() { if (OB_LIKELY(NULL != plan_cache_manager_)) { - if (OB_NOT_NULL(plan_cache_) && plan_cache_->is_valid()) { + if (OB_NOT_NULL(plan_cache_)) { // do nothing } else { // release old plancache and get new