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;
|
schema_type_ = TABLE_SCHEMA;
|
||||||
table_type_ = schema->get_table_type();
|
table_type_ = schema->get_table_type();
|
||||||
is_tmp_table_ = schema->is_tmp_table();
|
is_tmp_table_ = schema->is_tmp_table();
|
||||||
|
is_mv_container_table_ = schema->mv_container_table();
|
||||||
// copy table name
|
// copy table name
|
||||||
char *buf = nullptr;
|
char *buf = nullptr;
|
||||||
const ObString &tname = schema->get_table_name_str();
|
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_) {
|
if (outline_version != outline_state_.outline_version_) {
|
||||||
is_old_version = true;
|
is_old_version = true;
|
||||||
} else if (OB_FAIL(check_dep_schema_version(schema_array,
|
} else if (OB_FAIL(check_dep_schema_version(schema_array,
|
||||||
stored_schema_objs_,
|
|
||||||
is_old_version))) {
|
is_old_version))) {
|
||||||
LOG_WARN("failed to check schema obj versions", K(ret));
|
LOG_WARN("failed to check schema obj versions", K(ret));
|
||||||
} else {
|
} else {
|
||||||
@ -1534,19 +1534,21 @@ int ObPlanCacheValue::check_value_version(bool need_check_schema,
|
|||||||
|
|
||||||
//检查table schema version是否过期, get plan时使用
|
//检查table schema version是否过期, get plan时使用
|
||||||
int ObPlanCacheValue::check_dep_schema_version(const ObIArray<PCVSchemaObj> &schema_array,
|
int ObPlanCacheValue::check_dep_schema_version(const ObIArray<PCVSchemaObj> &schema_array,
|
||||||
const ObIArray<PCVSchemaObj *> &pcv_schema_objs,
|
|
||||||
bool &is_old_version)
|
bool &is_old_version)
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
is_old_version = false;
|
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;
|
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 {
|
} else {
|
||||||
for (int64_t i = 0; OB_SUCC(ret) && !is_old_version && i < table_count; ++i) {
|
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);
|
const PCVSchemaObj &schema_obj2 = schema_array.at(i);
|
||||||
if (nullptr == schema_obj1) {
|
if (nullptr == schema_obj1) {
|
||||||
ret = OB_ERR_UNEXPECTED;
|
ret = OB_ERR_UNEXPECTED;
|
||||||
@ -2062,6 +2064,41 @@ int ObPlanCacheValue::get_all_dep_schema(ObPlanCacheCtx &pc_ctx,
|
|||||||
return ret;
|
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信息
|
// 对于计划所依赖的schema进行比较,注意这里不比较table schema的version信息
|
||||||
// table schema的version信息用于淘汰pcv set,在check_value_version时进行比较
|
// table schema的version信息用于淘汰pcv set,在check_value_version时进行比较
|
||||||
int ObPlanCacheValue::match_dep_schema(const ObPlanCacheCtx &pc_ctx,
|
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;
|
int ret = OB_SUCCESS;
|
||||||
is_same = true;
|
is_same = true;
|
||||||
ObSQLSessionInfo *session_info = pc_ctx.sql_ctx_.session_info_;
|
ObSQLSessionInfo *session_info = pc_ctx.sql_ctx_.session_info_;
|
||||||
|
common::ObSEArray<PCVSchemaObj*, 4> check_stored_schema;
|
||||||
if (OB_ISNULL(session_info)) {
|
if (OB_ISNULL(session_info)) {
|
||||||
ret = OB_INVALID_ARGUMENT;
|
ret = OB_INVALID_ARGUMENT;
|
||||||
LOG_WARN("invalid argument", K(ret), K(session_info));
|
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不匹配,可能是以下情况:
|
// schema objs count不匹配,可能是以下情况:
|
||||||
// select * from all_sequences; // 系统视图,系统视图的dependency_table有多个
|
// select * from all_sequences; // 系统视图,系统视图的dependency_table有多个
|
||||||
// select * from all_sequences; // 普通表
|
// select * from all_sequences; // 普通表
|
||||||
is_same = false;
|
is_same = false;
|
||||||
} else {
|
} else {
|
||||||
for (int64_t i = 0; OB_SUCC(ret) && is_same && i < schema_array.count(); i++) {
|
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;
|
ret = OB_INVALID_ARGUMENT;
|
||||||
LOG_WARN("invalid null table schema",
|
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_
|
} else if (TMP_TABLE == schema_array.at(i).table_type_
|
||||||
&& schema_array.at(i).is_tmp_table_) { // check for mysql tmp table
|
&& 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_) &&
|
is_same = ((session_info->get_sessid_for_table() == sessid_) &&
|
||||||
(session_info->get_sess_create_time() == sess_create_time_));
|
(session_info->get_sess_create_time() == sess_create_time_));
|
||||||
} else if (lib::is_oracle_mode()
|
} else if (lib::is_oracle_mode()
|
||||||
&& TABLE_SCHEMA == stored_schema_objs_.at(i)->schema_type_
|
&& TABLE_SCHEMA == check_stored_schema.at(i)->schema_type_
|
||||||
&& !stored_schema_objs_.at(i)->match_compare(schema_array.at(i))) {
|
&& !check_stored_schema.at(i)->match_compare(schema_array.at(i))) {
|
||||||
// 检查oracle模式下普通表是否与系统表同名
|
// 检查oracle模式下普通表是否与系统表同名
|
||||||
is_same = false;
|
is_same = false;
|
||||||
} else if (lib::is_oracle_mode()
|
} else if (lib::is_oracle_mode()
|
||||||
&& SYNONYM_SCHEMA == stored_schema_objs_.at(i)->schema_type_) {
|
&& SYNONYM_SCHEMA == check_stored_schema.at(i)->schema_type_) {
|
||||||
is_same = (stored_schema_objs_.at(i)->database_id_ == schema_array.at(i).database_id_);
|
is_same = (check_stored_schema.at(i)->database_id_ == schema_array.at(i).database_id_);
|
||||||
} else {
|
} else {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,7 @@ struct PCVSchemaObj
|
|||||||
bool is_tmp_table_;
|
bool is_tmp_table_;
|
||||||
bool is_explicit_db_name_;
|
bool is_explicit_db_name_;
|
||||||
common::ObIAllocator *inner_alloc_;
|
common::ObIAllocator *inner_alloc_;
|
||||||
|
bool is_mv_container_table_;
|
||||||
|
|
||||||
PCVSchemaObj():
|
PCVSchemaObj():
|
||||||
tenant_id_(common::OB_INVALID_ID),
|
tenant_id_(common::OB_INVALID_ID),
|
||||||
@ -74,7 +75,8 @@ struct PCVSchemaObj
|
|||||||
table_type_(share::schema::MAX_TABLE_TYPE),
|
table_type_(share::schema::MAX_TABLE_TYPE),
|
||||||
is_tmp_table_(false),
|
is_tmp_table_(false),
|
||||||
is_explicit_db_name_(false),
|
is_explicit_db_name_(false),
|
||||||
inner_alloc_(nullptr) {}
|
inner_alloc_(nullptr),
|
||||||
|
is_mv_container_table_(false) {}
|
||||||
|
|
||||||
explicit PCVSchemaObj(ObIAllocator *alloc):
|
explicit PCVSchemaObj(ObIAllocator *alloc):
|
||||||
tenant_id_(common::OB_INVALID_ID),
|
tenant_id_(common::OB_INVALID_ID),
|
||||||
@ -85,7 +87,8 @@ struct PCVSchemaObj
|
|||||||
table_type_(share::schema::MAX_TABLE_TYPE),
|
table_type_(share::schema::MAX_TABLE_TYPE),
|
||||||
is_tmp_table_(false),
|
is_tmp_table_(false),
|
||||||
is_explicit_db_name_(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(const share::schema::ObTableSchema *schema);
|
||||||
int init_with_synonym(const ObSimpleSynonymSchema *schema);
|
int init_with_synonym(const ObSimpleSynonymSchema *schema);
|
||||||
@ -134,7 +137,8 @@ struct PCVSchemaObj
|
|||||||
K_(table_type),
|
K_(table_type),
|
||||||
K_(table_name),
|
K_(table_name),
|
||||||
K_(is_tmp_table),
|
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>
|
class ObPlanCacheValue :public common::ObDLinkBase<ObPlanCacheValue>
|
||||||
@ -333,9 +337,11 @@ private:
|
|||||||
share::schema::ObSchemaGetterGuard *schema_guard);
|
share::schema::ObSchemaGetterGuard *schema_guard);
|
||||||
|
|
||||||
int check_dep_schema_version(const common::ObIArray<PCVSchemaObj> &schema_array,
|
int check_dep_schema_version(const common::ObIArray<PCVSchemaObj> &schema_array,
|
||||||
const common::ObIArray<PCVSchemaObj *> &pcv_schema_objs,
|
|
||||||
bool &is_old_version);
|
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,
|
int match_dep_schema(const ObPlanCacheCtx &pc_ctx,
|
||||||
const common::ObIArray<PCVSchemaObj> &schema_array,
|
const common::ObIArray<PCVSchemaObj> &schema_array,
|
||||||
bool &is_same);
|
bool &is_same);
|
||||||
|
|||||||
Reference in New Issue
Block a user