fix dynamic schema memory leak caused by auto gather stats hold schema guard for a long time
This commit is contained in:
@ -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<int64_t, 128> 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<uint64_t, 256> 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<int64_t>(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<int64_t> &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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user