fix mv rewrite plan cache bug
This commit is contained in:
@ -55,6 +55,7 @@ int PCVSchemaObj::init(const ObTableSchema *schema)
|
||||
schema_type_ = TABLE_SCHEMA;
|
||||
table_type_ = schema->get_table_type();
|
||||
is_tmp_table_ = schema->is_tmp_table();
|
||||
is_mv_container_table_ = schema->mv_container_table();
|
||||
// copy table name
|
||||
char *buf = nullptr;
|
||||
const ObString &tname = schema->get_table_name_str();
|
||||
@ -1522,7 +1523,6 @@ int ObPlanCacheValue::check_value_version(bool need_check_schema,
|
||||
if (outline_version != outline_state_.outline_version_) {
|
||||
is_old_version = true;
|
||||
} else if (OB_FAIL(check_dep_schema_version(schema_array,
|
||||
stored_schema_objs_,
|
||||
is_old_version))) {
|
||||
LOG_WARN("failed to check schema obj versions", K(ret));
|
||||
} else {
|
||||
@ -1534,19 +1534,21 @@ int ObPlanCacheValue::check_value_version(bool need_check_schema,
|
||||
|
||||
//检查table schema version是否过期, get plan时使用
|
||||
int ObPlanCacheValue::check_dep_schema_version(const ObIArray<PCVSchemaObj> &schema_array,
|
||||
const ObIArray<PCVSchemaObj *> &pcv_schema_objs,
|
||||
bool &is_old_version)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_old_version = false;
|
||||
int64_t table_count = pcv_schema_objs.count();
|
||||
int64_t table_count = schema_array.count();
|
||||
ObSEArray<PCVSchemaObj*, 4> check_stored_schema;
|
||||
|
||||
if (schema_array.count() != pcv_schema_objs.count()) {
|
||||
if (OB_FAIL(remove_mv_schema(schema_array, check_stored_schema))) {
|
||||
LOG_WARN("failed to remove mv schema", K(ret));
|
||||
} else if (schema_array.count() != check_stored_schema.count()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("table count do not match", K(ret), K(schema_array.count()), K(pcv_schema_objs.count()));
|
||||
LOG_WARN("table count do not match", K(ret), K(schema_array.count()), K(check_stored_schema.count()));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !is_old_version && i < table_count; ++i) {
|
||||
const PCVSchemaObj *schema_obj1 = pcv_schema_objs.at(i);
|
||||
const PCVSchemaObj *schema_obj1 = check_stored_schema.at(i);
|
||||
const PCVSchemaObj &schema_obj2 = schema_array.at(i);
|
||||
if (nullptr == schema_obj1) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -2062,6 +2064,41 @@ int ObPlanCacheValue::get_all_dep_schema(ObPlanCacheCtx &pc_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 针对
|
||||
// 物化视图改写会使得同一条 SQL 的不同计划依赖的表不同,导致 plan cache 进入不同的 pcv set
|
||||
// 在检查 pcv set 的时候跳过物化视图相关的表,使得改写与不改写的 SQL 进入同一个 pcv set
|
||||
int ObPlanCacheValue::remove_mv_schema(const common::ObIArray<PCVSchemaObj> &schema_array,
|
||||
common::ObIArray<PCVSchemaObj*> &check_stored_schema)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool need_remove = true;
|
||||
int64_t j = 0;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stored_schema_objs_.count(); ++i) {
|
||||
if (OB_ISNULL(stored_schema_objs_.at(i))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid null table schema", K(ret), K(i), K(stored_schema_objs_.at(i)));
|
||||
} else if (MATERIALIZED_VIEW == stored_schema_objs_.at(i)->table_type_
|
||||
|| MATERIALIZED_VIEW_LOG == stored_schema_objs_.at(i)->table_type_
|
||||
|| stored_schema_objs_.at(i)->is_mv_container_table_) {
|
||||
if (j < schema_array.count()
|
||||
&& stored_schema_objs_.at(i)->schema_id_ == schema_array.at(j).schema_id_) {
|
||||
if (OB_FAIL(check_stored_schema.push_back(stored_schema_objs_.at(i)))) {
|
||||
LOG_WARN("failed to push back schema", K(ret));
|
||||
} else {
|
||||
++j;
|
||||
}
|
||||
} else {
|
||||
// do nothing, 仅存在于 pcv set 中的物化视图是改写出来的,抛弃
|
||||
}
|
||||
} else if (OB_FAIL(check_stored_schema.push_back(stored_schema_objs_.at(i)))) {
|
||||
LOG_WARN("failed to push back schema", K(ret));
|
||||
} else {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 对于计划所依赖的schema进行比较,注意这里不比较table schema的version信息
|
||||
// table schema的version信息用于淘汰pcv set,在check_value_version时进行比较
|
||||
int ObPlanCacheValue::match_dep_schema(const ObPlanCacheCtx &pc_ctx,
|
||||
@ -2071,20 +2108,23 @@ int ObPlanCacheValue::match_dep_schema(const ObPlanCacheCtx &pc_ctx,
|
||||
int ret = OB_SUCCESS;
|
||||
is_same = true;
|
||||
ObSQLSessionInfo *session_info = pc_ctx.sql_ctx_.session_info_;
|
||||
common::ObSEArray<PCVSchemaObj*, 4> check_stored_schema;
|
||||
if (OB_ISNULL(session_info)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", K(ret), K(session_info));
|
||||
} else if (schema_array.count() != stored_schema_objs_.count()) {
|
||||
} else if (OB_FAIL(remove_mv_schema(schema_array, check_stored_schema))) {
|
||||
LOG_WARN("failed to remove mv schema", K(ret));
|
||||
} else if (schema_array.count() != check_stored_schema.count()) {
|
||||
// schema objs count不匹配,可能是以下情况:
|
||||
// select * from all_sequences; // 系统视图,系统视图的dependency_table有多个
|
||||
// select * from all_sequences; // 普通表
|
||||
is_same = false;
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && is_same && i < schema_array.count(); i++) {
|
||||
if (OB_ISNULL(stored_schema_objs_.at(i))) {
|
||||
if (OB_ISNULL(check_stored_schema.at(i))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid null table schema",
|
||||
K(ret), K(i), K(schema_array.at(i)), K(stored_schema_objs_.at(i)));
|
||||
K(ret), K(i), K(schema_array.at(i)), K(check_stored_schema.at(i)));
|
||||
} else if (TMP_TABLE == schema_array.at(i).table_type_
|
||||
&& schema_array.at(i).is_tmp_table_) { // check for mysql tmp table
|
||||
// 如果包含临时表
|
||||
@ -2100,13 +2140,13 @@ int ObPlanCacheValue::match_dep_schema(const ObPlanCacheCtx &pc_ctx,
|
||||
is_same = ((session_info->get_sessid_for_table() == sessid_) &&
|
||||
(session_info->get_sess_create_time() == sess_create_time_));
|
||||
} else if (lib::is_oracle_mode()
|
||||
&& TABLE_SCHEMA == stored_schema_objs_.at(i)->schema_type_
|
||||
&& !stored_schema_objs_.at(i)->match_compare(schema_array.at(i))) {
|
||||
&& TABLE_SCHEMA == check_stored_schema.at(i)->schema_type_
|
||||
&& !check_stored_schema.at(i)->match_compare(schema_array.at(i))) {
|
||||
// 检查oracle模式下普通表是否与系统表同名
|
||||
is_same = false;
|
||||
} else if (lib::is_oracle_mode()
|
||||
&& SYNONYM_SCHEMA == stored_schema_objs_.at(i)->schema_type_) {
|
||||
is_same = (stored_schema_objs_.at(i)->database_id_ == schema_array.at(i).database_id_);
|
||||
&& SYNONYM_SCHEMA == check_stored_schema.at(i)->schema_type_) {
|
||||
is_same = (check_stored_schema.at(i)->database_id_ == schema_array.at(i).database_id_);
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@ -64,6 +64,7 @@ struct PCVSchemaObj
|
||||
bool is_tmp_table_;
|
||||
bool is_explicit_db_name_;
|
||||
common::ObIAllocator *inner_alloc_;
|
||||
bool is_mv_container_table_;
|
||||
|
||||
PCVSchemaObj():
|
||||
tenant_id_(common::OB_INVALID_ID),
|
||||
@ -74,7 +75,8 @@ struct PCVSchemaObj
|
||||
table_type_(share::schema::MAX_TABLE_TYPE),
|
||||
is_tmp_table_(false),
|
||||
is_explicit_db_name_(false),
|
||||
inner_alloc_(nullptr) {}
|
||||
inner_alloc_(nullptr),
|
||||
is_mv_container_table_(false) {}
|
||||
|
||||
explicit PCVSchemaObj(ObIAllocator *alloc):
|
||||
tenant_id_(common::OB_INVALID_ID),
|
||||
@ -85,7 +87,8 @@ struct PCVSchemaObj
|
||||
table_type_(share::schema::MAX_TABLE_TYPE),
|
||||
is_tmp_table_(false),
|
||||
is_explicit_db_name_(false),
|
||||
inner_alloc_(alloc) {}
|
||||
inner_alloc_(alloc),
|
||||
is_mv_container_table_(false) {}
|
||||
|
||||
int init(const share::schema::ObTableSchema *schema);
|
||||
int init_with_synonym(const ObSimpleSynonymSchema *schema);
|
||||
@ -134,7 +137,8 @@ struct PCVSchemaObj
|
||||
K_(table_type),
|
||||
K_(table_name),
|
||||
K_(is_tmp_table),
|
||||
K_(is_explicit_db_name));
|
||||
K_(is_explicit_db_name),
|
||||
K_(is_mv_container_table));
|
||||
};
|
||||
|
||||
class ObPlanCacheValue :public common::ObDLinkBase<ObPlanCacheValue>
|
||||
@ -333,9 +337,11 @@ private:
|
||||
share::schema::ObSchemaGetterGuard *schema_guard);
|
||||
|
||||
int check_dep_schema_version(const common::ObIArray<PCVSchemaObj> &schema_array,
|
||||
const common::ObIArray<PCVSchemaObj *> &pcv_schema_objs,
|
||||
bool &is_old_version);
|
||||
|
||||
int remove_mv_schema(const common::ObIArray<PCVSchemaObj> &schema_array,
|
||||
common::ObIArray<PCVSchemaObj*> &stored_schema_objs);
|
||||
|
||||
int match_dep_schema(const ObPlanCacheCtx &pc_ctx,
|
||||
const common::ObIArray<PCVSchemaObj> &schema_array,
|
||||
bool &is_same);
|
||||
|
||||
Reference in New Issue
Block a user