fix foreign key table related ddl.
This commit is contained in:
parent
1f0c63c0d7
commit
21f23309cb
@ -2739,22 +2739,30 @@ int ObDDLTaskRecordOperator::check_has_long_running_ddl(
|
||||
common::ObMySQLProxy *proxy,
|
||||
const uint64_t tenant_id,
|
||||
const uint64_t table_id,
|
||||
const share::ObCheckExistedDDLMode check_mode,
|
||||
bool &has_long_running_ddl)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
has_long_running_ddl = false;
|
||||
if (OB_UNLIKELY(nullptr == proxy || !proxy->is_inited()
|
||||
|| OB_INVALID_ID == tenant_id
|
||||
|| OB_INVALID_ID == table_id)) {
|
||||
|| OB_INVALID_ID == table_id
|
||||
|| ObCheckExistedDDLMode::INVALID_DDL_MODE == check_mode)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid arg", K(ret), KP(proxy), K(tenant_id), K(table_id));
|
||||
LOG_WARN("invalid arg", K(ret), KP(proxy), K(tenant_id), K(table_id), K(check_mode));
|
||||
} else {
|
||||
ObSqlString sql_string;
|
||||
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
|
||||
sqlclient::ObMySQLResult *result = nullptr;
|
||||
const ObDDLType lower_bound_type = (ObCheckExistedDDLMode::ALL_LONG_RUNNING_DDL == check_mode
|
||||
|| ObCheckExistedDDLMode::SIMPLE_TABLE_RUNNING_DDL == check_mode) ?
|
||||
ObDDLType::DDL_INVALID : ObDDLType::DDL_DOUBLE_TABLE_OFFLINE;
|
||||
const ObDDLType upper_bound_type = (ObCheckExistedDDLMode::ALL_LONG_RUNNING_DDL == check_mode
|
||||
|| ObCheckExistedDDLMode::DOUBLE_TABLE_RUNNING_DDL == check_mode) ?
|
||||
ObDDLType::DDL_NORMAL_TYPE : ObDDLType::DDL_DOUBLE_TABLE_OFFLINE;
|
||||
if (OB_FAIL(sql_string.assign_fmt(" SELECT * FROM %s "
|
||||
"WHERE object_id = %lu", OB_ALL_DDL_TASK_STATUS_TNAME,
|
||||
table_id))) {
|
||||
"WHERE object_id = %lu AND ddl_type > %d AND ddl_type < %d", OB_ALL_DDL_TASK_STATUS_TNAME,
|
||||
table_id, lower_bound_type, upper_bound_type))) {
|
||||
LOG_WARN("assign sql string failed", K(ret));
|
||||
} else if (OB_FAIL(proxy->read(res, tenant_id, sql_string.ptr()))) {
|
||||
LOG_WARN("query ddl task record failed", K(ret), K(sql_string));
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "lib/container/ob_array.h"
|
||||
#include "lib/thread/ob_async_task_queue.h"
|
||||
#include "lib/trace/ob_trace.h"
|
||||
#include "share/ob_ddl_common.h"
|
||||
#include "share/ob_ddl_task_executor.h"
|
||||
#include "share/ob_rpc_struct.h"
|
||||
#include "share/schema/ob_schema_struct.h"
|
||||
@ -241,10 +242,12 @@ public:
|
||||
const uint64_t table_id,
|
||||
bool &is_building);
|
||||
|
||||
// To check if any long-time running DDL exists.
|
||||
static int check_has_long_running_ddl(
|
||||
common::ObMySQLProxy *proxy,
|
||||
const uint64_t tenant_id,
|
||||
const uint64_t table_id,
|
||||
const share::ObCheckExistedDDLMode check_mode,
|
||||
bool &has_long_running_ddl);
|
||||
|
||||
static int check_has_conflict_ddl(
|
||||
|
@ -845,7 +845,6 @@ int ObTableRedefinitionTask::repending(const share::ObDDLTaskStatus next_task_st
|
||||
switch (task_type_) {
|
||||
case DDL_DIRECT_LOAD:
|
||||
case DDL_DIRECT_LOAD_INSERT:
|
||||
case DDL_TABLE_RESTORE:
|
||||
if (get_is_do_finish()) {
|
||||
if (OB_FAIL(switch_status(next_task_status, true, ret))) {
|
||||
LOG_WARN("fail to switch status", K(ret));
|
||||
|
@ -11193,7 +11193,8 @@ int ObDDLService::alter_table_in_trans(obrpc::ObAlterTableArg &alter_table_arg,
|
||||
const ObCreateForeignKeyArg &foreign_key_arg = const_alter_table_arg.foreign_key_arg_list_.at(0);
|
||||
int64_t fk_id = OB_INVALID_ID;
|
||||
res.schema_version_ = new_table_schema.get_schema_version();
|
||||
if (foreign_key_arg.need_validate_data_
|
||||
if (const_alter_table_arg.foreign_key_checks_
|
||||
&& foreign_key_arg.need_validate_data_
|
||||
&& ((!foreign_key_arg.is_modify_fk_state_
|
||||
&& foreign_key_arg.validate_flag_)
|
||||
|| (foreign_key_arg.is_modify_validate_flag_
|
||||
@ -11372,7 +11373,10 @@ int ObDDLService::check_is_offline_ddl(ObAlterTableArg &alter_table_arg,
|
||||
if (OB_SUCC(ret) && (is_long_running_ddl(ddl_type)
|
||||
|| alter_table_arg.is_alter_indexs_
|
||||
|| alter_table_arg.alter_constraint_type_!= obrpc::ObAlterTableArg::CONSTRAINT_NO_OPERATION)) {
|
||||
if (OB_FAIL(check_fk_related_table_ddl(*orig_table_schema))) {
|
||||
// For add fk operation, fk occurs in orig_table_schema after publish schema,
|
||||
// so the routine here can not refuse the add fk operation if related schema executing offline ddl.
|
||||
// Don't worry, add_table_foreign_keys in alter_table_in_trans will refuse it.
|
||||
if (OB_FAIL(check_fk_related_table_ddl(*orig_table_schema, ddl_type))) {
|
||||
LOG_WARN("check whether the foreign key related table is executing ddl failed", K(ret));
|
||||
}
|
||||
}
|
||||
@ -11449,23 +11453,26 @@ int ObDDLService::check_is_adding_constraint(const uint64_t tenant_id, const uin
|
||||
return ObDDLTaskRecordOperator::check_is_adding_constraint(sql_proxy_, allocator, tenant_id, table_id, is_building);
|
||||
}
|
||||
|
||||
// check whether the foreign key related table is executing offline ddl, creating index, and executin constrtaint task.
|
||||
// check whether the foreign key related table is executing specifing long-running ddl.
|
||||
// And ddl should be refused if the foreign key related table is executing above ddl.
|
||||
int ObDDLService::check_fk_related_table_ddl(
|
||||
const share::schema::ObTableSchema &data_table_schema)
|
||||
const share::schema::ObTableSchema &data_table_schema,
|
||||
const share::ObDDLType &ddl_type)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const uint64_t tenant_id = data_table_schema.get_tenant_id();
|
||||
ObSchemaGetterGuard schema_guard;
|
||||
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id)) {
|
||||
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id || share::ObDDLType::DDL_INVALID == ddl_type)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid arg", K(ret));
|
||||
LOG_WARN("invalid arg", K(ret), K(tenant_id), K(ddl_type));
|
||||
} else if (OB_FAIL(check_inner_stat())) {
|
||||
LOG_WARN("variable is not init");
|
||||
} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
|
||||
LOG_WARN("get schema guard failed", K(ret));
|
||||
} else {
|
||||
const ObIArray<ObForeignKeyInfo> &foreign_key_infos = data_table_schema.get_foreign_key_infos();
|
||||
const ObCheckExistedDDLMode check_mode = is_double_table_long_running_ddl(ddl_type) ?
|
||||
ObCheckExistedDDLMode::ALL_LONG_RUNNING_DDL : ObCheckExistedDDLMode::DOUBLE_TABLE_RUNNING_DDL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); i++) {
|
||||
const ObForeignKeyInfo &foreign_key_info = foreign_key_infos.at(i);
|
||||
const uint64_t related_table_id = data_table_schema.get_table_id() == foreign_key_info.parent_table_id_
|
||||
@ -11483,14 +11490,17 @@ int ObDDLService::check_fk_related_table_ddl(
|
||||
LOG_WARN("unexpected error, related schema is nullptr", K(ret), K(related_table_id), K(foreign_key_info));
|
||||
} else if (!related_schema->check_can_do_ddl()) {
|
||||
ret = OB_OP_NOT_ALLOW;
|
||||
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "execute ddl while foreign key related table is executing offline ddl");
|
||||
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "execute ddl while foreign key related table is executing long running ddl");
|
||||
} else if (OB_FAIL(ObDDLTaskRecordOperator::check_has_long_running_ddl(sql_proxy_,
|
||||
tenant_id,
|
||||
related_table_id,
|
||||
check_mode,
|
||||
has_long_running_ddl))) {
|
||||
LOG_WARN("check has long running ddl failed", K(ret), K(tenant_id), K(related_table_id));
|
||||
} else if (has_long_running_ddl) {
|
||||
ret = OB_OP_NOT_ALLOW;
|
||||
LOG_WARN("foreign key related table is executing offline ddl", K(ret), K(check_mode), K(tenant_id),
|
||||
"table_id", data_table_schema.get_table_id(), K(related_table_id));
|
||||
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "execute ddl while there are some long running ddl on foreign key related table");
|
||||
}
|
||||
}
|
||||
@ -13235,7 +13245,7 @@ int ObDDLService::alter_table(obrpc::ObAlterTableArg &alter_table_arg,
|
||||
end_usec = ObTimeUtility::current_time();
|
||||
cost_usec = end_usec - start_usec;
|
||||
start_usec = end_usec;
|
||||
LOG_INFO("alter_table_in_trans cost: ", K(cost_usec), K(ddl_type));
|
||||
LOG_INFO("alter_table_in_trans cost: ", K(ret), K(cost_usec), K(ddl_type), "ddl_stmt", alter_table_arg.ddl_stmt_str_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,8 @@ public:
|
||||
// check whether the foreign key related table is executing offline ddl, creating index, and constrtaint task.
|
||||
// And ddl should be refused if the foreign key related table is executing above ddl.
|
||||
int check_fk_related_table_ddl(
|
||||
const share::schema::ObTableSchema &data_table_schema);
|
||||
const share::schema::ObTableSchema &data_table_schema,
|
||||
const share::ObDDLType &ddl_type);
|
||||
int create_global_index(
|
||||
ObMySQLTransaction &trans,
|
||||
const obrpc::ObCreateIndexArg &arg,
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "lib/container/ob_array_iterator.h"
|
||||
#include "share/ob_srv_rpc_proxy.h"
|
||||
#include "lib/mysqlclient/ob_mysql_proxy.h"
|
||||
#include "share/ob_ddl_common.h"
|
||||
#include "share/ob_debug_sync.h"
|
||||
#include "share/ob_common_rpc_proxy.h"
|
||||
#include "share/schema/ob_table_schema.h"
|
||||
@ -133,7 +134,7 @@ int ObIndexBuilder::drop_index(const ObDropIndexArg &arg, obrpc::ObDropIndexRes
|
||||
} else if (is_db_in_recyclebin) {
|
||||
ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
|
||||
LOG_WARN("Can not drop index of db in recyclebin", K(ret), K(arg));
|
||||
} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(*table_schema))) {
|
||||
} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(*table_schema, ObDDLType::DDL_DROP_INDEX))) {
|
||||
LOG_WARN("check whether foreign key related table executes ddl failed", K(ret));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
@ -578,7 +579,7 @@ int ObIndexBuilder::do_create_index(
|
||||
LOG_USER_ERROR(OB_ERR_TOO_MANY_KEYS, OB_MAX_INDEX_PER_TABLE);
|
||||
int64_t index_count = table_schema->get_index_tid_count();
|
||||
LOG_WARN("too many index for table", K(OB_MAX_INDEX_PER_TABLE), K(index_count), K(ret));
|
||||
} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(*table_schema))) {
|
||||
} else if (OB_FAIL(ddl_service_.check_fk_related_table_ddl(*table_schema, ObDDLType::DDL_CREATE_INDEX))) {
|
||||
LOG_WARN("check whether the foreign key related table is executing ddl failed", K(ret));
|
||||
} else if (INDEX_TYPE_NORMAL_LOCAL == arg.index_type_
|
||||
|| INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_
|
||||
|
@ -234,6 +234,14 @@ static inline bool is_ddl_stmt_packet_retry_err(const int ret)
|
||||
;
|
||||
}
|
||||
|
||||
enum ObCheckExistedDDLMode
|
||||
{
|
||||
INVALID_DDL_MODE = 0,
|
||||
ALL_LONG_RUNNING_DDL = 1,
|
||||
SIMPLE_TABLE_RUNNING_DDL = 2,
|
||||
DOUBLE_TABLE_RUNNING_DDL = 3
|
||||
};
|
||||
|
||||
struct ObColumnNameInfo final
|
||||
{
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user