diff --git a/src/pl/sys_package/ob_dbms_stats.cpp b/src/pl/sys_package/ob_dbms_stats.cpp index 5187108cb3..a57aa30352 100644 --- a/src/pl/sys_package/ob_dbms_stats.cpp +++ b/src/pl/sys_package/ob_dbms_stats.cpp @@ -198,7 +198,9 @@ int ObDbmsStats::gather_schema_stats(ObExecContext &ctx, ParamStore ¶ms, ObO ObOptStatGatherStat gather_stat(task_info); ObOptStatGatherStatList::instance().push(gather_stat); ObOptStatRunningMonitor running_monitor(ctx.get_allocator(), start_time, stat_param.allocator_->used(), gather_stat); - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param, true))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param, true))) { LOG_WARN("failed to parse table part info", K(ret)); } else if (OB_FAIL(parse_gather_stat_options(ctx, params.at(1), @@ -920,7 +922,9 @@ int ObDbmsStats::delete_schema_stats(ObExecContext &ctx, ParamStore ¶ms, ObO stat_table.table_id_ = table_ids.at(i); ObTableStatParam stat_param = global_param; stat_param.allocator_ = &tmp_alloc;//use the temp allocator to free memory after delete stats. - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { LOG_WARN("failed to parse table part info", K(ret)); } else if (!params.at(4).is_null() && OB_FAIL(params.at(4).get_bool(stat_param.no_invalidate_))) { LOG_WARN("failed to get no invalidate", K(ret)); @@ -1390,7 +1394,9 @@ int ObDbmsStats::export_schema_stats(ObExecContext &ctx, ParamStore ¶ms, ObO stat_param.stat_id_ = stat_table_param.stat_id_; stat_param.cascade_ = true; stat_param.allocator_ = &tmp_alloc;//use the temp allocator to free memory after export stats. - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { LOG_WARN("failed to parse table part info", K(ret)); } else if (OB_FAIL(ObDbmsStatsExportImport::export_table_stats(ctx, stat_param, tmp_str))) { LOG_WARN("failed to export table stats", K(ret)); @@ -1738,7 +1744,9 @@ int ObDbmsStats::import_schema_stats(ObExecContext &ctx, ParamStore ¶ms, ObO stat_param.part_stat_param_.need_modify_ = true; stat_param.subpart_stat_param_.need_modify_ = true; stat_param.allocator_ = &tmp_alloc;//use the temp allocator to free memory after stat import - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { LOG_WARN("failed to parse table part info", K(ret)); } else if (!params.at(4).is_null() && OB_FAIL(params.at(4).get_bool(stat_param.no_invalidate_))) { LOG_WARN("failed to get stat no_invalidate ", K(ret)); @@ -2030,7 +2038,9 @@ int ObDbmsStats::lock_schema_stats(sql::ObExecContext &ctx, stat_table.database_id_ = global_param.db_id_; stat_table.table_id_ = table_ids.at(i); ObTableStatParam stat_param = global_param; - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { LOG_WARN("failed to parse table part info", K(ret)); } else { stat_param.global_stat_param_.need_modify_ = true; @@ -2219,7 +2229,9 @@ int ObDbmsStats::unlock_schema_stats(sql::ObExecContext &ctx, stat_table.database_id_ = global_param.db_id_; stat_table.table_id_ = table_ids.at(i); ObTableStatParam stat_param = global_param; - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { LOG_WARN("failed to parse table part info", K(ret)); } else { stat_param.global_stat_param_.need_modify_ = true; @@ -2406,7 +2418,9 @@ int ObDbmsStats::restore_schema_stats(sql::ObExecContext &ctx, stat_table.table_id_ = table_ids.at(i); ObTableStatParam stat_param = global_param; stat_param.allocator_ = &tmp_alloc;////use the temp allocator to free memory after stat restore - if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, global_param.tenant_id_))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(parse_table_part_info(ctx, stat_table, stat_param))) { LOG_WARN("failed to parse table part info", K(ret)); } else if (!params.at(2).is_null() && OB_FAIL(params.at(2).get_bool(stat_param.force_))) { LOG_WARN("failed to get force", K(ret)); @@ -5236,12 +5250,11 @@ int ObDbmsStats::gather_database_table_stats(sql::ObExecContext &ctx, { int ret = OB_SUCCESS; ObSEArray table_ids; - ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_; ObSQLSessionInfo *session = ctx.get_my_session(); uint64_t tenant_id = OB_INVALID_ID; - if (OB_ISNULL(schema_guard) || OB_ISNULL(session)) { + if (OB_ISNULL(session)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(schema_guard), K(session)); + LOG_WARN("get unexpected null", K(ret), K(session)); } else if (OB_FALSE_IT(tenant_id = session->get_effective_tenant_id())) { } else if (is_virtual_tenant_id(tenant_id)) { // do nothing @@ -5256,7 +5269,7 @@ int ObDbmsStats::gather_database_table_stats(sql::ObExecContext &ctx, tmp_succeed = succeed_cnt; if (OB_FAIL(ObBasicStatsEstimator::get_need_stats_tables(ctx, tenant_id, table_ids, slice_cnt))) { LOG_WARN("failed to get tables that need gather stats", K(ret)); - } else if (OB_FAIL(do_gather_tables_stats(ctx, *schema_guard, tenant_id, table_ids, + } else if (OB_FAIL(do_gather_tables_stats(ctx, tenant_id, table_ids, duration_time, succeed_cnt, task_info))) { LOG_WARN("failed to gather table stats", K(ret)); } @@ -5270,14 +5283,19 @@ int ObDbmsStats::gather_database_table_stats(sql::ObExecContext &ctx, // gather virtual table stats ObSEArray all_table_ids; if (OB_FAIL(ret)) { - } else if (OB_FAIL(schema_guard->get_table_ids_in_tenant(tenant_id, all_table_ids))){ + } else if (OB_ISNULL(ctx.get_virtual_table_ctx().schema_guard_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(ctx.get_virtual_table_ctx().schema_guard_)); + } else if (OB_FAIL(ctx.get_virtual_table_ctx().schema_guard_->get_table_ids_in_tenant(tenant_id, all_table_ids))) { LOG_WARN("failed to get virtual table ids in tenant", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < all_table_ids.count(); ++i) { int64_t table_id = static_cast(all_table_ids.at(i)); if (is_virtual_table(table_id) && !ObDbmsStatsUtils::is_no_stat_virtual_table(table_id)) { - if (OB_FAIL(do_gather_table_stats(ctx, *schema_guard, table_id, tenant_id, - duration_time, succeed_cnt, task_info))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, tenant_id))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(do_gather_table_stats(ctx, table_id, tenant_id, + duration_time, succeed_cnt, task_info))) { LOG_WARN("failed to gather virtual table stats", K(ret)); } else { ++task_info.task_table_count_; @@ -5290,7 +5308,6 @@ int ObDbmsStats::gather_database_table_stats(sql::ObExecContext &ctx, } int ObDbmsStats::do_gather_tables_stats(sql::ObExecContext &ctx, - ObSchemaGetterGuard &schema_guard, const uint64_t tenant_id, const ObIArray &table_ids, const int64_t duration_time, @@ -5299,8 +5316,10 @@ int ObDbmsStats::do_gather_tables_stats(sql::ObExecContext &ctx, { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < table_ids.count(); ++i) { - if (OB_FAIL(do_gather_table_stats(ctx, schema_guard, table_ids.at(i), tenant_id, - duration_time, succeed_cnt, task_info))) { + if (OB_FAIL(refresh_tenant_schema_guard(ctx, tenant_id))) { + LOG_WARN("refresh tenant schema guard failed", K(ret)); + } else if (OB_FAIL(do_gather_table_stats(ctx, table_ids.at(i), tenant_id, + duration_time, succeed_cnt, task_info))) { LOG_WARN("failed to gather table stats", K(ret)); } } @@ -5308,7 +5327,6 @@ int ObDbmsStats::do_gather_tables_stats(sql::ObExecContext &ctx, } int ObDbmsStats::do_gather_table_stats(sql::ObExecContext &ctx, - ObSchemaGetterGuard &schema_guard, const int64_t table_id, const uint64_t tenant_id, const int64_t duration_time, @@ -5318,14 +5336,18 @@ int ObDbmsStats::do_gather_table_stats(sql::ObExecContext &ctx, int ret = OB_SUCCESS; bool is_valid = false; const ObTableSchema *table_schema = NULL; - if (OB_FAIL(ObDbmsStatsUtils::check_is_stat_table(schema_guard, tenant_id, table_id, is_valid))) { + share::schema::ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_; + if (OB_ISNULL(schema_guard)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(schema_guard)); + } else if (OB_FAIL(ObDbmsStatsUtils::check_is_stat_table(*schema_guard, tenant_id, table_id, is_valid))) { LOG_WARN("failed to check sy table validity", K(ret)); } else if (!is_valid) { // only gather statistics for following tables: // 1. user table // 2. valid sys table // 3. virtual table - } else if (OB_FAIL(schema_guard.get_table_schema(tenant_id, table_id, table_schema))) { + } else if (OB_FAIL(schema_guard->get_table_schema(tenant_id, table_id, table_schema))) { LOG_WARN("failed to get table schema", K(ret)); } else if (OB_ISNULL(table_schema)) { ret = OB_ERR_UNEXPECTED; @@ -6252,5 +6274,23 @@ int ObDbmsStats::init_column_group_stat_param(const share::schema::ObTableSchema return ret; } +//Avoid holding schema guard for a long time to caused dynamic leakage of schema memory, we need refresh tenant schema guard +int ObDbmsStats::refresh_tenant_schema_guard(ObExecContext &ctx, const uint64_t tenant_id) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(ctx.get_my_session()) || OB_ISNULL(ctx.get_sql_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(ctx.get_my_session()), K(ctx.get_sql_ctx())); + } else { + ObTenantCachedSchemaGuardInfo &cached_schema_info = ctx.get_my_session()->get_cached_schema_guard_info(); + if (OB_FAIL(cached_schema_info.refresh_tenant_schema_guard(tenant_id))) { + LOG_WARN("refresh tenant schema guard failed", K(ret), K(tenant_id)); + } else { + ctx.get_sql_ctx()->schema_guard_ = &(cached_schema_info.get_schema_guard()); + } + } + return ret; +} + } } diff --git a/src/pl/sys_package/ob_dbms_stats.h b/src/pl/sys_package/ob_dbms_stats.h index ae776f19dd..94700b8427 100644 --- a/src/pl/sys_package/ob_dbms_stats.h +++ b/src/pl/sys_package/ob_dbms_stats.h @@ -445,7 +445,6 @@ public: ObOptStatTaskInfo &task_info); static int do_gather_table_stats(sql::ObExecContext &ctx, - ObSchemaGetterGuard &schema_guard, const int64_t table_id, const uint64_t tenant_id, const int64_t duration_time, @@ -453,7 +452,6 @@ public: ObOptStatTaskInfo &task_info); static int do_gather_tables_stats(sql::ObExecContext &ctx, - ObSchemaGetterGuard &schema_guard, const uint64_t tenant_id, const ObIArray &table_ids, const int64_t duration_time, @@ -578,6 +576,8 @@ private: static void decide_modified_part(ObTableStatParam ¶m, const bool cascade_parts); + static int refresh_tenant_schema_guard(ObExecContext &ctx, const uint64_t tenant_id); + }; }