fix information_schema.columns memory dynamic leak when resolving views

This commit is contained in:
obdev
2023-02-07 17:16:51 +08:00
committed by ob-robot
parent cc9cadb3ad
commit 8618e5d9bb
5 changed files with 83 additions and 46 deletions

View File

@ -46,7 +46,8 @@ ObInfoSchemaColumnsTable::ObInfoSchemaColumnsTable() :
last_filter_column_idx_(-1), last_filter_column_idx_(-1),
database_schema_array_(), database_schema_array_(),
filter_table_schema_array_(), filter_table_schema_array_(),
view_resolve_alloc_() mem_context_(nullptr),
iter_cnt_(0)
{ {
} }
@ -59,7 +60,11 @@ void ObInfoSchemaColumnsTable::reset()
{ {
ObVirtualTableScannerIterator::reset(); ObVirtualTableScannerIterator::reset();
tenant_id_ = OB_INVALID_ID; tenant_id_ = OB_INVALID_ID;
view_resolve_alloc_.reset(); if (OB_LIKELY(NULL != mem_context_)) {
DESTROY_CONTEXT(mem_context_);
mem_context_ = NULL;
}
iter_cnt_ = 0;
} }
int ObInfoSchemaColumnsTable::inner_get_next_row(common::ObNewRow *&row) int ObInfoSchemaColumnsTable::inner_get_next_row(common::ObNewRow *&row)
@ -72,6 +77,8 @@ int ObInfoSchemaColumnsTable::inner_get_next_row(common::ObNewRow *&row)
} else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id_)) { } else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id_)) {
ret = OB_NOT_INIT; ret = OB_NOT_INIT;
SERVER_LOG(WARN, "tenant id is invalid_id", K(ret), K(tenant_id_)); SERVER_LOG(WARN, "tenant id is invalid_id", K(ret), K(tenant_id_));
} else if (OB_FAIL(init_mem_context())) {
SERVER_LOG(WARN, "failed to init mem context", K(ret));
} else { } else {
if (!start_to_read_) { if (!start_to_read_) {
void *tmp_ptr = NULL; void *tmp_ptr = NULL;
@ -204,7 +211,10 @@ int ObInfoSchemaColumnsTable::iterate_table_schema_array(const bool is_filter_ta
} else { } else {
table_schema = table_schema_array.at(i); table_schema = table_schema_array.at(i);
} }
if (OB_ISNULL(table_schema)) { ++iter_cnt_;
if (0 == ++iter_cnt_ % 1024 && OB_FAIL(THIS_WORKER.check_status())) {
SERVER_LOG(WARN, "failed to check status", K(ret));
} else if (OB_ISNULL(table_schema)) {
ret = OB_ERR_UNEXPECTED; ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "table_schema should not be NULL", K(ret)); SERVER_LOG(WARN, "table_schema should not be NULL", K(ret));
} else { } else {
@ -226,22 +236,23 @@ int ObInfoSchemaColumnsTable::iterate_table_schema_array(const bool is_filter_ta
bool view_is_invalid = (0 == table_schema->get_object_status() || 0 == table_schema->get_column_count()); bool view_is_invalid = (0 == table_schema->get_object_status() || 0 == table_schema->get_column_count());
if (OB_FAIL(ret)) { if (OB_FAIL(ret)) {
} else if (is_normal_view && view_is_invalid) { } else if (is_normal_view && view_is_invalid) {
view_resolve_alloc_.reset_remain_one_page(); mem_context_->reset_remain_one_page();
WITH_CONTEXT(mem_context_) {
ObString view_definition; ObString view_definition;
sql::ObSelectStmt *select_stmt = NULL; sql::ObSelectStmt *select_stmt = NULL;
sql::ObSelectStmt *real_stmt = NULL; sql::ObSelectStmt *real_stmt = NULL;
ObStmtFactory stmt_factory(view_resolve_alloc_); ObStmtFactory stmt_factory(mem_context_->get_arena_allocator());
ObRawExprFactory expr_factory(view_resolve_alloc_); ObRawExprFactory expr_factory(mem_context_->get_arena_allocator());
if (OB_FAIL(ObSQLUtils::generate_view_definition_for_resolve( if (OB_FAIL(ObSQLUtils::generate_view_definition_for_resolve(
view_resolve_alloc_, mem_context_->get_arena_allocator(),
session_->get_local_collation_connection(), session_->get_local_collation_connection(),
table_schema->get_view_schema(), table_schema->get_view_schema(),
view_definition))) { view_definition))) {
SERVER_LOG(WARN, "fail to generate view definition for resolve", K(ret)); SERVER_LOG(WARN, "fail to generate view definition for resolve", K(ret));
} else if (OB_FAIL(ObTableColumns::resolve_view_definition(&view_resolve_alloc_, session_, schema_guard_, } else if (OB_FAIL(ObTableColumns::resolve_view_definition(&mem_context_->get_arena_allocator(), session_, schema_guard_,
*table_schema, select_stmt, expr_factory, stmt_factory, false))) { *table_schema, select_stmt, expr_factory, stmt_factory, false))) {
if (OB_ERR_UNKNOWN_TABLE != ret && OB_ERR_VIEW_INVALID != ret) { if (OB_ERR_UNKNOWN_TABLE != ret && OB_ERR_VIEW_INVALID != ret) {
SERVER_LOG(WARN, "failed to resolve view definition", K(view_definition), K(ret), K(table_schema->get_table_id())); SERVER_LOG(WARN, "failed to resolve view definition", K(view_definition), K(ret), K(table_schema->get_table_id()), K(mem_context_->used()));
} else { } else {
ret = OB_SUCCESS; ret = OB_SUCCESS;
continue; continue;
@ -270,6 +281,7 @@ int ObInfoSchemaColumnsTable::iterate_table_schema_array(const bool is_filter_ta
} }
} }
} }
}
} else if (OB_FAIL(iterate_column_schema_array(database_schema->get_database_name_str(), } else if (OB_FAIL(iterate_column_schema_array(database_schema->get_database_name_str(),
*table_schema, *table_schema,
last_db_schema_idx, last_db_schema_idx,
@ -1152,5 +1164,21 @@ int ObInfoSchemaColumnsTable::fill_row_cells(const common::ObString &database_na
return ret; return ret;
} }
inline int ObInfoSchemaColumnsTable::init_mem_context()
{
int ret = common::OB_SUCCESS;
if (OB_LIKELY(NULL == mem_context_)) {
lib::ContextParam param;
param.set_properties(lib::USE_TL_PAGE_OPTIONAL)
.set_mem_attr(tenant_id_, ObModIds::OB_SQL_EXECUTOR, ObCtxIds::DEFAULT_CTX_ID);
if (OB_FAIL(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context_, param))) {
SQL_ENG_LOG(WARN, "create entity failed", K(ret));
} else if (OB_ISNULL(mem_context_)) {
SQL_ENG_LOG(WARN, "mem entity is null", K(ret));
}
}
return ret;
}
} // namespace observer } // namespace observer
} // namespace oceanbase } // namespace oceanbase

View File

@ -115,6 +115,7 @@ private:
char* buf, char* buf,
const int64_t buf_len, const int64_t buf_len,
int64_t &pos); int64_t &pos);
inline int init_mem_context();
private: private:
uint64_t tenant_id_; uint64_t tenant_id_;
int64_t last_schema_idx_; int64_t last_schema_idx_;
@ -130,6 +131,8 @@ private:
common::ObSEArray<const share::schema::ObDatabaseSchema *, 8> database_schema_array_; common::ObSEArray<const share::schema::ObDatabaseSchema *, 8> database_schema_array_;
common::ObSEArray<const share::schema::ObTableSchema *, 16> filter_table_schema_array_; common::ObSEArray<const share::schema::ObTableSchema *, 16> filter_table_schema_array_;
ObArenaAllocator view_resolve_alloc_; ObArenaAllocator view_resolve_alloc_;
lib::MemoryContext mem_context_;
int64_t iter_cnt_;
}; };
} // namespace observer } // namespace observer
} // namespace oceanbase } // namespace oceanbase

View File

@ -927,7 +927,11 @@ int ObTableColumns::resolve_view_definition(
K(select_stmt_node->type_)); K(select_stmt_node->type_));
} else if (OB_FAIL(select_resolver.resolve(*select_stmt_node))) { } else if (OB_FAIL(select_resolver.resolve(*select_stmt_node))) {
LOG_WARN("resolve view definition failed", K(ret)); LOG_WARN("resolve view definition failed", K(ret));
if (OB_ALLOCATE_MEMORY_FAILED != ret) {
ret = OB_ERR_VIEW_INVALID; ret = OB_ERR_VIEW_INVALID;
} else {
LOG_WARN("failed to resolve view", K(ret));
}
if (throw_error) { if (throw_error) {
LOG_USER_ERROR(OB_ERR_VIEW_INVALID, db_name.length(), db_name.ptr(), LOG_USER_ERROR(OB_ERR_VIEW_INVALID, db_name.length(), db_name.ptr(),
table_name.length(), table_name.ptr()); table_name.length(), table_name.ptr());

View File

@ -1129,10 +1129,12 @@ int ObReferenceObjTable::process_reference_obj_table(const uint64_t tenant_id,
OZ (task_queue.erase_view_id_from_set(dep_obj_id)); OZ (task_queue.erase_view_id_from_set(dep_obj_id));
} }
} else if (OB_FAIL(task_queue.push(task))) { } else if (OB_FAIL(task_queue.push(task))) {
if (OB_UNLIKELY(OB_SIZE_OVERFLOW != ret)) {
LOG_WARN("push task failed", K(ret)); LOG_WARN("push task failed", K(ret));
} }
} }
} }
}
if (OB_FAIL(ret) && OB_INVALID_ID != dep_obj_id) { if (OB_FAIL(ret) && OB_INVALID_ID != dep_obj_id) {
int tmp_ret = OB_SUCCESS; int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = task_queue.erase_view_id_from_set(dep_obj_id))) { if (OB_SUCCESS != (tmp_ret = task_queue.erase_view_id_from_set(dep_obj_id))) {

View File

@ -266,7 +266,7 @@ void ObMaintainDepInfoTaskQueue::run2()
task->set_retry_times(task->get_retry_times() - 1); task->set_retry_times(task->get_retry_times() - 1);
task->set_last_execute_time(ObTimeUtility::current_time()); task->set_last_execute_time(ObTimeUtility::current_time());
if (OB_FAIL(queue_.push(task))) { if (OB_FAIL(queue_.push(task))) {
LOG_ERROR("push task to queue failed", K(ret)); LOG_WARN("push task to queue failed", K(ret));
} else { } else {
rescheduled = true; rescheduled = true;
} }