diff --git a/deps/oblib/src/lib/CMakeLists.txt b/deps/oblib/src/lib/CMakeLists.txt index bed3e32c78..98535f801b 100644 --- a/deps/oblib/src/lib/CMakeLists.txt +++ b/deps/oblib/src/lib/CMakeLists.txt @@ -319,6 +319,7 @@ ob_set_subtarget(ob_malloc_object_list common_alloc allocator/ob_mod_define.cpp allocator/ob_page_manager.cpp allocator/ob_slice_alloc.cpp + allocator/ob_sql_mem_leak_checker.cpp allocator/ob_tc_malloc.cpp ) diff --git a/deps/oblib/src/lib/alloc/alloc_struct.cpp b/deps/oblib/src/lib/alloc/alloc_struct.cpp index d3a8aa70ce..6966eceea7 100644 --- a/deps/oblib/src/lib/alloc/alloc_struct.cpp +++ b/deps/oblib/src/lib/alloc/alloc_struct.cpp @@ -24,13 +24,16 @@ using namespace common; namespace lib { - thread_local ObMemAttr ObMallocHookAttrGuard::tl_mem_attr(OB_SERVER_TENANT_ID, "glibc_malloc", ObCtxIds::GLIBC); static int64_t g_divisive_mem_size[OB_MAX_CPU_NUM]; static thread_local bool g_is_ob_mem_mgr_path = false; +uint32_t ObMemVersionNode::global_version = 0; +__thread bool ObMemVersionNode::tl_ignore_node = true; +__thread ObMemVersionNode* ObMemVersionNode::tl_node = NULL; + ObMallocHookAttrGuard::ObMallocHookAttrGuard(const ObMemAttr& attr) : old_attr_(tl_mem_attr) { diff --git a/deps/oblib/src/lib/alloc/alloc_struct.h b/deps/oblib/src/lib/alloc/alloc_struct.h index 07d0755ceb..c764092ce5 100644 --- a/deps/oblib/src/lib/alloc/alloc_struct.h +++ b/deps/oblib/src/lib/alloc/alloc_struct.h @@ -23,6 +23,7 @@ #include "lib/alloc/alloc_assist.h" #include "lib/alloc/abit_set.h" #include "lib/allocator/ob_mod_define.h" +#include "lib/list/ob_dlink_node.h" #ifndef NDEBUG #define MEMCHK_LEVEL 1 @@ -119,15 +120,24 @@ struct ObLabel const char *str_; }; +struct ObMemVersionNode : public ObDLinkBase +{ + static uint32_t global_version; + static __thread bool tl_ignore_node; + static __thread ObMemVersionNode* tl_node; + uint32_t version_ = UINT32_MAX; +}; + struct ObMemAttr { - friend ObMemAttr DoNotUseMe(ObMemAttr &attr, bool expect_500); + friend ObMemAttr DoNotUseMe(ObMemAttr &attr); + friend ObMemAttr UseUnexpected500(ObMemAttr &attr); + friend ObMemAttr IgnoreVersion(ObMemAttr &attr); uint64_t tenant_id_; ObLabel label_; uint64_t ctx_id_; uint64_t sub_ctx_id_; ObAllocPrio prio_; - explicit ObMemAttr( uint64_t tenant_id = common::OB_SERVER_TENANT_ID, ObLabel label = ObLabel(), @@ -137,42 +147,73 @@ struct ObMemAttr label_(label), ctx_id_(ctx_id), sub_ctx_id_(ObSubCtxIds::MAX_SUB_CTX_ID), - prio_(prio) {} + prio_(prio), + use_500_(false), + expect_500_(true), + ignore_version_(ObMemVersionNode::tl_ignore_node) + {} int64_t to_string(char* buf, const int64_t buf_len) const; bool use_500() const { return use_500_; } bool expect_500() const { return expect_500_; } + bool ignore_version() const { return ignore_version_; } private: - bool use_500_ = false; - bool expect_500_ = true; + union { + char padding__[4]; + struct { + struct { + uint8_t use_500_ : 1; + uint8_t expect_500_ : 1; + uint8_t ignore_version_ : 1; + }; + }; + }; }; -inline ObMemAttr DoNotUseMe(ObMemAttr &attr, bool expect_500) +inline ObMemAttr DoNotUseMe(ObMemAttr &attr) { attr.use_500_ = true; - attr.expect_500_ = expect_500; + attr.ignore_version_ = true; return attr; } -inline ObMemAttr DoNotUseMe(const ObMemAttr &&attr, const bool expect_500) +inline ObMemAttr UseUnexpected500(ObMemAttr &attr) { - ObMemAttr attr_cpy = attr; - return DoNotUseMe(attr_cpy, expect_500); + attr.use_500_ = true; + attr.expect_500_ = false; + attr.ignore_version_ = true; + return attr; } -inline ObMemAttr DoNotUseMe(const ObLabel &label, const bool expect_500) +inline ObMemAttr IgnoreVersion(ObMemAttr &attr) { - ObMemAttr attr(OB_SERVER_TENANT_ID, label); - return DoNotUseMe(attr, expect_500); + attr.ignore_version_ = true; + return attr; } -inline ObMemAttr DoNotUseMe(const ObLabel &label, const uint64_t ctx_id, const bool expect_500) -{ - ObMemAttr attr(OB_SERVER_TENANT_ID, label, ctx_id); - return DoNotUseMe(attr, expect_500); -} +#define ObMemAttrFriendFunc(func_name) \ + inline ObMemAttr func_name(const ObMemAttr &&attr) \ + { \ + ObMemAttr attr_cpy = attr; \ + return func_name(attr_cpy); \ + } \ + inline ObMemAttr func_name(const ObLabel &label) \ + { \ + ObMemAttr attr(OB_SERVER_TENANT_ID, label); \ + return func_name(attr); \ + } \ + inline ObMemAttr func_name(const ObLabel &label, const uint64_t ctx_id) \ + { \ + ObMemAttr attr(OB_SERVER_TENANT_ID, label, ctx_id); \ + return func_name(attr); \ + } -#define SET_USE_500(args...) ::oceanbase::lib::DoNotUseMe(args, true) -#define SET_USE_UNEXPECTED_500(args...) ::oceanbase::lib::DoNotUseMe(args, false) +ObMemAttrFriendFunc(DoNotUseMe); +ObMemAttrFriendFunc(UseUnexpected500); +ObMemAttrFriendFunc(IgnoreVersion); + +#define SET_USE_500(args...) ::oceanbase::lib::DoNotUseMe(args) +#define SET_USE_UNEXPECTED_500(args...) ::oceanbase::lib::UseUnexpected500(args) +#define SET_IGNORE_MEM_VERSION(args...) ::oceanbase::lib::IgnoreVersion(args) struct AllocHelper { @@ -274,16 +315,18 @@ struct AObject { uint16_t obj_offset_; uint32_t alloc_bytes_; - uint64_t tenant_id_; + uint32_t version_; char label_[AOBJECT_LABEL_SIZE + 1]; // padding to ensure data_ is 16x offset union { - char padding__[4]; + char padding__[16]; struct { struct { uint8_t on_leak_check_ : 1; uint8_t on_malloc_sample_ : 1; + uint8_t ignore_version_ : 1; + }; }; }; @@ -522,8 +565,7 @@ char *ABlock::data() const AObject::AObject() : MAGIC_CODE_(FREE_AOBJECT_MAGIC_CODE), nobjs_(0), nobjs_prev_(0), obj_offset_(0), - alloc_bytes_(0), tenant_id_(0), - on_leak_check_(false), on_malloc_sample_(false) + alloc_bytes_(0), on_leak_check_(false), on_malloc_sample_(false) { } diff --git a/deps/oblib/src/lib/alloc/memory_dump.cpp b/deps/oblib/src/lib/alloc/memory_dump.cpp index eb16ad6c38..55ecafae66 100644 --- a/deps/oblib/src/lib/alloc/memory_dump.cpp +++ b/deps/oblib/src/lib/alloc/memory_dump.cpp @@ -14,7 +14,7 @@ #include "lib/alloc/memory_dump.h" #include -#include "lib/alloc/ob_free_log_printer.h" +#include "lib/allocator/ob_sql_mem_leak_checker.h" #include "lib/signal/ob_signal_struct.h" #include "lib/rc/context.h" #include "lib/utility/utility.h" @@ -205,6 +205,45 @@ int ObMemoryDump::push(void *task) return ret; } +int ObMemoryDump::generate_mod_stat_task(ObMemoryCheckContext *memory_check_ctx) +{ + int ret = OB_SUCCESS; + ObMemoryDumpTask *task = alloc_task(); + if (OB_ISNULL(task)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc task failed"); + } else { + task->type_ = STAT_LABEL; + task->memory_check_ctx_ = memory_check_ctx; + COMMON_LOG(INFO, "task info", K(*task)); + if (OB_FAIL(push(task))) { + LOG_WARN("push task failed", K(ret)); + free_task(task); + } + } + return ret; +} + +int ObMemoryDump::check_sql_memory_leak() +{ + int ret = OB_SUCCESS; + ObMemoryCheckContext memory_check_ctx; + ObThreadCond &cond = memory_check_ctx.cond_; + if (OB_FAIL(cond.init(ObWaitEventIds::DEFAULT_COND_WAIT))) { + LOG_WARN("thread cond init failed", K(ret)); + } else if (OB_FAIL(generate_mod_stat_task(&memory_check_ctx))) { + LOG_WARN("generate mod stat task", K(ret)); + } else { + ObThreadCondGuard guard(cond); + if (OB_FAIL(cond.wait())) { + LOG_WARN("thread condition wait failed", K(ret)); + } else { + ret = memory_check_ctx.ret_; + } + } + return ret; +} + int ObMemoryDump::load_malloc_sample_map(ObMallocSampleMap &malloc_sample_map) { int ret = OB_SUCCESS; @@ -231,19 +270,10 @@ void ObMemoryDump::run1() } else if (OB_ENTRY_NOT_EXIST == ret) { int64_t current_ts = common::ObClockGenerator::getClock(); if (current_ts - last_dump_ts > STAT_LABEL_INTERVAL) { - auto *task = alloc_task(); - if (OB_ISNULL(task)) { - LOG_WARN("alloc task failed"); - } else { - task->type_ = STAT_LABEL; - if (OB_FAIL(push(task))){ - LOG_WARN("push task failed", K(ret)); - free_task(task); - } - } + generate_mod_stat_task(); last_dump_ts = current_ts; } else { - ob_usleep(current_ts - last_dump_ts); + ob_usleep(1000); } } } @@ -485,6 +515,13 @@ void ObMemoryDump::handle(void *task) "tenant_id", "ctx_id", "chunk_cnt", "label_cnt", "segv_cnt"); const int64_t start_ts = ObTimeUtility::current_time(); + static bool has_memory_leak = false; + // sql memory leak can diagnose the memleak of object whose mem_version belongs to [min_check_version, max_check_version). + uint32_t min_check_version; + uint32_t max_check_version; + ObMemoryCheckContext *memory_check_ctx = m_task->memory_check_ctx_; + ObSqlMemoryLeakChecker::get_instance().update_check_range(NULL == memory_check_ctx || !memory_check_ctx->is_sql_memory_leak(), + min_check_version, max_check_version); for (int tenant_idx = 0; tenant_idx < tenant_cnt; tenant_idx++) { uint64_t tenant_id = tenant_ids_[tenant_idx]; for (int ctx_id = 0; ctx_id < ObCtxIds::MAX_CTX_ID; ctx_id++) { @@ -517,28 +554,28 @@ void ObMemoryDump::handle(void *task) UNUSEDx(chunk, block); return OB_SUCCESS; }, - [tenant_id, ctx_id, &lmap, w_stat, &item_used] + [tenant_id, ctx_id, &lmap, w_stat, &item_used, min_check_version, max_check_version] (AChunk *chunk, ABlock *block, AObject *object) { int ret = OB_SUCCESS; if (object->in_use_) { - bool expect = AOBJECT_TAIL_MAGIC_CODE == - reinterpret_cast(object->data_[object->alloc_bytes_]); - if (!expect && object->is_valid() && object->in_use_ - && REACH_TIME_INTERVAL(1 * 1000 * 1000)) { - ObLabel label = object->label(); - char *ptr = object->data_; - int32_t length = object->alloc_bytes_; - LOG_INFO("tail magic maybe broken!!!", K(tenant_id), KP(ptr), - K(length), K(label)); + if (OB_FAIL(label_stat(chunk, block, object, lmap, w_stat->up2date_items_, + ARRAYSIZEOF(w_stat->up2date_items_), item_used))) { + // do-nothing + } else if (OB_FAIL(malloc_sample_stat(tenant_id, ctx_id, object, + w_stat->malloc_sample_map_))) { + // do-nothing + } else if (!object->ignore_version_ && + object->version_ >= min_check_version && + object->version_ < max_check_version) { + has_memory_leak = true; + char bt[MAX_BACKTRACE_LENGTH] = {'\0'}; + if (object->on_malloc_sample_) { + parray(bt, sizeof(bt), (int64_t*)&object->data_[object->alloc_bytes_ - AOBJECT_BACKTRACE_SIZE], AOBJECT_BACKTRACE_COUNT); + } + allow_next_syslog(); + LOG_WARN("SQL_MEMORY_LEAK", KP(object), K(tenant_id), K(ctx_id), K(object->version_), K(object->label_), K(bt)); } } - ret = label_stat(chunk, block, object, lmap, - w_stat->up2date_items_, ARRAYSIZEOF(w_stat->up2date_items_), - item_used); - if (OB_SUCC(ret)) { - ret = malloc_sample_stat(tenant_id, ctx_id, - object, w_stat->malloc_sample_map_); - } return ret; }); if (OB_FAIL(ret)) { @@ -593,7 +630,17 @@ void ObMemoryDump::handle(void *task) ObLatchWGuard guard(iter_lock_, common::ObLatchIds::MEM_DUMP_ITER_LOCK); std::swap(r_stat_, w_stat_); } - ObFreeLogPrinter::get_instance().disable_free_log(); + if (NULL != memory_check_ctx) { + if (memory_check_ctx->is_sql_memory_leak() && has_memory_leak) { + memory_check_ctx->ret_ = OB_ERR_UNEXPECTED; + has_memory_leak = false; + LOG_WARN("there has sql memory leak"); + } + if (OB_FAIL(memory_check_ctx->cond_.signal())) { + LOG_WARN("failed to signal condition", K(ret)); + } + memory_check_ctx = NULL; + } } else { int fd = -1; if (-1 == (fd = ::open(LOG_FILE, diff --git a/deps/oblib/src/lib/alloc/memory_dump.h b/deps/oblib/src/lib/alloc/memory_dump.h index b75423c678..7b1b9c25bd 100644 --- a/deps/oblib/src/lib/alloc/memory_dump.h +++ b/deps/oblib/src/lib/alloc/memory_dump.h @@ -45,6 +45,21 @@ enum DumpType STAT_LABEL }; +struct ObMemoryCheckContext +{ + enum CheckType + { + SQL_MEMORY_LEAK, + }; + ObMemoryCheckContext(CheckType type = SQL_MEMORY_LEAK) + : ret_(OB_SUCCESS), type_(type), cond_() + {} + bool is_sql_memory_leak() { return SQL_MEMORY_LEAK == type_; } + int ret_; + CheckType type_; + ObThreadCond cond_; +}; + class ObMemoryDumpTask { public: @@ -68,6 +83,9 @@ public: void *p_chunk_; }; }; + struct { + ObMemoryCheckContext *memory_check_ctx_; + }; }; }; @@ -189,6 +207,8 @@ public: lib::ObMutexGuard guard(task_mutex_); avaliable_task_set_ |= (1 << pos); } + int generate_mod_stat_task(ObMemoryCheckContext *memory_check_ctx = NULL); + int check_sql_memory_leak(); int load_malloc_sample_map(lib::ObMallocSampleMap& malloc_sample_map); private: void run1() override; diff --git a/deps/oblib/src/lib/alloc/ob_tenant_ctx_allocator.cpp b/deps/oblib/src/lib/alloc/ob_tenant_ctx_allocator.cpp index f44ae15190..1f2ebc14b7 100644 --- a/deps/oblib/src/lib/alloc/ob_tenant_ctx_allocator.cpp +++ b/deps/oblib/src/lib/alloc/ob_tenant_ctx_allocator.cpp @@ -460,6 +460,10 @@ void* ObTenantCtxAllocator::common_realloc(const void *ptr, const int64_t size, if (obj != NULL) { obj->on_malloc_sample_ = sample_allowed; ob_malloc_sample_backtrace(obj, size); + obj->ignore_version_ = attr.ignore_version() || ObMemVersionNode::tl_ignore_node; + if (!obj->ignore_version_) { + obj->version_ = ObMemVersionNode::tl_node->version_; + } nptr = obj->data_; get_mem_leak_checker().on_alloc(*obj, attr); SANITY_POISON(obj, AOBJECT_HEADER_SIZE); @@ -467,9 +471,6 @@ void* ObTenantCtxAllocator::common_realloc(const void *ptr, const int64_t size, SANITY_POISON((void*)upper_align((int64_t)obj->data_ + size, 8), alloc_size - size + sizeof(AOBJECT_TAIL_MAGIC_CODE)); } else if (TC_REACH_TIME_INTERVAL(1 * 1000 * 1000)) { - int level = ObFreeLogPrinter::get_level(); - ObFreeLogPrinter::get_instance().enable_free_log(attr.tenant_id_, - attr.ctx_id_, level); const char *msg = is_errsim ? "[ERRSIM] errsim inject memory error" : alloc_failed_msg(); LOG_DBA_WARN(OB_ALLOCATE_MEMORY_FAILED, "[OOPS]", "alloc failed reason", KCSTRING(msg)); _OB_LOG_RET(WARN, OB_ALLOCATE_MEMORY_FAILED, "oops, alloc failed, tenant_id=%ld, ctx_id=%ld, ctx_name=%s, ctx_hold=%ld, " diff --git a/deps/oblib/src/lib/alloc/object_mgr.cpp b/deps/oblib/src/lib/alloc/object_mgr.cpp index 91336b0da3..e0bea0e532 100644 --- a/deps/oblib/src/lib/alloc/object_mgr.cpp +++ b/deps/oblib/src/lib/alloc/object_mgr.cpp @@ -247,6 +247,7 @@ SubObjectMgr *ObjectMgr::create_sub_mgr() auto *obj = root_mgr.alloc_object(sizeof(SubObjectMgr), attr); root_mgr.unlock(); if (OB_NOT_NULL(obj)) { + obj->ignore_version_ = true; SANITY_UNPOISON(obj->data_, obj->alloc_bytes_); sub_mgr = new (obj->data_) SubObjectMgr(ta_, enable_no_log_, diff --git a/deps/oblib/src/lib/alloc/object_set.cpp b/deps/oblib/src/lib/alloc/object_set.cpp index e69b55c941..52bca3f23c 100644 --- a/deps/oblib/src/lib/alloc/object_set.cpp +++ b/deps/oblib/src/lib/alloc/object_set.cpp @@ -84,10 +84,8 @@ AObject *ObjectSet::alloc_object( if (NULL != obj) { abort_unless(obj->in_use_); abort_unless(obj->is_valid()); - reinterpret_cast(obj->data_[size]) = AOBJECT_TAIL_MAGIC_CODE; obj->alloc_bytes_ = static_cast(size); - if (attr.label_.str_ != nullptr) { STRNCPY(&obj->label_[0], attr.label_.str_, sizeof(obj->label_)); obj->label_[sizeof(obj->label_) - 1] = '\0'; diff --git a/deps/oblib/src/lib/allocator/ob_sql_mem_leak_checker.cpp b/deps/oblib/src/lib/allocator/ob_sql_mem_leak_checker.cpp new file mode 100644 index 0000000000..ac8daa62ac --- /dev/null +++ b/deps/oblib/src/lib/allocator/ob_sql_mem_leak_checker.cpp @@ -0,0 +1,66 @@ +/** + * 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. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_sql_mem_leak_checker.h" + +namespace oceanbase +{ +using namespace lib; +namespace common +{ +ObSqlMemoryLeakChecker &ObSqlMemoryLeakChecker::get_instance() +{ + static ObSqlMemoryLeakChecker instance; + return instance; +} + +void ObSqlMemoryLeakChecker::add(ObMemVersionNode &node) +{ + lib::ObMutexGuard guard(lock_); + dlist_.add_first(&node); +} + +void ObSqlMemoryLeakChecker::remove(ObMemVersionNode &node) +{ + lib::ObMutexGuard guard(lock_); + dlist_.remove(&node); +} + +uint32_t ObSqlMemoryLeakChecker::get_min_version() +{ + uint32_t version = UINT32_MAX; + ObMutexGuard guard(lock_); + DLIST_FOREACH_NORET(node, dlist_) { + if (node->version_ < version) { + version = node->version_; + } + } + return version; +} + +void ObSqlMemoryLeakChecker::update_check_range(const bool need_delay, + uint32_t &min_check_version, + uint32_t &max_check_version) +{ + uint32_t global_version = ATOMIC_AAF(&ObMemVersionNode::global_version, 1); + min_check_version = min_check_version_; + max_check_version = max_check_version_; + max_check_version_ = std::min(get_min_version(), global_version); + if (!need_delay) { + max_check_version = max_check_version_; + } + min_check_version_ = max_check_version; + COMMON_LOG(INFO, "update_check_range", K(min_check_version), K(max_check_version), K(global_version)); +} + +} // end namespace common +} // end namespace oceanbase \ No newline at end of file diff --git a/deps/oblib/src/lib/allocator/ob_sql_mem_leak_checker.h b/deps/oblib/src/lib/allocator/ob_sql_mem_leak_checker.h new file mode 100644 index 0000000000..8ec9736f12 --- /dev/null +++ b/deps/oblib/src/lib/allocator/ob_sql_mem_leak_checker.h @@ -0,0 +1,89 @@ +/** + * 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. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_SQL_MEM_LEAK_CHECKER_H_ +#define OCEANBASE_SQL_MEM_LEAK_CHECKER_H_ + +#include "lib/lock/ob_mutex.h" +#include "lib/alloc/alloc_struct.h" +namespace oceanbase +{ +namespace common +{ + +class ObSqlMemoryLeakChecker +{ +public: + ObSqlMemoryLeakChecker() + : lock_(), dlist_() + {} + static ObSqlMemoryLeakChecker &get_instance(); + void add(lib::ObMemVersionNode &node); + void remove(lib::ObMemVersionNode &node); + uint32_t get_min_version(); + void update_check_range(const bool need_delay, + uint32_t &min_check_version, + uint32_t &max_check_version); +private: + uint32_t min_check_version_; + uint32_t max_check_version_; + lib::ObMutex lock_; + ObDList dlist_; +}; + +struct ObMemVersionNodeGuard +{ +public: + ObMemVersionNodeGuard() + { + lib::ObMemVersionNode::tl_node = &node_; + ObSqlMemoryLeakChecker::get_instance().add(node_); + } + ~ObMemVersionNodeGuard() + { + lib::ObMemVersionNode::tl_node = NULL; + ObSqlMemoryLeakChecker::get_instance().remove(node_); + } +private: + lib::ObMemVersionNode node_; +}; + +struct ObSqlMemoryLeakGuard +{ +public: + ObSqlMemoryLeakGuard(const bool enable_memory_leak) + : enable_memory_leak_(enable_memory_leak && NULL != lib::ObMemVersionNode::tl_node), + ignore_node_(lib::ObMemVersionNode::tl_ignore_node) + { + lib::ObMemVersionNode::tl_ignore_node = !enable_memory_leak_; + if (enable_memory_leak) { + version_ = lib::ObMemVersionNode::tl_node->version_; + lib::ObMemVersionNode::tl_node->version_ = ATOMIC_LOAD(&lib::ObMemVersionNode::global_version); + } + } + ~ObSqlMemoryLeakGuard() + { + lib::ObMemVersionNode::tl_ignore_node = ignore_node_; + if (enable_memory_leak_) { + lib::ObMemVersionNode::tl_node->version_ = version_; + } + } +private: + bool enable_memory_leak_; + bool ignore_node_; + uint32_t version_; +}; +#define DISABLE_SQL_MEMLEAK_GUARD ::oceanbase::common::ObSqlMemoryLeakGuard sql_memory_leak_guard(false); +#define ENABLE_SQL_MEMLEAK_GUARD ::oceanbase::common::ObSqlMemoryLeakGuard sql_memory_leak_guard(true); +} // end namespace common +} // end namespace oceanbase +#endif \ No newline at end of file diff --git a/deps/oblib/src/lib/hash/ob_linear_hash_map.h b/deps/oblib/src/lib/hash/ob_linear_hash_map.h index d09a8a0ee4..cc5f7cd463 100644 --- a/deps/oblib/src/lib/hash/ob_linear_hash_map.h +++ b/deps/oblib/src/lib/hash/ob_linear_hash_map.h @@ -642,6 +642,7 @@ int ObLinearHashMap::HashMapMemMgrCore::init(const int64_ int ret = OB_SUCCESS; dir_alloc_.set_attr(ObMemAttr(tenant_id, "LinearHashMapDi")); cnter_alloc_.set_attr(ObMemAttr(tenant_id, "LinearHashMapCn")); + map_array_.set_attr(SET_USE_500("HashMapArray")); // Init node alloc. ret = node_alloc_.init(static_cast(sizeof(Node)), SET_USE_500(ObMemAttr(tenant_id, "LinearHashMapNo"))); diff --git a/deps/oblib/src/lib/mysqlclient/ob_connection_allocator.h b/deps/oblib/src/lib/mysqlclient/ob_connection_allocator.h index 51177d92ff..8b2499d65a 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_connection_allocator.h +++ b/deps/oblib/src/lib/mysqlclient/ob_connection_allocator.h @@ -350,7 +350,7 @@ int ObLruConnectionAllocator::init() int ret = OB_SUCCESS; if (is_inited_) { // do nothing - } else if (OB_FAIL(sessionid_to_conns_map_.create(HASH_BUCKET_NUM, "sessid_conn_map"))) { + } else if (OB_FAIL(sessionid_to_conns_map_.create(HASH_BUCKET_NUM, SET_IGNORE_MEM_VERSION("sessid_conn_map")))) { _OB_LOG(WARN, "failed to init hashmap sessionid_to_conns_map_, ret=%d", ret); } else { is_inited_ = true; diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp index e23a1f1092..69afe27331 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp @@ -461,6 +461,7 @@ int ObDbLinkProxy::create_dblink_pool(const dblink_param_ctx ¶m_ctx, const O int ObDbLinkProxy::acquire_dblink(const dblink_param_ctx ¶m_ctx, ObISQLConnection *&dblink_conn) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObISQLConnectionPool *dblink_pool = NULL; if (!is_inited()) { ret = OB_NOT_INIT; @@ -579,6 +580,7 @@ int ObDbLinkProxy::execute_init_sql(const sqlclient::dblink_param_ctx ¶m_ctx int ObDbLinkProxy::release_dblink(/*uint64_t dblink_id,*/ DblinkDriverProto dblink_type, ObISQLConnection *dblink_conn) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObISQLConnectionPool *dblink_pool = NULL; if (!is_inited()) { ret = OB_NOT_INIT; diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h index 17faad50a0..c614fd5b71 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h @@ -13,6 +13,7 @@ #ifndef OCEANBASE_MYSQL_PROXY_H_ #define OCEANBASE_MYSQL_PROXY_H_ +#include "lib/allocator/ob_sql_mem_leak_checker.h" #include "lib/mysqlclient/ob_isql_client.h" #include "lib/mysqlclient/ob_mysql_result.h" #include "lib/mysqlclient/ob_mysql_statement.h" diff --git a/deps/oblib/src/rpc/obrpc/ob_rpc_mem_pool.cpp b/deps/oblib/src/rpc/obrpc/ob_rpc_mem_pool.cpp index da2ae61746..b988ddb1b2 100644 --- a/deps/oblib/src/rpc/obrpc/ob_rpc_mem_pool.cpp +++ b/deps/oblib/src/rpc/obrpc/ob_rpc_mem_pool.cpp @@ -42,6 +42,7 @@ static void* rpc_mem_pool_direct_alloc(int64_t tenant_id, const char* label, int tenant_id = OB_SERVER_TENANT_ID; } ObMemAttr attr(tenant_id, label, common::ObCtxIds::RPC_CTX_ID); + SET_IGNORE_MEM_VERSION(attr); lib::ObTenantCtxAllocatorGuard allocator = lib::ObMallocAllocator::get_instance()->get_tenant_ctx_allocator(tenant_id, common::ObCtxIds::RPC_CTX_ID); if (OB_ISNULL(allocator)) { attr.tenant_id_ = OB_SERVER_TENANT_ID; diff --git a/src/observer/mysql/obmp_query.cpp b/src/observer/mysql/obmp_query.cpp index 6f19dab61f..2f5ff68497 100644 --- a/src/observer/mysql/obmp_query.cpp +++ b/src/observer/mysql/obmp_query.cpp @@ -14,6 +14,7 @@ #include "observer/mysql/obmp_query.h" +#include "lib/allocator/ob_sql_mem_leak_checker.h" #include "lib/utility/ob_macro_utils.h" #include "lib/utility/ob_tracepoint.h" #include "lib/worker.h" @@ -1269,6 +1270,7 @@ OB_INLINE int ObMPQuery::response_result(ObMySQLResultSet &result, // 通过判断 plan 是否为 null 来确定是 plan 还是 cmd // 针对 plan 和 cmd 分开处理,逻辑会较为清晰。 if (OB_LIKELY(NULL != result.get_physical_plan())) { + ENABLE_SQL_MEMLEAK_GUARD; if (need_trans_cb) { ObAsyncPlanDriver drv(gctx_, ctx_, session, retry_ctrl_, *this); // NOTE: sql_end_cb必须在drv.response_result()之前初始化好 diff --git a/src/observer/ob_dump_task_generator.cpp b/src/observer/ob_dump_task_generator.cpp index bd6cd97a93..5ca274f525 100644 --- a/src/observer/ob_dump_task_generator.cpp +++ b/src/observer/ob_dump_task_generator.cpp @@ -143,21 +143,7 @@ int ObDumpTaskGenerator::generate_task_from_file() int ObDumpTaskGenerator::generate_mod_stat_task() { - int ret = OB_SUCCESS; - auto &mem_dump = ObMemoryDump::get_instance(); - ObMemoryDumpTask *task = mem_dump.alloc_task(); - if (OB_ISNULL(task)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("alloc task failed"); - } else { - task->type_ = STAT_LABEL; - COMMON_LOG(INFO, "task info", K(*task)); - if (OB_FAIL(mem_dump.push(task))) { - LOG_WARN("push task failed", K(ret)); - mem_dump.free_task(task); - } - } - return ret; + return ObMemoryDump::get_instance().generate_mod_stat_task(); } void ObDumpTaskGenerator::dump_memory_leak() diff --git a/src/observer/ob_inner_sql_connection.cpp b/src/observer/ob_inner_sql_connection.cpp index 9323da3792..54a96fbac1 100644 --- a/src/observer/ob_inner_sql_connection.cpp +++ b/src/observer/ob_inner_sql_connection.cpp @@ -914,6 +914,7 @@ template int ObInnerSQLConnection::retry_while_no_tenant_resource(const int64_t cluster_id, const uint64_t &tenant_id, T function) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; share::ObLSID ls_id(share::ObLSID::SYS_LS_ID); const int64_t max_retry_us = 128 * 1000; int64_t retry_us = 2 * 1000; @@ -1827,6 +1828,7 @@ int ObInnerSQLConnection::execute( const uint64_t tenant_id, sqlclient::ObIExecutor &executor) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; FLTSpanGuard(inner_execute); SMART_VAR(ObInnerSQLResult, res, get_session()) { if (OB_FAIL(res.init())) { diff --git a/src/observer/ob_service.cpp b/src/observer/ob_service.cpp index 3cb8ad87a1..671b882d1f 100644 --- a/src/observer/ob_service.cpp +++ b/src/observer/ob_service.cpp @@ -25,6 +25,7 @@ #include "lib/thread_local/ob_tsi_factory.h" #include "lib/utility/utility.h" #include "lib/time/ob_tsc_timestamp.h" +#include "lib/alloc/memory_dump.h" #include "common/ob_member_list.h" #include "common/ob_zone.h" @@ -2423,7 +2424,12 @@ int ObService::get_wrs_info(const obrpc::ObGetWRSArg &arg, int ObService::refresh_memory_stat() { - return ObDumpTaskGenerator::generate_mod_stat_task(); + int ret = OB_SUCCESS; + if (OB_FAIL(ObMemoryDump::get_instance().check_sql_memory_leak())) { + ret = OB_ERR_UNEXPECTED; + LOG_USER_ERROR(OB_ERR_UNEXPECTED, "there has sql memory leak"); + } + return ret; } int ObService::wash_memory_fragmentation() diff --git a/src/observer/omt/ob_th_worker.cpp b/src/observer/omt/ob_th_worker.cpp index 986ff5fa9f..4cf119c337 100644 --- a/src/observer/omt/ob_th_worker.cpp +++ b/src/observer/omt/ob_th_worker.cpp @@ -19,6 +19,7 @@ #include "lib/stat/ob_diagnose_info.h" #include "lib/stat/ob_session_stat.h" #include "lib/allocator/ob_page_manager.h" +#include "lib/allocator/ob_sql_mem_leak_checker.h" #include "lib/rc/context.h" #include "lib/thread/ob_thread_name.h" #include "ob_tenant.h" @@ -305,6 +306,7 @@ void ObThWorker::worker(int64_t &tenant_id, int64_t &req_recv_timestamp, int32_t blocking_ts_ = &Thread::blocking_ts_; ObTLTaGuard ta_guard(tenant_->id()); + ObMemVersionNodeGuard mem_version_node_guard; // Avoid adding and deleting entities from the root node for every request, the parameters are meaningless CREATE_WITH_TEMP_ENTITY(RESOURCE_OWNER, OB_SERVER_TENANT_ID) { auto *pm = common::ObPageManager::thread_local_instance(); diff --git a/src/observer/table_load/ob_table_load_instance.cpp b/src/observer/table_load/ob_table_load_instance.cpp index e263d5964e..d54ba94cff 100644 --- a/src/observer/table_load/ob_table_load_instance.cpp +++ b/src/observer/table_load/ob_table_load_instance.cpp @@ -70,6 +70,7 @@ int ObTableLoadInstance::init(ObTableLoadParam ¶m, const ObIArray & ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", KR(ret), K(param), KPC(execute_ctx)); } else { + DISABLE_SQL_MEMLEAK_GUARD; execute_ctx_ = execute_ctx; allocator_ = execute_ctx->get_allocator(); if (OB_FAIL(param.normalize())) { diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index d0982bfcf7..3ae9376d0a 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -1426,6 +1426,7 @@ int ObPL::execute(ObExecContext &ctx, bool is_called_from_sql) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; int64_t execute_start = ObTimeUtility::current_time(); ObObj local_result(ObMaxType); int local_status = OB_SUCCESS; @@ -1706,6 +1707,7 @@ int ObPL::parameter_anonymous_block(ObExecContext &ctx, int ObPL::execute(ObExecContext &ctx, ParamStore ¶ms, const ObStmtNodeTree *block) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; FLTSpanGuard(pl_entry); lib::MemoryContext mem_context = NULL; lib::ContextParam param; @@ -1852,6 +1854,7 @@ int ObPL::execute(ObExecContext &ctx, ObBitSet &out_args) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; FLTSpanGuard(pl_entry); ObPLFunction *routine = NULL; ObCacheObjGuard cacheobj_guard(PL_ANON_HANDLE); @@ -1941,6 +1944,7 @@ int ObPL::execute(ObExecContext &ctx, bool is_called_from_sql) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; FLTSpanGuard(pl_entry); bool debug_mode = false; ObPLFunction *routine = NULL; diff --git a/src/pl/ob_pl_package_manager.cpp b/src/pl/ob_pl_package_manager.cpp index ddfc43c579..7a3c83d9d1 100644 --- a/src/pl/ob_pl_package_manager.cpp +++ b/src/pl/ob_pl_package_manager.cpp @@ -862,6 +862,7 @@ int ObPLPackageManager::load_package_spec(const ObPLResolveCtx &resolve_ctx, ObPLPackage *&package_spec) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; package_spec = NULL; const uint64_t tenant_id = package_spec_info.get_tenant_id(); uint64_t db_id = package_spec_info.get_database_id(); @@ -929,6 +930,7 @@ int ObPLPackageManager::load_package_body(const ObPLResolveCtx &resolve_ctx, ObPLPackage *&package_body) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; package_body = NULL; ObPLCompiler compiler(resolve_ctx.allocator_, resolve_ctx.session_info_, diff --git a/src/share/cache/ob_kvcache_inst_map.cpp b/src/share/cache/ob_kvcache_inst_map.cpp index d89c65c1b1..ff60e3b803 100644 --- a/src/share/cache/ob_kvcache_inst_map.cpp +++ b/src/share/cache/ob_kvcache_inst_map.cpp @@ -295,7 +295,7 @@ int ObKVCacheInstMap::get_cache_inst( } else if (OB_HASH_NOT_EXIST == ret) { lib::ObMemAttr attr(inst_key.tenant_id_, "CACHE_MAP_NODE"); SET_USE_500(attr); - inst = OB_NEW(ObKVCacheInst, ObMemAttr(inst_key.tenant_id_, "CACHE_INST")); + inst = OB_NEW(ObKVCacheInst, SET_IGNORE_MEM_VERSION(ObMemAttr(inst_key.tenant_id_, "CACHE_INST"))); if (OB_ISNULL(inst)) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(WARN, "Fail to alloc cache inst, ", K(ret)); diff --git a/src/share/ob_encryption_util_os.cpp b/src/share/ob_encryption_util_os.cpp index 6a120d56e8..a4d69f82cb 100644 --- a/src/share/ob_encryption_util_os.cpp +++ b/src/share/ob_encryption_util_os.cpp @@ -360,6 +360,7 @@ static void* ob_malloc_openssl(size_t nbyte, const char *, int) ObMemAttr attr; attr.ctx_id_ = ObCtxIds::GLIBC; attr.label_ = ObModIds::OB_BUFFER; + SET_IGNORE_MEM_VERSION(attr); return ob_malloc(nbyte, attr); } @@ -368,6 +369,7 @@ static void* ob_realloc_openssl(void *ptr, size_t nbyte, const char *, int) ObMemAttr attr; attr.ctx_id_ = ObCtxIds::GLIBC; attr.label_ = ObModIds::OB_BUFFER; + SET_IGNORE_MEM_VERSION(attr); return ob_realloc(ptr, nbyte, attr); } diff --git a/src/share/ob_local_device.cpp b/src/share/ob_local_device.cpp index 9fa0739bcd..9d2026c781 100644 --- a/src/share/ob_local_device.cpp +++ b/src/share/ob_local_device.cpp @@ -113,7 +113,7 @@ ObLocalDevice::~ObLocalDevice() int ObLocalDevice::init(const common::ObIODOpts &opts) { int ret = OB_SUCCESS; - const ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "LDIOSetup"); + const ObMemAttr mem_attr = SET_IGNORE_MEM_VERSION(ObMemAttr(OB_SYS_TENANT_ID, "LDIOSetup")); if (OB_UNLIKELY(is_inited_)) { ret = OB_INIT_TWICE; SHARE_LOG(WARN, "The local device has been inited, ", K(ret)); @@ -1514,7 +1514,7 @@ int ObLocalDevice::open_block_file( } if (OB_SUCC(ret)) { - const ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "LDBlockBitMap"); + const ObMemAttr mem_attr = SET_IGNORE_MEM_VERSION(ObMemAttr(OB_SYS_TENANT_ID, "LDBlockBitMap")); total_block_cnt_ = block_file_size_ / block_size_; if (OB_ISNULL(free_block_array_ = (int64_t *) ob_malloc(sizeof(int64_t) * total_block_cnt_, mem_attr))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -1538,7 +1538,7 @@ int ObLocalDevice::resize_block_file(const int64_t new_size) // copy free block info to new_free_block_array int ret = OB_SUCCESS; int sys_ret = 0; - const ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "LDBlockBitMap"); + const ObMemAttr mem_attr = SET_IGNORE_MEM_VERSION(ObMemAttr(OB_SYS_TENANT_ID, "LDBlockBitMap")); int64_t new_total_block_cnt = new_size / block_size_; int64_t *new_free_block_array = nullptr; bool *new_block_bitmap = nullptr; diff --git a/src/sql/dtl/ob_dtl_channel_loop.cpp b/src/sql/dtl/ob_dtl_channel_loop.cpp index 49e07902ee..83bfd9f939 100644 --- a/src/sql/dtl/ob_dtl_channel_loop.cpp +++ b/src/sql/dtl/ob_dtl_channel_loop.cpp @@ -151,6 +151,7 @@ int ObDtlChannelLoop::ObDtlChannelLoopProc::process( const ObDtlLinkedBuffer &buffer, bool &transferred) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObDtlMsgHeader header; if (buffer.is_data_msg()) { last_msg_type_ = static_cast(ObDtlMsgType::PX_NEW_ROW); diff --git a/src/sql/dtl/ob_dtl_interm_result_manager.cpp b/src/sql/dtl/ob_dtl_interm_result_manager.cpp index 4f51a0aace..2a106d889c 100644 --- a/src/sql/dtl/ob_dtl_interm_result_manager.cpp +++ b/src/sql/dtl/ob_dtl_interm_result_manager.cpp @@ -203,6 +203,7 @@ int ObDTLIntermResultManager::create_interm_result_info(ObMemAttr &attr, int ret = OB_SUCCESS; void *result_info_buf = NULL; void *store_buf = NULL; + SET_IGNORE_MEM_VERSION(attr); const int64_t store_size = use_rich_format ? sizeof(ObTempColumnStore) : sizeof(ObChunkDatumStore); if (OB_ISNULL(result_info_buf = ob_malloc(sizeof(ObDTLIntermResultInfo), attr))) { ret = OB_ALLOCATE_MEMORY_FAILED; diff --git a/src/sql/engine/sequence/ob_sequence_op.h b/src/sql/engine/sequence/ob_sequence_op.h index d3042a7993..94ac3a8631 100644 --- a/src/sql/engine/sequence/ob_sequence_op.h +++ b/src/sql/engine/sequence/ob_sequence_op.h @@ -47,7 +47,11 @@ public: class ObSequenceExecutor { public: ObSequenceExecutor() - :dblink_id_(OB_INVALID_ID) {} + : dblink_id_(OB_INVALID_ID) + { + seq_schemas_.set_attr(SET_IGNORE_MEM_VERSION("SeqSchema")); + seq_ids_.set_attr(SET_IGNORE_MEM_VERSION("SeqId")); + } ~ObSequenceExecutor() { destroy(); } virtual int init(ObExecContext &ctx)=0; virtual void reset() { seq_ids_.reset(); seq_schemas_.reset();} diff --git a/src/sql/engine/table/ob_table_scan_op.cpp b/src/sql/engine/table/ob_table_scan_op.cpp index 8ef0f4da48..2dc0ff290e 100644 --- a/src/sql/engine/table/ob_table_scan_op.cpp +++ b/src/sql/engine/table/ob_table_scan_op.cpp @@ -387,8 +387,9 @@ OB_INLINE int ObTableScanOp::reuse_table_rescan_allocator() if (OB_ISNULL(table_rescan_allocator_)) { ObSQLSessionInfo *my_session = GET_MY_SESSION(ctx_); lib::ContextParam param; - param.set_mem_attr(my_session->get_effective_tenant_id(), - "TableRescanCtx", ObCtxIds::DEFAULT_CTX_ID) + ObMemAttr attr(my_session->get_effective_tenant_id(), + "TableRescanCtx", ObCtxIds::DEFAULT_CTX_ID); + param.set_mem_attr(SET_IGNORE_MEM_VERSION(attr)) .set_properties(lib::USE_TL_PAGE_OPTIONAL) .set_ablock_size(lib::INTACT_MIDDLE_AOBJECT_SIZE); lib::MemoryContext mem_context; diff --git a/src/sql/executor/ob_maintain_dependency_info_task.cpp b/src/sql/executor/ob_maintain_dependency_info_task.cpp index 15e0eb0230..101d91717f 100644 --- a/src/sql/executor/ob_maintain_dependency_info_task.cpp +++ b/src/sql/executor/ob_maintain_dependency_info_task.cpp @@ -130,6 +130,7 @@ int ObMaintainObjDepInfoTask::check_and_build_dep_info_arg( share::ObAsyncTask *ObMaintainObjDepInfoTask::deep_copy(char *buf, const int64_t buf_size) const { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObAsyncTask *task = nullptr; const int64_t need_size = get_deep_copy_size(); if (OB_ISNULL(buf)) { diff --git a/src/sql/ob_sql_trans_control.cpp b/src/sql/ob_sql_trans_control.cpp index e1a5630722..f5ce75cc30 100644 --- a/src/sql/ob_sql_trans_control.cpp +++ b/src/sql/ob_sql_trans_control.cpp @@ -262,6 +262,7 @@ int ObSqlTransControl::end_trans(ObExecContext &exec_ctx, { int ret = OB_SUCCESS; bool sync = false; + DISABLE_SQL_MEMLEAK_GUARD; ObSQLSessionInfo *session = GET_MY_SESSION(exec_ctx); ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(exec_ctx); #ifndef NDEBUG @@ -525,6 +526,7 @@ int ObSqlTransControl::decide_trans_read_interface_specs( int ObSqlTransControl::start_stmt(ObExecContext &exec_ctx) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObSQLSessionInfo *session = GET_MY_SESSION(exec_ctx); ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(exec_ctx); const ObPhysicalPlan *plan = plan_ctx->get_phy_plan(); @@ -1042,6 +1044,7 @@ int ObSqlTransControl::xa_rollback_all_changes(ObExecContext &exec_ctx) int ObSqlTransControl::end_stmt(ObExecContext &exec_ctx, const bool rollback) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObSQLSessionInfo *session = GET_MY_SESSION(exec_ctx); auto *plan_ctx = GET_PHY_PLAN_CTX(exec_ctx); const ObPhysicalPlan *plan = NULL; diff --git a/src/storage/blocksstable/encoding/ob_micro_block_decoder.h b/src/storage/blocksstable/encoding/ob_micro_block_decoder.h index a7356d471f..e04cb85031 100644 --- a/src/storage/blocksstable/encoding/ob_micro_block_decoder.h +++ b/src/storage/blocksstable/encoding/ob_micro_block_decoder.h @@ -88,7 +88,13 @@ class ObDecoderCtxArray final { public: typedef ObColumnDecoderCtx ObDecoderCtx; - ObDecoderCtxArray(): ctxs_(), ctx_blocks_() {}; + ObDecoderCtxArray(): ctxs_(), ctx_blocks_() + { + ObMemAttr attr(ob_thread_tenant_id(), "TLDecoderCtxArr"); + SET_IGNORE_MEM_VERSION(attr); + ctxs_.set_attr(attr); + ctx_blocks_.set_attr(attr); + }; ~ObDecoderCtxArray() { reset(); diff --git a/src/storage/blocksstable/ob_tmp_file.cpp b/src/storage/blocksstable/ob_tmp_file.cpp index 868a50a4c8..711e19f578 100644 --- a/src/storage/blocksstable/ob_tmp_file.cpp +++ b/src/storage/blocksstable/ob_tmp_file.cpp @@ -1080,6 +1080,7 @@ int ObTmpFile::aio_write(const ObTmpFileIOInfo &io_info, ObTmpFileIOHandle &hand { // only support append at present. int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; if (IS_NOT_INIT) { ret = OB_NOT_INIT; STORAGE_LOG(WARN, "ObTmpFile has not been inited", K(ret)); diff --git a/src/storage/blocksstable/ob_tmp_file_store.cpp b/src/storage/blocksstable/ob_tmp_file_store.cpp index 42a9c7052e..518ff7d666 100644 --- a/src/storage/blocksstable/ob_tmp_file_store.cpp +++ b/src/storage/blocksstable/ob_tmp_file_store.cpp @@ -1665,6 +1665,7 @@ int ObTmpFileStore::alloc(const int64_t dir_id, const uint64_t tenant_id, const ObTmpFileExtent &extent) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObTmpTenantFileStoreHandle store_handle; if (OB_FAIL(get_store(tenant_id, store_handle))) { STORAGE_LOG(WARN, "fail to get tmp tenant file store", K(ret), K(tenant_id)); @@ -1917,6 +1918,7 @@ int ObTmpFileStore::get_all_tenant_id(common::ObIArray &tenant_ids) int ObTmpFileStore::get_store(const uint64_t tenant_id, ObTmpTenantFileStoreHandle &handle) { int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; void *buf = NULL; handle.reset(); if (IS_NOT_INIT) { diff --git a/src/storage/tx/ob_dblink_client.cpp b/src/storage/tx/ob_dblink_client.cpp index 3bed43bf9f..ffeadf7dd9 100644 --- a/src/storage/tx/ob_dblink_client.cpp +++ b/src/storage/tx/ob_dblink_client.cpp @@ -332,7 +332,7 @@ int ObDBLinkClient::init_query_impl_(const ObTxIsolationLevel isolation) if (NULL == impl_) { if (DblinkDriverProto::DBLINK_DRV_OB == dblink_type_) { void *ptr = NULL; - if (NULL == (ptr = mtl_malloc(sizeof(ObXAQueryObImpl), "ObXAQuery"))) { + if (NULL == (ptr = mtl_malloc(sizeof(ObXAQueryObImpl), SET_IGNORE_MEM_VERSION("ObXAQuery")))) { ret = OB_ALLOCATE_MEMORY_FAILED; TRANS_LOG(WARN, "fail to allocate memory", K(ret), K(*this)); } else { @@ -367,7 +367,7 @@ int ObDBLinkClient::init_query_impl_(const ObTxIsolationLevel isolation) } } else if (DblinkDriverProto::DBLINK_DRV_OCI == dblink_type_) { void *ptr = NULL; - if (NULL == (ptr = mtl_malloc(sizeof(ObXAQueryOraImpl), "ObXAQuery"))) { + if (NULL == (ptr = mtl_malloc(sizeof(ObXAQueryOraImpl), SET_IGNORE_MEM_VERSION("ObXAQuery")))) { ret = OB_ALLOCATE_MEMORY_FAILED; TRANS_LOG(WARN, "fail to allocate memory", K(ret), K(*this)); } else { diff --git a/src/storage/tx/ob_xa_ctx.cpp b/src/storage/tx/ob_xa_ctx.cpp index 371bddd15f..4180c717c4 100644 --- a/src/storage/tx/ob_xa_ctx.cpp +++ b/src/storage/tx/ob_xa_ctx.cpp @@ -322,7 +322,7 @@ int ObXACtx::init_xa_branch_info_() if (NULL == xa_branch_info_) { void *ptr = NULL; - if (NULL == (ptr = mtl_malloc(sizeof(ObXABranchInfoArray), "XABranchInfo"))) { + if (NULL == (ptr = mtl_malloc(sizeof(ObXABranchInfoArray), SET_IGNORE_MEM_VERSION("XABranchInfo")))) { ret = OB_ALLOCATE_MEMORY_FAILED; TRANS_LOG(WARN, "allocate memory failed", K(ret), K(*this)); } else { @@ -1144,7 +1144,7 @@ int ObXACtx::get_dblink_client_(const DblinkDriverProto dblink_type, if (dblink_client_array_.count() >= OB_MAX_DBLINK_CLIENT_COUNT) { ret = OB_SIZE_OVERFLOW; TRANS_LOG(WARN, "create unexpected dblink client num", K(ret), K(*this)); - } else if (NULL == (ptr = mtl_malloc(sizeof(ObDBLinkClient), "ObDBLinkClient"))) { + } else if (NULL == (ptr = mtl_malloc(sizeof(ObDBLinkClient), SET_IGNORE_MEM_VERSION("ObDBLinkClient")))) { ret = OB_ALLOCATE_MEMORY_FAILED; TRANS_LOG(WARN, "allocate memory failed", K(ret), K(*this)); } else { diff --git a/src/storage/tx_storage/ob_access_service.cpp b/src/storage/tx_storage/ob_access_service.cpp index 0d2792b8cb..d38fd62499 100644 --- a/src/storage/tx_storage/ob_access_service.cpp +++ b/src/storage/tx_storage/ob_access_service.cpp @@ -221,6 +221,7 @@ int ObAccessService::table_scan( { ACTIVE_SESSION_FLAG_SETTER_GUARD(in_storage_read); int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; const share::ObLSID &ls_id = vparam.ls_id_; const common::ObTabletID &data_tablet_id = vparam.tablet_id_; ObTableScanIterator *iter = nullptr; @@ -659,6 +660,7 @@ int ObAccessService::delete_rows( { ACTIVE_SESSION_FLAG_SETTER_GUARD(in_storage_write); int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObStoreCtxGuard ctx_guard; ObLS *ls = nullptr; ObLSTabletService *tablet_service = nullptr; @@ -779,6 +781,7 @@ int ObAccessService::insert_rows( { ACTIVE_SESSION_FLAG_SETTER_GUARD(in_storage_write); int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObStoreCtxGuard ctx_guard; ObLS *ls = nullptr; ObLSTabletService *tablet_service = nullptr; @@ -842,6 +845,7 @@ int ObAccessService::insert_row( { ACTIVE_SESSION_FLAG_SETTER_GUARD(in_storage_write); int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObStoreCtxGuard ctx_guard; ObLS *ls = nullptr; ObLSTabletService *tablet_service = nullptr; @@ -917,6 +921,7 @@ int ObAccessService::update_rows( { ACTIVE_SESSION_FLAG_SETTER_GUARD(in_storage_write); int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObStoreCtxGuard ctx_guard; ObLS *ls = nullptr; ObLSTabletService *tablet_service = nullptr; @@ -979,6 +984,7 @@ int ObAccessService::lock_rows( { ACTIVE_SESSION_FLAG_SETTER_GUARD(in_storage_write); int ret = OB_SUCCESS; + DISABLE_SQL_MEMLEAK_GUARD; ObStoreCtxGuard ctx_guard; ObLS *ls = nullptr; ObLSTabletService *tablet_service = nullptr;