[FEAT MERGE][CP]parallel comment/create index

This commit is contained in:
fanfangzhou 2024-11-19 06:15:24 +00:00 committed by ob-robot
parent 88687485ac
commit afb6162c48
53 changed files with 3204 additions and 402 deletions

View File

@ -843,6 +843,12 @@ DEF_NAME(id, "id")
DEF_NAME(wait_ddl_trans, "wait_ddl_trans")
DEF_NAME(end_ddl_trans, "end_ddl_trans")
DEF_NAME_PAIR(create_view, "create view")
DEF_NAME_PAIR(set_comment, "set comment")
DEF_NAME(lock_common_ddl, "lock common ddl")
DEF_NAME(check_schemas, "check schemas")
DEF_NAME(alter_schemas, "alter schemas")
DEF_NAME_PAIR(parallel_ddl, "parallel ddl")
DEF_NAME(submit_task, "submit task")
// location cache related
DEF_NAME_PAIR(renew_loc_by_sql, "renew loc by sql")

View File

@ -105,6 +105,7 @@ void oceanbase::observer::init_srv_xlator_for_rootserver(ObSrvRpcXlator *xlator)
RPC_PROCESSOR(rootserver::ObRpcAbortRedefTableP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcUpdateDDLTaskActiveTimeP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcCreateHiddenTableP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcSetCommentP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcAlterTableP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcExchangePartitionP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcDropTableP, *gctx_.root_service_);
@ -113,6 +114,7 @@ void oceanbase::observer::init_srv_xlator_for_rootserver(ObSrvRpcXlator *xlator)
RPC_PROCESSOR(rootserver::ObRpcTruncateTableV2P, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcCreateAuxIndexP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcCreateIndexP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcParallelCreateIndexP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcDropIndexP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcDropIndexOnFailedP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcCreateMLogP, *gctx_.root_service_);
@ -121,6 +123,7 @@ void oceanbase::observer::init_srv_xlator_for_rootserver(ObSrvRpcXlator *xlator)
RPC_PROCESSOR(rootserver::ObRpcRefreshConfigP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcRootMinorFreezeP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObUpdateIndexTableStatusP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObUpdateIndexStatusP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcCreateOutlineP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcAlterOutlineP, *gctx_.root_service_);
RPC_PROCESSOR(rootserver::ObRpcDropOutlineP, *gctx_.root_service_);

View File

@ -146,6 +146,9 @@ ob_set_subtarget(ob_rootserver parallel_ddl
parallel_ddl/ob_create_view_helper.cpp
parallel_ddl/ob_index_name_checker.cpp
parallel_ddl/ob_tablet_balance_allocator.cpp
parallel_ddl/ob_set_comment_helper.cpp
parallel_ddl/ob_create_index_helper.cpp
parallel_ddl/ob_update_index_status_helper.cpp
)
ob_set_subtarget(ob_rootserver freeze

View File

@ -60,6 +60,8 @@ using namespace blocksstable;
namespace rootserver
{
ObDDLTaskKey::ObDDLTaskKey()
: tenant_id_(OB_INVALID_TENANT_ID), object_id_(OB_INVALID_ID), schema_version_(0)
{
@ -1044,9 +1046,8 @@ int ObDDLTask::set_ddl_stmt_str(const ObString &ddl_stmt_str)
int ObDDLTask::serialize_params_to_message(char *buf, const int64_t buf_size, int64_t &pos) const
{
int ret = OB_SUCCESS;
bool is_unique_index = false;
bool is_global_index = false;
ObDDLTaskSerializeField serialize_field(task_version_, parallelism_, data_format_version_, consumer_group_id_, is_abort_, sub_task_trace_id_, is_unique_index, is_global_index, is_pre_split_);
ObDDLTaskSerializeField serialize_field(task_version_, parallelism_, data_format_version_, consumer_group_id_, is_abort_,
sub_task_trace_id_, is_unique_index_, is_global_index_, is_pre_split_);
if (OB_UNLIKELY(nullptr == buf || buf_size <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), KP(buf), K(buf_size));
@ -1074,6 +1075,8 @@ int ObDDLTask::deserialize_params_from_message(const uint64_t tenant_id, const c
consumer_group_id_ = serialize_field.consumer_group_id_;
is_abort_ = serialize_field.is_abort_;
sub_task_trace_id_ = serialize_field.sub_task_trace_id_;
is_unique_index_ = serialize_field.is_unique_index_;
is_global_index_ = serialize_field.is_global_index_;
is_pre_split_ = serialize_field.is_pre_split_;
}
return ret;
@ -1081,9 +1084,8 @@ int ObDDLTask::deserialize_params_from_message(const uint64_t tenant_id, const c
int64_t ObDDLTask::get_serialize_param_size() const
{
bool is_unique_index = false;
bool is_global_index = false;
ObDDLTaskSerializeField serialize_field(task_version_, parallelism_, data_format_version_, consumer_group_id_, is_abort_, sub_task_trace_id_, is_unique_index, is_global_index, is_pre_split_);
ObDDLTaskSerializeField serialize_field(task_version_, parallelism_, data_format_version_, consumer_group_id_, is_abort_,
sub_task_trace_id_, is_unique_index_, is_global_index_, is_pre_split_);
return serialize_field.get_serialize_size();
}
@ -1117,6 +1119,7 @@ int ObDDLTask::convert_to_record(
task_record.task_version_ = get_task_version();
task_record.execution_id_ = get_execution_id();
task_record.ret_code_ = get_ret_code();
task_record.consensus_schema_version_ = get_consensus_schema_version();
task_record.ddl_need_retry_at_executor_ = !is_ddl_retryable();
const ObString &ddl_stmt_str = get_ddl_stmt_str();
if (serialize_param_size > 0) {
@ -1379,6 +1382,7 @@ int ObDDLTask::report_error_code(const ObString &forward_user_message, const int
const int64_t buf_size = is_ddl_retry_task ? forward_user_message.length() + 1: OB_MAX_ERROR_MSG_LEN;
error_message.ret_code_ = ret_code_;
error_message.ddl_type_ = task_type_;
error_message.consensus_schema_version_ = consensus_schema_version_;
if (OB_FAIL(databuff_printf(error_message.dba_message_, OB_MAX_ERROR_MSG_LEN, "%s", "Successful ddl"))) {
LOG_WARN("print ddl dba message failed", K(ret));
} else if (OB_FAIL(error_message.prepare_user_message_buf(buf_size))) {
@ -2857,6 +2861,7 @@ void ObDDLTaskRecord::reset()
task_version_ = 0;
ret_code_ = OB_SUCCESS;
execution_id_ = -1; // -1 is invalid
consensus_schema_version_ = OB_INVALID_VERSION;
}
@ -3184,6 +3189,35 @@ int ObDDLTaskRecordOperator::update_ret_code_and_message(
return ret;
}
int ObDDLTaskRecordOperator::update_consensus_schema_version(
common::ObISQLClient &sql_client,
const uint64_t tenant_id,
const int64_t task_id,
const int64_t consensus_schema_version)
{
int ret = OB_SUCCESS;
ObSqlString sql_string;
int64_t affected_rows = 0;
if (OB_ISNULL(sql_client.get_pool())
|| OB_UNLIKELY(task_id <= 0 || tenant_id == OB_INVALID_TENANT_ID
|| consensus_schema_version <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", KR(ret), K(tenant_id), K(task_id));
} else if (OB_FAIL(sql_string.assign_fmt("UPDATE %s SET consensus_schema_version=%ld WHERE task_id=%lu ",
OB_ALL_DDL_TASK_STATUS_TNAME, consensus_schema_version, task_id))) {
LOG_WARN("assign sql string failed", KR(ret), K(consensus_schema_version), K(task_id));
} else if (OB_FAIL(DDL_SIM(tenant_id, task_id, TASK_STATUS_OPERATOR_SLOW))) {
LOG_WARN("ddl sim failure: slow inner sql", KR(ret), K(tenant_id), K(task_id));
} else if (OB_FAIL(DDL_SIM(tenant_id, task_id, UPDATE_TASK_RECORD_ON_RET_CODE_FAILED))) {
LOG_WARN("ddl sim failure", KR(ret), K(tenant_id), K(task_id));
} else if (OB_FAIL(sql_client.write(tenant_id, sql_string.ptr(), affected_rows))) {
LOG_WARN("update snapshot_version of ddl task record failed", KR(ret), K(sql_string));
} else if (OB_UNLIKELY(affected_rows < 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected affected_rows", KR(ret), K(affected_rows));
}
return ret;
}
int ObDDLTaskRecordOperator::get_schedule_info_for_update(
common::ObISQLClient &proxy,
const uint64_t tenant_id,
@ -3586,12 +3620,10 @@ int ObDDLTaskRecordOperator::check_is_adding_constraint(
ObSqlString sql_string;
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
sqlclient::ObMySQLResult *result = NULL;
if (OB_FAIL(sql_string.assign_fmt(" SELECT time_to_usec(gmt_create) AS create_time, tenant_id, task_id, object_id, target_object_id, ddl_type, "
"schema_version, parent_task_id, trace_id, status, snapshot_version, task_version, execution_id, "
"UNHEX(ddl_stmt_str) as ddl_stmt_str_unhex, ret_code, UNHEX(message) as message_unhex FROM %s "
"WHERE object_id = %" PRIu64 " && ddl_type IN (%d, %d, %d)", OB_ALL_DDL_TASK_STATUS_TNAME,
if (OB_FAIL(sql_string.assign_fmt(GET_DDL_TASK_SQL
" WHERE object_id = %" PRIu64 " && ddl_type IN (%d, %d, %d)", OB_ALL_DDL_TASK_STATUS_TNAME,
object_id, DDL_CHECK_CONSTRAINT, DDL_FOREIGN_KEY_CONSTRAINT, DDL_ADD_NOT_NULL_COLUMN))) {
LOG_WARN("assign sql string failed", K(ret));
LOG_WARN("assign sql string failed", KR(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));
} else if (OB_ISNULL(result = res.get_result())) {
@ -3686,11 +3718,9 @@ int ObDDLTaskRecordOperator::check_has_conflict_ddl(
ObSqlString sql_string;
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
sqlclient::ObMySQLResult *result = nullptr;
if (OB_FAIL(sql_string.assign_fmt("SELECT time_to_usec(gmt_create) AS create_time, tenant_id, task_id, object_id, target_object_id, ddl_type,"
"schema_version, parent_task_id, trace_id, status, snapshot_version, task_version, execution_id,"
"UNHEX(ddl_stmt_str) as ddl_stmt_str_unhex, ret_code, UNHEX(message) as message_unhex FROM %s "
"WHERE object_id = %lu", OB_ALL_DDL_TASK_STATUS_TNAME, table_id))) {
LOG_WARN("assign sql string failed", K(ret));
if (OB_FAIL(sql_string.assign_fmt(GET_DDL_TASK_SQL
" WHERE object_id = %lu", OB_ALL_DDL_TASK_STATUS_TNAME, table_id))) {
LOG_WARN("assign sql string failed", KR(ret), K(table_id));
} else if (OB_FAIL(DDL_SIM(tenant_id, task_id, TASK_STATUS_OPERATOR_SLOW))) {
LOG_WARN("ddl sim failure: slow inner sql", K(ret), K(tenant_id), K(task_id));
} else if (OB_FAIL(DDL_SIM(tenant_id, task_id, QUERY_TASK_RECORD_CHECK_CONFLICT_DDL_FAILED))) {
@ -3962,9 +3992,8 @@ int ObDDLTaskRecordOperator::get_ddl_task_record(const uint64_t tenant_id,
if (OB_UNLIKELY(!proxy.is_inited())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(proxy.is_inited()));
} else if (OB_FAIL(sql_string.assign_fmt(" SELECT time_to_usec(gmt_create) AS create_time, tenant_id, task_id, object_id, target_object_id, ddl_type, "
"schema_version, parent_task_id, trace_id, status, snapshot_version, task_version, execution_id, "
"UNHEX(ddl_stmt_str) as ddl_stmt_str_unhex, ret_code, UNHEX(message) as message_unhex FROM %s WHERE task_id=%lu", OB_ALL_DDL_TASK_STATUS_TNAME, task_id))) {
} else if (OB_FAIL(sql_string.assign_fmt(GET_DDL_TASK_SQL
" WHERE task_id=%lu ", OB_ALL_DDL_TASK_STATUS_TNAME, task_id))) {
LOG_WARN("assign sql string failed", K(ret), K(task_id));
} else if (OB_FAIL(get_task_record(tenant_id, sql_string, proxy, allocator, task_records))) {
LOG_WARN("get task record failed", K(ret), K(sql_string));
@ -3991,9 +4020,7 @@ int ObDDLTaskRecordOperator::get_all_ddl_task_record(common::ObMySQLProxy &proxy
if (OB_UNLIKELY(!proxy.is_inited())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(proxy.is_inited()));
} else if (OB_FAIL(sql_string.assign_fmt(" SELECT time_to_usec(gmt_create) AS create_time, tenant_id, task_id, object_id, target_object_id, ddl_type, "
"schema_version, parent_task_id, trace_id, status, snapshot_version, task_version, execution_id, "
"UNHEX(ddl_stmt_str) as ddl_stmt_str_unhex, ret_code, UNHEX(message) as message_unhex FROM %s ", OB_ALL_VIRTUAL_DDL_TASK_STATUS_TNAME))) {
} else if (OB_FAIL(sql_string.assign_fmt(GET_DDL_TASK_SQL, OB_ALL_VIRTUAL_DDL_TASK_STATUS_TNAME))) {
LOG_WARN("assign sql string failed", K(ret));
} else if (OB_FAIL(get_task_record(OB_INVALID_TENANT_ID, sql_string, proxy, allocator, records))) {
LOG_WARN("get task record failed", K(ret), K(sql_string));
@ -4126,21 +4153,63 @@ int ObDDLTaskRecordOperator::insert_record(
}
}
}
uint64_t tenant_data_version = 0;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(to_hex_str(record.ddl_stmt_str_, ddl_stmt_string))) {
LOG_WARN("append hex escaped ddl stmt string failed", K(ret));
} else if (OB_FAIL(to_hex_str(record.message_, message_string))) {
LOG_WARN("append hex escaped string failed", K(ret));
} else if (OB_FAIL(sql_string.assign_fmt(
" INSERT INTO %s (gmt_create, gmt_modified, task_id, parent_task_id, tenant_id, object_id, schema_version, target_object_id, ddl_type, trace_id, status, task_version, execution_id, ret_code, ddl_stmt_str, message) "
" VALUES (usec_to_time(%lu), usec_to_time(%lu), %lu, %lu, %lu, %lu, %lu, %lu, %d, '%s', %ld, %lu, %ld, %lu, '%.*s', \"%.*s\") ",
OB_ALL_DDL_TASK_STATUS_TNAME, record.gmt_create_, record.gmt_create_, record.task_id_, record.parent_task_id_,
ObSchemaUtils::get_extract_tenant_id(record.tenant_id_, record.tenant_id_), record.object_id_, record.schema_version_,
get_record_id(record.ddl_type_, record.target_object_id_), record.ddl_type_, trace_id_str, record.task_status_, record.task_version_, record.execution_id_, record.ret_code_,
static_cast<int>(ddl_stmt_string.length()), ddl_stmt_string.ptr(), static_cast<int>(message_string.length()), message_string.ptr()))) {
LOG_WARN("assign sql string failed", K(ret), K(record));
} else if (OB_FAIL(DDL_SIM(record.tenant_id_, record.task_id_, TASK_STATUS_OPERATOR_SLOW))) {
} else if (OB_FAIL(GET_MIN_DATA_VERSION(record.tenant_id_, tenant_data_version))) {
LOG_WARN("get tenant data version failed", KR(ret), K_(record.tenant_id));
} else if ((tenant_data_version < DATA_VERSION_4_2_2_0
|| (tenant_data_version >= DATA_VERSION_4_3_0_0 && tenant_data_version < DATA_VERSION_4_3_5_0))
&& record.consensus_schema_version_ != OB_INVALID_VERSION) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("consensus schema version should be invalid before 4220", KR(ret), K_(record.consensus_schema_version));
} else {
ObDMLSqlSplicer dml;
if (OB_FAIL(dml.add_gmt_create(record.gmt_create_))) {
LOG_WARN("fail to add gmt_create", KR(ret), K_(record.gmt_create));
} else if (OB_FAIL(dml.add_gmt_modified(record.gmt_create_))) {
LOG_WARN("fail to add gmt_modified", KR(ret), K_(record.gmt_create));
} else if (OB_FAIL(dml.add_pk_column("task_id", record.task_id_))) {
LOG_WARN("fail to add task_id", KR(ret), K_(record.task_id));
} else if (OB_FAIL(dml.add_column("parent_task_id", record.parent_task_id_))) {
LOG_WARN("fail to add parent_task_id", KR(ret), K_(record.parent_task_id));
} else if (OB_FAIL(dml.add_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(record.tenant_id_, record.tenant_id_)))) {
LOG_WARN("fail to add tenant_id", KR(ret), K_(record.tenant_id));
} else if (OB_FAIL(dml.add_column("object_id", record.object_id_))) {
LOG_WARN("fail to add object_id", KR(ret), K_(record.object_id));
} else if (OB_FAIL(dml.add_column("schema_version", record.schema_version_))) {
LOG_WARN("fail to add schema_version", KR(ret), K_(record.schema_version));
} else if (OB_FAIL(dml.add_column("target_object_id", get_record_id(record.ddl_type_, record.target_object_id_)))) {
LOG_WARN("fail to add target_object_id", KR(ret), K_(record.ddl_type), K_(record.target_object_id));
} else if (OB_FAIL(dml.add_column("ddl_type", record.ddl_type_))) {
LOG_WARN("fail to add ddl_type", KR(ret), K_(record.ddl_type));
} else if (OB_FAIL(dml.add_column("trace_id", trace_id_str))) {
LOG_WARN("fail to add trace_id", KR(ret), K(trace_id_str));
} else if (OB_FAIL(dml.add_column("status", record.task_status_))) {
LOG_WARN("fail to add status", KR(ret), K_(record.task_status));
} else if (OB_FAIL(dml.add_column("task_version", record.task_version_))) {
LOG_WARN("fail to add task_version", KR(ret), K_(record.task_version));
} else if (OB_FAIL(dml.add_column("execution_id", record.execution_id_))) {
LOG_WARN("fail to add execution_id", KR(ret), K_(record.execution_id));
} else if (OB_FAIL(dml.add_column("ret_code", record.ret_code_))) {
LOG_WARN("fail to add ret_code", KR(ret), K_(record.ret_code));
} else if (OB_FAIL(dml.add_column("ddl_stmt_str", ddl_stmt_string.string()))) {
LOG_WARN("fail to add ddl_stmt_str", KR(ret), K(ddl_stmt_string));
} else if (OB_FAIL(dml.add_column("message", message_string.string()))) {
LOG_WARN("fail to add message", KR(ret), K(message_string));
} else if (((tenant_data_version >= DATA_VERSION_4_2_2_0 && tenant_data_version < DATA_VERSION_4_3_0_0)
|| (tenant_data_version >= DATA_VERSION_4_3_5_0))
&& OB_FAIL(dml.add_column("consensus_schema_version", record.consensus_schema_version_))) {
LOG_WARN("fail to add consensus_schema_version", KR(ret), K_(record.consensus_schema_version));
} else if (OB_FAIL(dml.splice_insert_sql(OB_ALL_DDL_TASK_STATUS_TNAME, sql_string))) {
LOG_WARN("fail to generate sql string", KR(ret));
}
}
if (FAILEDx(DDL_SIM(record.tenant_id_, record.task_id_, TASK_STATUS_OPERATOR_SLOW))) {
LOG_WARN("ddl sim failure: slow inner sql", K(ret), K(record.tenant_id_), K(record.task_id_));
} else if (OB_FAIL(proxy.write(record.tenant_id_, sql_string.ptr(), affected_rows))) {
LOG_WARN("insert ddl task record failed", K(ret), K(sql_string), K(record));
@ -4186,6 +4255,9 @@ int ObDDLTaskRecordOperator::fill_task_record(
EXTRACT_INT_FIELD_MYSQL(*result_row, "execution_id", task_record.execution_id_, int64_t);
EXTRACT_VARCHAR_FIELD_MYSQL(*result_row, "message_unhex", task_message);
EXTRACT_VARCHAR_FIELD_MYSQL(*result_row, "ddl_stmt_str_unhex", ddl_stmt_str);
EXTRACT_INT_FIELD_MYSQL_WITH_DEFAULT_VALUE(*result_row, "consensus_schema_version", task_record.consensus_schema_version_, int64_t,
false /*skip null error*/, true /*skip column error*/, OB_INVALID_VERSION);
if (OB_SUCC(ret) && OB_INVALID_TENANT_ID != tenant_id) {
if (OB_INVALID_TENANT_ID != task_record.tenant_id_) {
ret = OB_ERR_UNEXPECTED;

View File

@ -79,7 +79,7 @@ public:
void reset();
TO_STRING_KV(K_(task_id), K_(parent_task_id), K_(ddl_type), K_(trace_id), K_(task_status), K_(tenant_id), K_(object_id),
K_(schema_version), K_(target_object_id), K_(snapshot_version), K_(message), K_(task_version), K_(ret_code), K_(execution_id),
K_(ddl_need_retry_at_executor));
K_(ddl_need_retry_at_executor), K_(consensus_schema_version));
public:
static const int64_t MAX_MESSAGE_LENGTH = 4096;
typedef common::ObFixedLengthString<MAX_MESSAGE_LENGTH> TaskMessage;
@ -101,8 +101,10 @@ public:
int64_t execution_id_;
ObString ddl_stmt_str_;
bool ddl_need_retry_at_executor_;
int64_t consensus_schema_version_;
};
struct ObDDLTaskInfo final
{
public:
@ -279,6 +281,8 @@ public:
class ObDDLTaskRecordOperator final
{
#define GET_DDL_TASK_SQL " SELECT *, time_to_usec(gmt_create) AS create_time, " \
" UNHEX(ddl_stmt_str) as ddl_stmt_str_unhex, UNHEX(message) as message_unhex FROM %s "
public:
static int update_task_status(
common::ObISQLClient &proxy,
@ -324,6 +328,11 @@ public:
const int ret_code,
ObString &message);
static int update_consensus_schema_version(
common::ObISQLClient &proxy,
const uint64_t tenant_id,
const int64_t task_id,
const int64_t consensus_schema_version);
static int update_parent_task_message(
const int64_t tenant_id,
const int64_t parent_task_id,
@ -678,7 +687,8 @@ public:
parent_task_id_(0), parent_task_key_(), task_version_(0), parallelism_(0),
allocator_(lib::ObLabel("DdlTask")), compat_mode_(lib::Worker::CompatMode::INVALID), err_code_occurence_cnt_(0),
longops_stat_(nullptr), gmt_create_(0), stat_info_(), delay_schedule_time_(0), next_schedule_ts_(0),
execution_id_(-1), start_time_(0), data_format_version_(0), is_pre_split_(false), wait_trans_ctx_()
execution_id_(-1), start_time_(0), data_format_version_(0), is_pre_split_(false), wait_trans_ctx_(), is_unique_index_(false),
is_global_index_(false), consensus_schema_version_(OB_INVALID_VERSION)
{}
ObDDLTask():
ObDDLTask(share::DDL_INVALID)
@ -774,6 +784,9 @@ public:
virtual bool support_longops_monitoring() const { return false; }
int cleanup();
int update_task_record_status_and_msg(common::ObISQLClient &proxy, const share::ObDDLTaskStatus real_new_status);
bool is_unique_index() { return is_unique_index_; }
bool is_global_index() { return is_global_index_; }
int64_t get_consensus_schema_version() { return consensus_schema_version_; }
#ifdef ERRSIM
int check_errsim_error();
@ -786,7 +799,7 @@ public:
K_(task_version), K_(parallelism), K_(ddl_stmt_str), K_(compat_mode),
K_(sys_task_id), K_(err_code_occurence_cnt), K_(stat_info),
K_(next_schedule_ts), K_(delay_schedule_time), K(execution_id_), K(sql_exec_addrs_), K_(data_format_version), K(consumer_group_id_),
K_(dst_tenant_id), K_(dst_schema_version), K_(is_pre_split));
K_(dst_tenant_id), K_(dst_schema_version), K_(is_pre_split), K_(is_unique_index), K_(is_global_index), K_(consensus_schema_version));
static const int64_t MAX_ERR_TOLERANCE_CNT = 3L; // Max torlerance count for error code.
static const int64_t DEFAULT_TASK_IDLE_TIME_US = 10L * 1000L; // 10ms
protected:
@ -868,6 +881,9 @@ protected:
int64_t consumer_group_id_;
bool is_pre_split_;
ObDDLWaitTransEndCtx wait_trans_ctx_;
bool is_unique_index_;
bool is_global_index_;
int64_t consensus_schema_version_;
};
enum ColChecksumStat

View File

@ -149,6 +149,7 @@ int ObDropIndexTask::update_index_status(const ObIndexStatus new_status)
arg.status_ = new_status;
arg.exec_tenant_id_ = tenant_id_;
arg.in_offline_ddl_white_list_ = index_schema->get_table_state_flag() != TABLE_STATE_NORMAL;
arg.data_table_id_ = index_schema->get_data_table_id();
int64_t ddl_rpc_timeout = 0;
int64_t table_id = index_schema->get_table_id();
DEBUG_SYNC(BEFORE_UPDATE_GLOBAL_INDEX_STATUS);

View File

@ -258,7 +258,7 @@ ObAsyncTask *ObIndexSSTableBuildTask::deep_copy(char *buf, const int64_t buf_siz
/*************** ObIndexBuildTask *************/
ObIndexBuildTask::ObIndexBuildTask()
: ObDDLTask(ObDDLType::DDL_CREATE_INDEX), index_table_id_(target_object_id_), doc_id_col_id_(OB_INVALID_ID), is_unique_index_(false), is_global_index_(false), root_service_(nullptr), snapshot_held_(false),
: ObDDLTask(ObDDLType::DDL_CREATE_INDEX), index_table_id_(target_object_id_), root_service_(nullptr), snapshot_held_(false),
is_sstable_complete_task_submitted_(false), sstable_complete_request_time_(0), sstable_complete_ts_(0),
check_unique_snapshot_(0), complete_sstable_job_ret_code_(INT64_MAX), create_index_arg_(), target_cg_cnt_(0)
{
@ -423,12 +423,6 @@ int ObIndexBuildTask::init(
data_format_version_ = tenant_data_version;
if (OB_SUCC(ret)) {
task_status_ = static_cast<ObDDLTaskStatus>(task_status);
if (share::schema::is_rowkey_doc_aux(create_index_arg_.index_type_) ||
share::schema::is_doc_rowkey_aux(create_index_arg_.index_type_)) {
if (OB_FAIL(ObFtsIndexBuilderUtil::get_doc_id_column_id(data_table_schema, doc_id_col_id_))) {
LOG_WARN("failed to get doc id column id", K(ret));
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(init_ddl_task_monitor_info(index_schema->get_table_id()))) {
@ -456,48 +450,45 @@ int ObIndexBuildTask::init(const ObDDLTaskRecord &task_record)
const uint64_t index_table_id = task_record.target_object_id_;
const int64_t schema_version = task_record.schema_version_;
int64_t pos = 0;
const ObTableSchema *data_schema = nullptr;
const ObTableSchema *index_schema = nullptr;
const char *ddl_type_str = nullptr;
const char *target_name = nullptr;
ObSchemaGetterGuard schema_guard;
if (OB_UNLIKELY(is_inited_)) {
ret = OB_INIT_TWICE;
LOG_WARN("init twice", K(ret));
LOG_WARN("init twice", KR(ret));
} else if (OB_ISNULL(root_service_ = GCTX.root_service_)) {
ret = OB_ERR_SYS;
LOG_WARN("root_service is null", K(ret), KP(root_service_));
LOG_WARN("root_service is null", KR(ret), KP(root_service_));
} else if (!root_service_->in_service()) {
ret = OB_STATE_NOT_MATCH;
LOG_WARN("root service not in service", K(ret));
LOG_WARN("root service not in service", KR(ret));
} else if (!task_record.is_valid()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(task_record));
LOG_WARN("invalid arguments", KR(ret), K(task_record));
} else if (OB_FAIL(DDL_SIM(task_record.tenant_id_, task_record.task_id_, DDL_TASK_INIT_BY_RECORD_FAILED))) {
LOG_WARN("ddl sim failure", K(task_record.tenant_id_), K(task_record.task_id_));
} else if (OB_FAIL(deserialize_params_from_message(task_record.tenant_id_, task_record.message_.ptr(), task_record.message_.length(), pos))) {
LOG_WARN("deserialize params from message failed", K(ret));
} else if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(
task_record.tenant_id_, schema_guard, schema_version))) {
LOG_WARN("fail to get schema guard", K(ret), K(index_table_id), K(schema_version));
} else if (OB_FAIL(schema_guard.check_formal_guard())) {
LOG_WARN("schema_guard is not formal", K(ret), K(index_table_id));
} else if (OB_FAIL(schema_guard.get_table_schema(task_record.tenant_id_, data_table_id, data_schema))) {
LOG_WARN("fail to get table schema", K(ret), K(data_table_id));
} else if (OB_FAIL(schema_guard.get_table_schema(task_record.tenant_id_, index_table_id, index_schema))) {
LOG_WARN("fail to get table schema", K(ret), K(index_table_id));
} else if (OB_ISNULL(data_schema) || OB_ISNULL(index_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("fail to get table schema", K(ret), K(data_schema), K(index_schema));
} else if (OB_UNLIKELY((ObIndexArg::ADD_MLOG == create_index_arg_.index_action_type_)
&& (!index_schema->is_mlog_table()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index action is add_mlog but index schema is not mlog",
KR(ret), K(create_index_arg_.index_action_type_), K(index_schema->get_table_type()));
} else {
LOG_WARN("deserialize params from message failed", KR(ret));
} else if (ObIndexArg::ADD_MLOG == create_index_arg_.index_action_type_) {
ObSchemaGetterGuard schema_guard;
const ObTableSchema *index_schema = nullptr;
if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(
task_record.tenant_id_, schema_guard, schema_version))) {
LOG_WARN("fail to get schema guard", KR(ret), K(index_table_id), K(schema_version));
} else if (OB_FAIL(schema_guard.check_formal_guard())) {
LOG_WARN("schema_guard is not formal", KR(ret), K(index_table_id));
} else if (OB_FAIL(schema_guard.get_table_schema(task_record.tenant_id_, index_table_id, index_schema))) {
LOG_WARN("fail to get table schema", KR(ret), K(index_table_id));
} else if (OB_ISNULL(index_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("fail to get table schema", KR(ret));
} else if (OB_UNLIKELY((!index_schema->is_mlog_table()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index action is add_mlog but index schema is not mlog",
KR(ret), K(create_index_arg_.index_action_type_), K(index_schema->get_table_type()));
}
}
if (OB_SUCC(ret)) {
task_type_ = task_record.ddl_type_;
is_global_index_ = index_schema->is_global_index_table();
is_unique_index_ = index_schema->is_unique_index();
tenant_id_ = task_record.tenant_id_;
object_id_ = data_table_id;
index_table_id_ = index_table_id;
@ -506,7 +497,7 @@ int ObIndexBuildTask::init(const ObDDLTaskRecord &task_record)
execution_id_ = task_record.execution_id_;
task_status_ = static_cast<ObDDLTaskStatus>(task_record.task_status_);
task_type_ = task_record.ddl_type_; // could be create index / mlog
consensus_schema_version_ = task_record.consensus_schema_version_;
if (ObDDLTaskStatus::VALIDATE_CHECKSUM == task_status_) {
sstable_complete_ts_ = ObTimeUtility::current_time();
}
@ -517,15 +508,9 @@ int ObIndexBuildTask::init(const ObDDLTaskRecord &task_record)
dst_tenant_id_ = tenant_id_;
dst_schema_version_ = schema_version_;
if (share::schema::is_rowkey_doc_aux(create_index_arg_.index_type_) ||
share::schema::is_doc_rowkey_aux(create_index_arg_.index_type_)) {
if (OB_FAIL(ObFtsIndexBuilderUtil::get_doc_id_column_id(data_schema, doc_id_col_id_))) {
LOG_WARN("failed to get doc id column id", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(init_ddl_task_monitor_info(index_schema->get_table_id()))) {
LOG_WARN("init ddl task monitor info failed", K(ret));
} else if (OB_FAIL(init_ddl_task_monitor_info(index_table_id))) {
LOG_WARN("init ddl task monitor info failed", KR(ret));
} else {
is_inited_ = true;
@ -601,6 +586,15 @@ int ObIndexBuildTask::check_health()
} else if (ObIndexStatus::INDEX_STATUS_INDEX_ERROR == index_schema->get_index_status()) {
ret = OB_SUCCESS == ret_code_ ? OB_ERR_ADD_INDEX : ret_code_;
LOG_WARN("index status error", K(ret), K(index_table_id_), K(index_schema->get_table_name_str()), K(index_schema->get_index_status()));
} else if (data_format_version_ < MOCK_DATA_VERSION_4_2_4_0
|| (data_format_version_ >= DATA_VERSION_4_3_0_0 && data_format_version_ < DATA_VERSION_4_3_5_0)) {
// Since parallel ddl do not guaranteen the local schema guard could get the index schema when do init(),
// the initialization of is_global/unique_index in init() are modified to rely on the persistence of
// relative field in task_record.message_.
// However, the task_record constructed before the upgrade process do not have the persistence of relative field.
// Thus, need to initialize is_global/unique_index here.
is_global_index_ = index_schema->is_global_index_table();
is_unique_index_ = index_schema->is_unique_index();
}
#ifdef ERRSIM
if (OB_SUCC(ret)) {
@ -1041,9 +1035,9 @@ int ObIndexBuildTask::wait_data_complement()
share::ObLSID ls_id;
common::ObAddr leader_addr;
ObArray<ObTabletID> index_partition_ids;
if (OB_UNLIKELY(!is_inited_)) {
if (OB_UNLIKELY(!is_inited_) || OB_ISNULL(root_service_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", K(ret));
LOG_WARN("not init", KR(ret));
} else if (ObDDLTaskStatus::REDEFINITION != task_status_) {
LOG_WARN("task status not match", K(ret), K(task_status_));
} else if (OB_UNLIKELY(snapshot_version_ <= 0)) {
@ -1092,9 +1086,25 @@ int ObIndexBuildTask::wait_data_complement()
}
#endif
ObArray<int64_t> ignore_col_ids;
if (doc_id_col_id_ != OB_INVALID &&
OB_FAIL(ignore_col_ids.push_back(doc_id_col_id_))) {
LOG_WARN("failed to push back to ignore_col_ids", K(ret));
const ObTableSchema *data_table_schema = nullptr;
ObMultiVersionSchemaService &schema_service = root_service_->get_schema_service();
share::schema::ObSchemaGetterGuard schema_guard;
uint64_t doc_id_col_id = OB_INVALID_ID;
if (share::schema::is_rowkey_doc_aux(create_index_arg_.index_type_) ||
share::schema::is_doc_rowkey_aux(create_index_arg_.index_type_)) {
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("get tenant schema guard failed", KR(ret));
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, object_id_, data_table_schema))) {
LOG_WARN("get table schema failed", KR(ret), K(object_id_));
} else if (OB_ISNULL(data_table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("data table not exist", KR(ret));
} else if (OB_FAIL(ObFtsIndexBuilderUtil::get_doc_id_column_id(data_table_schema, doc_id_col_id))) {
LOG_WARN("failed to get doc id column id", KR(ret));
} else if (doc_id_col_id != OB_INVALID &&
OB_FAIL(ignore_col_ids.push_back(doc_id_col_id))) {
LOG_WARN("failed to push back to ignore_col_ids", KR(ret));
}
}
if (OB_FAIL(ret)) {
} else if (need_verify_checksum && OB_FAIL(ObDDLChecksumOperator::check_column_checksum(
@ -1120,9 +1130,9 @@ int ObIndexBuildTask::wait_local_index_data_complement()
int ret = OB_SUCCESS;
bool state_finished = false;
bool is_request_end = false;
if (OB_UNLIKELY(!is_inited_)) {
if (OB_UNLIKELY(!is_inited_) || OB_ISNULL(root_service_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", K(ret));
LOG_WARN("not init", KR(ret));
} else if (ObDDLTaskStatus::REDEFINITION != task_status_) {
ret = OB_STATE_NOT_MATCH;
LOG_WARN("task status not match", K(ret), K(task_status_));
@ -1163,10 +1173,27 @@ int ObIndexBuildTask::wait_local_index_data_complement()
// when the major compaction is delayed, skip verify column checksum
need_verify_checksum = 0 == GCONF.errsim_ddl_major_delay_time;
#endif
ObArray<int64_t> ignore_col_ids;
if (doc_id_col_id_ != OB_INVALID &&
OB_FAIL(ignore_col_ids.push_back(doc_id_col_id_))) {
LOG_WARN("failed to push back to ignore_col_ids", K(ret));
const ObTableSchema *data_table_schema = nullptr;
uint64_t doc_id_col_id = OB_INVALID_ID;
share::schema::ObSchemaGetterGuard schema_guard;
ObMultiVersionSchemaService &schema_service = root_service_->get_schema_service();
if (share::schema::is_rowkey_doc_aux(create_index_arg_.index_type_) ||
share::schema::is_doc_rowkey_aux(create_index_arg_.index_type_)) {
if (OB_FAIL(schema_service.get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("get tenant schema guard failed", KR(ret));
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, object_id_, data_table_schema))) {
LOG_WARN("get table schema failed", KR(ret), K(object_id_));
} else if (OB_ISNULL(data_table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("data table not exist", KR(ret));
} else if (OB_FAIL(ObFtsIndexBuilderUtil::get_doc_id_column_id(data_table_schema, doc_id_col_id))) {
LOG_WARN("failed to get doc id column id", KR(ret));
} else if (doc_id_col_id != OB_INVALID &&
OB_FAIL(ignore_col_ids.push_back(doc_id_col_id))) {
LOG_WARN("failed to push back to ignore_col_ids", KR(ret));
}
}
if (OB_FAIL(ret)) {
} else if (need_verify_checksum && OB_FAIL(ObDDLChecksumOperator::check_column_checksum_without_execution_id(
@ -1506,7 +1533,7 @@ int ObIndexBuildTask::enable_index()
} else if ((ObIndexArg::ADD_MLOG == create_index_arg_.index_action_type_)
&& OB_FAIL(update_mlog_last_purge_scn())) {
LOG_WARN("failed to update mlog last purge scn", KR(ret));
} else if (OB_FAIL(update_index_status_in_schema(*index_schema, INDEX_STATUS_AVAILABLE))) {
} else if (OB_FAIL(update_index_status_in_schema(*index_schema, INDEX_STATUS_AVAILABLE, schema_guard))) {
LOG_WARN("fail to try notify index take effect", K(ret), K(index_table_id_));
} else {
state_finished = true;
@ -1525,12 +1552,19 @@ int ObIndexBuildTask::enable_index()
return ret;
}
int ObIndexBuildTask::update_index_status_in_schema(const ObTableSchema &index_schema, const ObIndexStatus new_status)
int ObIndexBuildTask::update_index_status_in_schema(const ObTableSchema &index_schema, const ObIndexStatus new_status,
ObSchemaGetterGuard &schema_guard)
{
int ret = OB_SUCCESS;
const ObDatabaseSchema *database_schema = nullptr;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", K(ret));
} else if (OB_FAIL(schema_guard.get_database_schema(tenant_id_, index_schema.get_database_id(), database_schema))) {
LOG_WARN("fail to get database schema", KR(ret), K(tenant_id_), K(index_schema.get_database_id()));
} else if (OB_ISNULL(database_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("database schema is nullptr", KR(ret));
} else {
obrpc::ObUpdateIndexStatusArg arg;
arg.index_table_id_ = index_schema.get_table_id();
@ -1538,6 +1572,8 @@ int ObIndexBuildTask::update_index_status_in_schema(const ObTableSchema &index_s
arg.exec_tenant_id_ = tenant_id_;
arg.in_offline_ddl_white_list_ = true;
arg.task_id_ = task_id_;
arg.data_table_id_ = index_schema.get_data_table_id();
arg.database_name_ = database_schema->get_database_name();
int64_t ddl_rpc_timeout = 0;
int64_t tmp_timeout = 0;
if (INDEX_STATUS_AVAILABLE == new_status) {
@ -1558,18 +1594,35 @@ int ObIndexBuildTask::update_index_status_in_schema(const ObTableSchema &index_s
}
DEBUG_SYNC(BEFORE_UPDATE_GLOBAL_INDEX_STATUS);
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ObDDLUtil::get_ddl_rpc_timeout(index_schema.get_all_part_num(), ddl_rpc_timeout))) {
if (FAILEDx(ObDDLUtil::get_ddl_rpc_timeout(index_schema.get_all_part_num(), ddl_rpc_timeout))) {
LOG_WARN("get ddl rpc timeout fail", K(ret));
} else if (OB_FAIL(ObDDLUtil::get_ddl_rpc_timeout(tenant_id_, index_schema.get_data_table_id(), tmp_timeout))) {
LOG_WARN("get ddl rpc timeout fail", K(ret));
} else if (OB_FALSE_IT(ddl_rpc_timeout += tmp_timeout)) {
} else if (OB_FAIL(DDL_SIM(tenant_id_, task_id_, UPDATE_INDEX_STATUS_FAILED))) {
LOG_WARN("ddl sim failure", K(ret), K(tenant_id_), K(task_id_));
} else if (OB_FAIL(root_service_->get_common_rpc_proxy().to(GCTX.self_addr()).timeout(ddl_rpc_timeout).update_index_status(arg))) {
LOG_WARN("update index status failed", K(ret), K(arg));
} else {
LOG_INFO("notify index status changed finish", K(new_status), K(index_table_id_), K(ddl_rpc_timeout), "ddl_stmt_str", arg.ddl_stmt_str_);
const bool is_parallel = create_index_arg_.is_parallel_;
if (!is_parallel
|| data_format_version_ < DATA_VERSION_4_2_2_0
|| (data_format_version_ >= DATA_VERSION_4_3_3_0 && data_format_version_ < DATA_VERSION_4_3_5_0)) {
if (OB_FAIL(root_service_->get_common_rpc_proxy().to(GCTX.self_addr()).timeout(ddl_rpc_timeout).update_index_status(arg))) {
LOG_WARN("update index status failed", K(ret), K(arg));
}
} else {
obrpc::ObParallelDDLRes res;
ObTimeoutCtx ctx;
if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, GCONF._ob_ddl_timeout))) {
LOG_WARN("fail to set timeout ctx", KR(ret));
} else if (OB_FAIL(root_service_->get_common_rpc_proxy().to(GCTX.self_addr()).timeout(ddl_rpc_timeout).parallel_update_index_status(arg, res))) {
LOG_WARN("fail to parallel update index status", KR(ret), K(arg));
} else {
consensus_schema_version_ = res.schema_version_;
}
}
if (OB_SUCC(ret)) {
LOG_INFO("notify index status changed finish", K(new_status), K(index_table_id_), K(ddl_rpc_timeout), "ddl_stmt_str", arg.ddl_stmt_str_);
}
}
}
return ret;
@ -1592,7 +1645,7 @@ int ObIndexBuildTask::clean_on_failed()
ObSchemaGetterGuard schema_guard;
bool drop_index_on_failed = true; // TODO@wenqu: index building triggered by truncate partition may need keep the failed index schema
bool index_status_is_available = false;
if (OB_FAIL(root_service_->get_schema_service().get_tenant_schema_guard(tenant_id_, schema_guard))) {
if (OB_FAIL(root_service_->get_ddl_service().get_tenant_schema_guard_with_version_in_inner_table(tenant_id_, schema_guard))) {
LOG_WARN("get tenant schema failed", K(ret), K(tenant_id_));
} else if (OB_FAIL(schema_guard.check_table_exist(tenant_id_, index_table_id_, is_index_exist))) {
LOG_WARN("check table exist failed", K(ret), K_(tenant_id), K(index_table_id_));
@ -1606,7 +1659,7 @@ int ObIndexBuildTask::clean_on_failed()
} else if (index_schema->is_in_recyclebin()) {
// the index has been dropped, just finish this task
} else if (ObIndexStatus::INDEX_STATUS_UNAVAILABLE == index_schema->get_index_status()
&& OB_FAIL(update_index_status_in_schema(*index_schema, ObIndexStatus::INDEX_STATUS_INDEX_ERROR))) {
&& OB_FAIL(update_index_status_in_schema(*index_schema, ObIndexStatus::INDEX_STATUS_INDEX_ERROR, schema_guard))) {
LOG_WARN("update index schema failed", K(ret));
} else if (drop_index_on_failed) {
DEBUG_SYNC(CREATE_INDEX_FAILED);

View File

@ -124,7 +124,7 @@ public:
virtual int64_t get_serialize_param_size() const override;
virtual bool support_longops_monitoring() const override { return true; }
static int deep_copy_index_arg(common::ObIAllocator &allocator, const obrpc::ObCreateIndexArg &source_arg, obrpc::ObCreateIndexArg &dest_arg);
INHERIT_TO_STRING_KV("ObDDLTask", ObDDLTask, K(index_table_id_), K(doc_id_col_id_), K(snapshot_held_), K(is_sstable_complete_task_submitted_), K(sstable_complete_request_time_),
INHERIT_TO_STRING_KV("ObDDLTask", ObDDLTask, K(index_table_id_), K(snapshot_held_), K(is_sstable_complete_task_submitted_), K(sstable_complete_request_time_),
K(sstable_complete_ts_), K(check_unique_snapshot_), K(complete_sstable_job_ret_code_), K_(redefinition_execution_id), K(create_index_arg_), K(target_cg_cnt_));
private:
int prepare();
@ -141,7 +141,8 @@ private:
int release_snapshot(const int64_t snapshot);
int update_index_status_in_schema(
const share::schema::ObTableSchema &index_schema,
const share::schema::ObIndexStatus new_status);
const share::schema::ObIndexStatus new_status,
ObSchemaGetterGuard &schema_guard);
int check_health();
int reap_old_replica_build_task(bool &need_exec_new_inner_sql);
int send_build_single_replica_request(const bool &is_partitioned_local_index_task,
@ -170,9 +171,6 @@ private:
using ObDDLTask::schema_version_;
using ObDDLTask::snapshot_version_;
uint64_t &index_table_id_;
uint64_t doc_id_col_id_;
bool is_unique_index_;
bool is_global_index_;
ObRootService *root_service_;
bool snapshot_held_;
bool is_sstable_complete_task_submitted_;

View File

@ -485,7 +485,8 @@ ObNewTableTabletAllocator::ObNewTableTabletAllocator(
const uint64_t tenant_id,
share::schema::ObSchemaGetterGuard &schema_guard,
common::ObMySQLProxy *sql_proxy,
const bool use_parallel_ddl /*= false*/)
const bool use_parallel_ddl /*= false*/,
const share::schema::ObTableSchema *data_table_schema /*nullptr*/)
: tenant_id_(tenant_id),
schema_guard_(schema_guard),
sql_proxy_(sql_proxy),
@ -494,7 +495,8 @@ ObNewTableTabletAllocator::ObNewTableTabletAllocator(
ls_id_array_(),
inited_(false),
is_add_partition_(false),
use_parallel_ddl_(use_parallel_ddl)
use_parallel_ddl_(use_parallel_ddl),
data_table_schema_(data_table_schema)
{
}
@ -1226,9 +1228,22 @@ int ObNewTableTabletAllocator::alloc_ls_for_local_index_tablet(
const uint64_t tenant_id = index_schema.get_tenant_id();
const uint64_t data_table_id = index_schema.get_data_table_id();
const share::schema::ObTableSchema *table_schema = nullptr;
if (OB_FAIL(schema_guard_.get_table_schema(
tenant_id, data_table_id, table_schema))) {
LOG_WARN("fail to get table schema", KR(ret), K(tenant_id), K(data_table_id));
if (use_parallel_ddl_) {
if (OB_ISNULL(data_table_schema_)) {
ret = OB_NOT_INIT;
LOG_WARN("should use cached data_table_schema when alloc ls for local index tablet when doing parallel ddl", KR(ret));
} else if (OB_UNLIKELY(data_table_schema_->get_table_id() != data_table_id)) {
LOG_WARN("fail to get table schema", KR(ret), K(data_table_schema_->get_table_id()) ,K(data_table_id));
} else {
table_schema = data_table_schema_;
}
} else {
if (OB_FAIL(schema_guard_.get_table_schema(
tenant_id, data_table_id, table_schema))) {
LOG_WARN("fail to get table schema", KR(ret), K(tenant_id), K(data_table_id));
}
}
if (OB_FAIL(ret)) {
} else if (OB_UNLIKELY(nullptr == table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("table not exist", KR(ret), K(data_table_id));

View File

@ -156,11 +156,14 @@ private:
class ObNewTableTabletAllocator
{
public:
// when doing prepare() during parallel create local index, the data table should be the latest.
// thus, need the data_table_schema from the latest_schema_guard.
ObNewTableTabletAllocator(
const uint64_t tenant_id,
share::schema::ObSchemaGetterGuard &schema_guard,
common::ObMySQLProxy *sql_proxy,
const bool use_parallel_ddl = false);
const bool use_parallel_ddl = false,
const share::schema::ObTableSchema *data_table_schema = nullptr);
virtual ~ObNewTableTabletAllocator();
public:
int init();
@ -277,6 +280,7 @@ private:
bool is_add_partition_;
static int64_t alloc_tablet_ls_offset_;
bool use_parallel_ddl_;
const share::schema::ObTableSchema *data_table_schema_;
};
}//end namespace rootserver

View File

@ -126,6 +126,7 @@
#include "rootserver/restore/ob_tenant_clone_util.h"
#include "rootserver/ob_split_partition_helper.h"
#include "rootserver/mview/ob_mview_dependency_service.h"
#include "rootserver/parallel_ddl/ob_ddl_helper.h"
#include "storage/ddl/ob_ddl_alter_auto_part_attr.h"
#include "share/tablet/ob_tablet_to_ls_operator.h"
#include "share/tablet/ob_tablet_to_table_history_operator.h"
@ -23720,17 +23721,26 @@ int ObDDLService::check_is_foreign_key_parent_table(const ObTableSchema &table_s
return ret;
}
int ObDDLService::check_table_schema_is_legal(const ObDatabaseSchema & database_schema,
int ObDDLService::check_table_schema_is_legal(const obrpc::ObTruncateTableArg &arg,
const ObDatabaseSchema & database_schema,
const ObTableSchema &table_schema,
const bool check_foreign_key,
ObMySQLTransaction &trans)
{
int ret = OB_SUCCESS;
int64_t table_id = table_schema.get_table_id();
const int64_t table_id = table_schema.get_table_id();
ObString table_name = table_schema.get_table_name();
ObString database_name = database_schema.get_database_name();
if (table_schema.is_in_recyclebin() || database_schema.is_in_recyclebin()) {
if (OB_UNLIKELY(table_schema.get_database_id() != database_schema.get_database_id())) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("table databse id not equal to database schema", KR(ret),
K(table_schema.get_database_id()),
K(database_schema.get_database_id()));
} else if (OB_UNLIKELY(database_schema.get_database_name_str() != arg.database_name_)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("database_schema's database name not equal to arg", KR(ret), K(database_schema.get_database_name_str()), K_(arg.database_name));
} else if (table_schema.is_in_recyclebin() || database_schema.is_in_recyclebin()) {
ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
LOG_WARN("can not truncate table in recyclebin",
KR(ret), K(table_name), K(table_id), K(database_name));
@ -23841,8 +23851,14 @@ int ObDDLService::new_truncate_table(const obrpc::ObTruncateTableArg &arg,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("trans conn is NULL", KR(ret), K(arg));
// To verify the existence of database and table
} else if (OB_FAIL(ObDDLHelper::obj_lock_database_name(trans, tenant_id, arg.database_name_, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database name", KR(ret), K(tenant_id), K_(arg.database_name));
} else if (OB_FAIL(ObDDLHelper::obj_lock_obj_name(trans, tenant_id, arg.database_name_, arg.table_name_, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock table name", KR(ret), K(tenant_id), K_(arg.database_name), K_(arg.table_name));
} else if (OB_FAIL(check_db_and_table_is_exist(arg, trans, database_id, table_id))) {
LOG_WARN("failed to check database and table exist", KR(ret), K(arg.database_name_), K(arg.table_name_));
} else if (OB_FAIL(ObDDLHelper::obj_lock_obj_id(trans, tenant_id, database_id, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock databse id", KR(ret), K(tenant_id), K(database_id));
} else {
// table lock
ObTableSchema orig_table_schema;
@ -23853,9 +23869,11 @@ int ObDDLService::new_truncate_table(const obrpc::ObTruncateTableArg &arg,
schema_status.tenant_id_ = tenant_id;
int64_t before_table_lock = ObTimeUtility::current_time();
bool lock_table_not_allow = false;
LOG_INFO("truncate cost after trans start and check_db_table_is_exist", KR(ret), "cost_ts", before_table_lock - start_time);
LOG_INFO("truncate cost after trans start, lock database name, lock table name, and check_db_table_is_exist", KR(ret), "cost_ts", before_table_lock - start_time);
// try lock
if (OB_FAIL(ObInnerConnectionLockUtil::lock_table(tenant_id,
if (OB_FAIL(ObDDLHelper::obj_lock_obj_id(trans, tenant_id, table_id, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock table id", KR(ret), K(tenant_id), K(table_id));
} else if (OB_FAIL(ObInnerConnectionLockUtil::lock_table(tenant_id,
table_id,
EXCLUSIVE,
0,
@ -23867,29 +23885,14 @@ int ObDDLService::new_truncate_table(const obrpc::ObTruncateTableArg &arg,
lock_table_not_allow = true;
}
}
uint64_t compat_version = 0;
int64_t after_table_lock = ObTimeUtility::current_time();
LOG_INFO("truncate cost after lock table", KR(ret), "cost_ts", after_table_lock - before_table_lock);
LOG_INFO("truncate cost after lock table id and lock table", KR(ret), "cost_ts", after_table_lock - before_table_lock);
if (FAILEDx(schema_service->get_db_schema_from_inner_table(schema_status, database_id, database_schema_array, trans))){
LOG_WARN("fail to get database schema", KR(ret), K(arg.database_name_), K(database_id));
// get table full scehma
} else if (OB_FAIL(schema_service->get_full_table_schema_from_inner_table(schema_status, table_id, orig_table_schema, allocator, trans))) {
LOG_WARN("fail to get table schema", KR(ret), K(arg.table_name_), K(table_id));
// in upgrade, check the data_version to prevent from executing wrong logical
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) {
LOG_WARN("get min data_version failed", KR(ret), K(tenant_id));
} else if (compat_version < DATA_VERSION_4_1_0_0) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("server state is not suppported when tenant's data version is below 4.1.0.0", KR(ret), K(compat_version));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant's data version is below 4.1.0.0, truncate table is ");
} else if (orig_table_schema.get_autoinc_column_id() != 0
&& compat_version < DATA_VERSION_4_2_0_0) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("server state is not suppported to use_parallel_truncate when tenant's data version is below 4.2.0.0 "
"and table has autoinc column", KR(ret), K(compat_version), K(tenant_id), K(arg.table_name_));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant's data version is below 4.2.0.0, truncate table with autoinc column is ");
// To verify the args are legal
} else if (OB_FAIL(check_table_schema_is_legal(database_schema_array.at(0), orig_table_schema, arg.foreign_key_checks_, trans))) {
} else if (OB_FAIL(check_table_schema_is_legal(arg, database_schema_array.at(0), orig_table_schema, arg.foreign_key_checks_, trans))) {
LOG_WARN("failed to check table schema is legal",
KR(ret), K(arg.table_name_), K(table_id), K(orig_table_schema.get_schema_version()));
} else if (lock_table_not_allow) {

View File

@ -500,7 +500,8 @@ public:
common::ObArray<const ObTableSchema*> &table_schemas,
ObArenaAllocator &allocator,
ObMySQLTransaction &trans);
int check_table_schema_is_legal(const ObDatabaseSchema & databae_schema,
int check_table_schema_is_legal(const obrpc::ObTruncateTableArg &arg,
const ObDatabaseSchema & databae_schema,
const ObTableSchema &table_schema,
const bool check_foreign_key,
ObMySQLTransaction &trans);

View File

@ -121,6 +121,9 @@
#include "parallel_ddl/ob_create_table_helper.h" // ObCreateTableHelper
#include "parallel_ddl/ob_create_view_helper.h" // ObCreateViewHelper
#include "parallel_ddl/ob_set_comment_helper.h" //ObCommentHelper
#include "parallel_ddl/ob_create_index_helper.h" // ObCreateIndexHelper
#include "parallel_ddl/ob_update_index_status_helper.h" // ObUpdateIndexStatusHelper
namespace oceanbase
{
@ -4539,6 +4542,33 @@ int ObRootService::recover_restore_table_ddl(const obrpc::ObRecoverRestoreTableD
return ret;
}
int ObRootService::set_comment(const obrpc::ObSetCommentArg &arg, obrpc::ObParallelDDLRes &res)
{
LOG_TRACE("receive set comment arg", K(arg));
int64_t begin_time = ObTimeUtility::current_time();
const uint64_t tenant_id = arg.exec_tenant_id_;
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!inited_)) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (OB_UNLIKELY(!arg.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", KR(ret), K(arg));
} else if (OB_FAIL(parallel_ddl_pre_check_(tenant_id))) {
LOG_WARN("fail to pre check parallel ddl", KR(ret), K(tenant_id));
} else {
ObSetCommentHelper comment_helper(schema_service_, tenant_id, arg, res);
if (OB_FAIL(comment_helper.init(ddl_service_))) {
LOG_WARN("fail to init comment helper", KR(ret), K(tenant_id));
} else if (OB_FAIL(comment_helper.execute())) {
LOG_WARN("fail to execute comment", KR(ret), K(tenant_id));
}
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
LOG_TRACE("finish set comment", KR(ret), K(arg), K(cost));
return ret;
}
int ObRootService::alter_table(const obrpc::ObAlterTableArg &arg, obrpc::ObAlterTableRes &res)
{
LOG_DEBUG("receive alter table arg", K(arg));
@ -4784,6 +4814,52 @@ int ObRootService::create_mlog(const obrpc::ObCreateMLogArg &arg, obrpc::ObCreat
return ret;
}
int ObRootService::parallel_create_index(const ObCreateIndexArg &arg, obrpc::ObAlterTableRes &res)
{
LOG_TRACE("receive parallel create index arg", K(arg));
int ret = OB_SUCCESS;
int64_t begin_time = ObTimeUtility::current_time();
const uint64_t tenant_id = arg.exec_tenant_id_;
uint64_t data_version = 0;
if (!inited_) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (!arg.is_valid()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", KR(ret), K(arg));
} else if (OB_FAIL(parallel_ddl_pre_check_(tenant_id))) {
LOG_WARN("pre check failed before parallel ddl execute", KR(ret), K(tenant_id));
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, data_version))) {
LOG_WARN("fail to get data version", KR(ret), K(tenant_id));
} else if (data_version < DATA_VERSION_4_2_2_0
|| (data_version >= DATA_VERSION_4_3_0_0 && data_version < DATA_VERSION_4_3_5_0)
|| share::schema::is_fts_or_multivalue_index(arg.index_type_)
|| share::schema::is_vec_index(arg.index_type_)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("not supported", KR(ret), K(data_version), K(arg.index_type_));
} else {
ObCreateIndexHelper create_index_helper(schema_service_, tenant_id, ddl_service_, arg, res);
if (OB_FAIL(create_index_helper.init(ddl_service_))) {
LOG_WARN("fail to init create index helper", KR(ret), K(tenant_id));
} else if (OB_FAIL(create_index_helper.execute())) {
LOG_WARN("fail to execute create index table", KR(ret), K(tenant_id));
}
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
char table_id_buffer[256];
snprintf(table_id_buffer, sizeof(table_id_buffer), "data_table_id:%ld, index_table_id:%ld",
arg.data_table_id_, arg.index_table_id_);
ROOTSERVICE_EVENT_ADD("ddl scheduler", "parallel create index",
"tenant_id", arg.tenant_id_,
"ret", ret,
"trace_id", *ObCurTraceId::get_trace_id(),
"task_id", res.task_id_,
"table_id", table_id_buffer,
"schema_version", res.schema_version_);
LOG_TRACE("finish parallel create index", KR(ret), K(arg), K(cost), "ddl_event_info", ObDDLEventInfo());
return ret;
}
int ObRootService::drop_table(const obrpc::ObDropTableArg &arg, obrpc::ObDDLRes &res)
{
int ret = OB_SUCCESS;
@ -5737,6 +5813,33 @@ int ObRootService::clone_tenant(const obrpc::ObCloneTenantArg &arg,
return ret;
}
int ObRootService::parallel_update_index_status(const obrpc::ObUpdateIndexStatusArg &arg, obrpc::ObParallelDDLRes &res)
{
LOG_TRACE("receive update index status arg", K(arg));
int64_t begin_time = ObTimeUtility::current_time();
int ret = OB_SUCCESS;
const uint64_t tenant_id = arg.exec_tenant_id_;
if (!inited_) {
ret = OB_NOT_INIT;
LOG_WARN("not init", KR(ret));
} else if (OB_UNLIKELY(!arg.is_valid() || OB_INVALID_ID == arg.data_table_id_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", KR(ret), K(arg));
} else if (OB_FAIL(parallel_ddl_pre_check_(tenant_id))) {
LOG_WARN("pre check failed before parallel ddl execute", KR(ret), K(tenant_id));
} else {
ObUpdateIndexStatusHelper update_index_status_helper(schema_service_, tenant_id, arg, res);
if (OB_FAIL(update_index_status_helper.init(ddl_service_))) {
LOG_WARN("fail to init create table helper", KR(ret), K(tenant_id));
} else if (OB_FAIL(update_index_status_helper.execute())) {
LOG_WARN("fail to execute update index status helper", KR(ret));
}
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
LOG_TRACE("finish update index status", KR(ret), K(arg), K(cost));
return ret;
}
int ObRootService::init_debug_database()
{
const schema_create_func *creator_ptr_array[] = {

View File

@ -509,6 +509,7 @@ public:
int parallel_create_table(const obrpc::ObCreateTableArg &arg, obrpc::ObCreateTableRes &res);
int create_table(const obrpc::ObCreateTableArg &arg, obrpc::ObCreateTableRes &res);
int alter_database(const obrpc::ObAlterDatabaseArg &arg);
int set_comment(const obrpc::ObSetCommentArg &arg, obrpc::ObParallelDDLRes &res);
int alter_table(const obrpc::ObAlterTableArg &arg, obrpc::ObAlterTableRes &res);
int start_redef_table(const obrpc::ObStartRedefTableArg &arg, obrpc::ObStartRedefTableRes &res);
int copy_table_dependents(const obrpc::ObCopyTableDependentsArg &arg);
@ -539,6 +540,7 @@ public:
const obrpc::ObCreateAuxIndexArg &arg,
obrpc::ObCreateAuxIndexRes &result);
int create_index(const obrpc::ObCreateIndexArg &arg, obrpc::ObAlterTableRes &res);
int parallel_create_index(const obrpc::ObCreateIndexArg &arg, obrpc::ObAlterTableRes &res);
int drop_table(const obrpc::ObDropTableArg &arg, obrpc::ObDDLRes &res);
int drop_database(const obrpc::ObDropDatabaseArg &arg, obrpc::ObDropDatabaseRes &drop_database_res);
int drop_tablegroup(const obrpc::ObDropTablegroupArg &arg);
@ -559,6 +561,7 @@ public:
int root_minor_freeze(const obrpc::ObRootMinorFreezeArg &arg);
int update_index_status(const obrpc::ObUpdateIndexStatusArg &arg);
int update_mview_status(const obrpc::ObUpdateMViewStatusArg &arg);
int parallel_update_index_status(const obrpc::ObUpdateIndexStatusArg &arg, obrpc::ObParallelDDLRes &res);
int purge_table(const obrpc::ObPurgeTableArg &arg);
int flashback_table_from_recyclebin(const obrpc::ObFlashBackTableFromRecyclebinArg &arg);
int flashback_table_to_time_point(const obrpc::ObFlashBackTableToScnArg &arg);

View File

@ -30,7 +30,10 @@ namespace rootserver
inline bool is_parallel_ddl(const obrpc::ObRpcPacketCode pcode)
{
return obrpc::OB_TRUNCATE_TABLE_V2 == pcode
|| obrpc::OB_PARALLEL_CREATE_TABLE == pcode;
|| obrpc::OB_PARALLEL_CREATE_TABLE == pcode
|| obrpc::OB_PARALLEL_SET_COMMENT == pcode
|| obrpc::OB_PARALLEL_CREATE_INDEX == pcode
|| obrpc::OB_PARALLEL_UPDATE_INDEX_STATUS == pcode;
}
// precondition: enable_ddl = false
@ -335,6 +338,7 @@ DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_TABLEGROUP, ObRpcAlterTablegroupP, a
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_TABLE, ObRpcCreateTableP, create_table(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_RECOVER_RESTORE_TABLE_DDL, ObRpcRecoverRestoreTableDDLP, recover_restore_table_ddl(arg_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_PARALLEL_CREATE_TABLE, ObRpcParallelCreateTableP, parallel_create_table(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_PARALLEL_SET_COMMENT, ObRpcSetCommentP, set_comment(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_TABLE, ObRpcAlterTableP, alter_table(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_EXCHANGE_PARTITION, ObRpcExchangePartitionP, exchange_partition(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_SPLIT_GLOBAL_INDEX_TABLET, ObSplitGlobalIndexTabletTaskP, split_global_index_tablet(arg_));
@ -344,6 +348,7 @@ DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_TRUNCATE_TABLE, ObRpcTruncateTableP, trunc
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_TRUNCATE_TABLE_V2, ObRpcTruncateTableV2P, truncate_table_v2(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_AUX_INDEX, ObRpcCreateAuxIndexP, create_aux_index(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_INDEX, ObRpcCreateIndexP, create_index(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_PARALLEL_CREATE_INDEX, ObRpcParallelCreateIndexP, parallel_create_index(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_INDEX, ObRpcDropIndexP, drop_index(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_INDEX_ON_FAILED, ObRpcDropIndexOnFailedP, drop_index_on_failed(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_REBUILD_VEC_INDEX, ObRpcRebuildVecIndexP, rebuild_vec_index(arg_, result_));
@ -364,6 +369,7 @@ DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_REVOKE_ROUTINE, ObRpcRevokeRoutineP, revok
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_REVOKE_SYSPRIV, ObRpcRevokeSysPrivP, revoke_syspriv(arg_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_UPDATE_INDEX_TABLE_STATUS, ObUpdateIndexTableStatusP, update_index_status(arg_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_UPDATE_MVIEW_TABLE_STATUS, ObRpcUpdateMViewTableStatusP, update_mview_status(arg_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_PARALLEL_UPDATE_INDEX_STATUS, ObUpdateIndexStatusP, parallel_update_index_status(arg_, result_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_FLASHBACK_TABLE_FROM_RECYCLEBIN, ObRpcFlashBackTableFromRecyclebinP, flashback_table_from_recyclebin(arg_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_FLASHBACK_INDEX, ObRpcFlashBackIndexP, flashback_index(arg_));
DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_PURGE_TABLE, ObRpcPurgeTableP, purge_table(arg_));

View File

@ -0,0 +1,808 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX RS
#include "rootserver/ob_root_service.h"
#include "rootserver/parallel_ddl/ob_create_index_helper.h"
#include "rootserver/ob_table_creator.h"
#include "rootserver/freeze/ob_major_freeze_helper.h"
#include "rootserver/ob_balance_group_ls_stat_operator.h"
#include "rootserver/ddl_task/ob_ddl_scheduler.h"
#include "share/ob_index_builder_util.h"
#include "share/ob_rpc_struct.h"
#include "share/ob_debug_sync_point.h"
#include "share/schema/ob_multi_version_schema_service.h"
#include "share/schema/ob_table_sql_service.h"
#include "sql/resolver/ob_resolver_utils.h"
using namespace oceanbase::lib;
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
using namespace oceanbase::rootserver;
ObCreateIndexHelper::ObCreateIndexHelper(
share::schema::ObMultiVersionSchemaService *schema_service,
const uint64_t tenant_id,
rootserver::ObDDLService &ddl_service,
const obrpc::ObCreateIndexArg &arg,
obrpc::ObAlterTableRes &res)
: ObDDLHelper(schema_service, tenant_id),
arg_(arg),
new_arg_(nullptr),
res_(res),
orig_data_table_schema_(nullptr),
new_data_table_schema_(nullptr),
index_schemas_(),
gen_columns_(),
index_builder_(ddl_service),
task_record_()
{
}
ObCreateIndexHelper::~ObCreateIndexHelper()
{
if (OB_NOT_NULL(new_arg_)) {
new_arg_->~ObCreateIndexArg();
new_arg_ = nullptr;
}
}
int ObCreateIndexHelper::execute()
{
RS_TRACE(parallel_ddl_begin);
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(start_ddl_trans_())) {
LOG_WARN("fail to start ddl trans", KR(ret));
} else if (OB_FAIL(lock_objects_())) {
LOG_WARN("fail to lock objects", KR(ret));
} else if (OB_FAIL(check_table_legitimacy_())) {
LOG_WARN("fail to check create index", KR(ret));
} else if (OB_FAIL(generate_index_schema_())) {
LOG_WARN("fail to generate index schema");
} else if (OB_FAIL(calc_schema_version_cnt_())) {
LOG_WARN("fail to calc schema version cnt", KR(ret));
} else if (OB_FAIL(gen_task_id_and_schema_versions_())) {
LOG_WARN("fail to gen task id and schema versions", KR(ret));
} else if (OB_FAIL(create_index_())) {
LOG_WARN("fail to create index", KR(ret));
} else if (OB_FAIL(serialize_inc_schema_dict_())) {
LOG_WARN("fail to serialize inc schema dict", KR(ret));
} else if (OB_FAIL(wait_ddl_trans_())) {
LOG_WARN("fail to wait ddl trans", KR(ret));
} else if (OB_FAIL(add_index_name_to_cache_())) {
LOG_WARN("fail to add index name to cache", KR(ret));
}
const bool commit = OB_SUCC(ret);
if (OB_FAIL(end_ddl_trans_(ret))) {
LOG_WARN("fail to end ddl trans", KR(ret));
if (commit) {
int tmp_ret = OB_SUCCESS;
if (OB_ISNULL(ddl_service_)) {
tmp_ret = OB_ERR_UNEXPECTED;
LOG_WARN("ddl_service_ is null", KR(tmp_ret));
} else if (OB_TMP_FAIL(ddl_service_->get_index_name_checker().reset_cache(tenant_id_))) {
LOG_WARN("fail to reset cache", K(ret), KR(tmp_ret), K_(tenant_id));
}
}
} else {
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
int64_t last_schema_version = OB_INVALID_VERSION;
int64_t end_schema_version = OB_INVALID_VERSION;
if (OB_ISNULL(tsi_generator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tsi generator is null", KR(ret));
} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
LOG_WARN("fail to get current version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_FAIL(tsi_generator->get_end_version(end_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_UNLIKELY(last_schema_version != end_schema_version)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("too much schema versions may be allocated", KR(ret), KPC(tsi_generator));
} else if (OB_UNLIKELY(index_schemas_.count() != 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index schemas count unexpected", KR(ret), K(index_schemas_.count()));
} else {
res_.index_table_id_ = index_schemas_.at(0).get_table_id();
res_.schema_version_ = last_schema_version;
res_.task_id_ = task_record_.task_id_;
if (OB_FAIL(GCTX.root_service_->get_ddl_task_scheduler().schedule_ddl_task(task_record_))) {
LOG_WARN("fail to schedule ddl task", KR(ret), K_(task_record));
}
}
}
if (OB_ERR_KEY_NAME_DUPLICATE == ret) {
if (true == arg_.if_not_exist_) {
ret = OB_SUCCESS;
LOG_USER_WARN(OB_ERR_KEY_NAME_DUPLICATE, arg_.index_name_.length(), arg_.index_name_.ptr());
} else {
LOG_USER_ERROR(OB_ERR_KEY_NAME_DUPLICATE, arg_.index_name_.length(), arg_.index_name_.ptr());
}
}
RS_TRACE(parallel_ddl_end);
FORCE_PRINT_TRACE(THE_RS_TRACE, "[parallel create index]");
return ret;
}
// the online ddl lock and table lock will be locked when submit ddl task
int ObCreateIndexHelper::lock_objects_()
{
int ret = OB_SUCCESS;
const ObDatabaseSchema *database_schema = NULL;
DEBUG_SYNC(BEFORE_PARALLEL_DDL_LOCK);
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(lock_database_by_obj_name_())) {
LOG_WARN("fail to lock databases by obj name", KR(ret));
} else if (OB_FAIL(check_database_legitimacy_())) {
LOG_WARN("fail to prefech schemas", KR(ret), K_(tenant_id));
} else if (OB_FAIL(lock_objects_by_name_())) {
LOG_WARN("fail to prefech schemas", KR(ret), K_(tenant_id));
} else if (OB_FAIL(lock_objects_by_id_())) {
LOG_WARN("fail to lock objects by id", KR(ret), K_(tenant_id));
} else if (OB_FAIL(check_parallel_ddl_conflict_(arg_.based_schema_object_infos_))) {
LOG_WARN("fail to check parallel ddl conflict", KR(ret));
} else if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig_data_table_schema", KR(ret));
} else if (OB_UNLIKELY(database_id_ != orig_data_table_schema_->get_database_id())) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("database_id_ is not equal to table schema's databse_id",
KR(ret), K_(database_id), K(orig_data_table_schema_->get_database_id()));
} else if (OB_FAIL(latest_schema_guard_.get_database_schema(database_id_, database_schema))) {
LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K_(database_id));
} else if (OB_ISNULL(database_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("databse_schema is null", KR(ret));
} else if (OB_UNLIKELY(database_schema->get_database_name_str() != arg_.database_name_)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("database_schema's database name not equal to arg",
KR(ret), K(database_schema->get_database_name_str()), K_(arg_.database_name));
}
DEBUG_SYNC(AFTER_PARALLEL_DDL_LOCK);
RS_TRACE(lock_objects);
return ret;
}
int ObCreateIndexHelper::lock_database_by_obj_name_()
{
int ret = OB_SUCCESS;
const ObString &database_name = arg_.database_name_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(add_lock_object_by_database_name_(database_name, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database by name", KR(ret), K_(tenant_id), K(database_name));
} else if (OB_FAIL(lock_databases_by_name_())) {
LOG_WARN("fail to lock databases by name", KR(ret), K_(tenant_id));
}
return ret;
}
//lock table name and index name (x)
int ObCreateIndexHelper::lock_objects_by_name_()
{
int ret = OB_SUCCESS;
bool is_oracle_mode = false;
const ObString &database_name = arg_.database_name_;
const ObString &table_name = arg_.table_name_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(
tenant_id_, is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", KR(ret));
} else if (OB_FAIL(add_lock_object_by_name_(database_name, table_name,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to add lock object by name", KR(ret), K_(tenant_id), K(database_name), K(table_name));
} else if (is_oracle_mode) {
const ObString &index_name = arg_.index_name_;
if (OB_FAIL(add_lock_object_by_name_(database_name, index_name,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock object by index name", KR(ret), K_(tenant_id), K(database_name), K(index_name));
}
}
if (FAILEDx(lock_existed_objects_by_name_())) {
LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
}
return ret;
}
int ObCreateIndexHelper::check_database_legitimacy_()
{
int ret = OB_SUCCESS;
const ObString &database_name = arg_.database_name_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(ObDDLHelper::check_database_legitimacy_(database_name, database_id_))) {
LOG_WARN("fail to check database legitimacy", KR(ret), K(database_name));
}
return ret;
}
// lock data table id and foreign table id
// the foreign table need to aware the related table have created an index
// thus, need to push foreign table schema_version
int ObCreateIndexHelper::lock_objects_by_id_()
{
int ret = OB_SUCCESS;
uint64_t table_id = OB_INVALID_ID;
ObTableType table_type;
int64_t schema_version = OB_INVALID_VERSION;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == database_id_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("database is not exist", KR(ret), K_(tenant_id), K_(arg_.database_name));
} else if (OB_FAIL(add_lock_object_by_id_(database_id_,
share::schema::DATABASE_SCHEMA, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database id", KR(ret), K_(database_id));
} else if (OB_FAIL(latest_schema_guard_.get_table_id(database_id_, arg_.session_id_, arg_.table_name_, table_id, table_type, schema_version))) {
LOG_WARN("fail to get table id", KR(ret), K_(database_id), K_(arg_.session_id), K_(arg_.table_name));
} else if (OB_UNLIKELY(OB_INVALID_ID == table_id)) {
ret = OB_ERR_OBJECT_NOT_EXIST;
LOG_WARN("table not exist", KR(ret), K_(database_id), K_(arg_.session_id), K_(arg_.table_name));
} else if (OB_FAIL(add_lock_object_by_id_(table_id,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock table id", KR(ret), K_(tenant_id));
} else if (OB_FAIL(latest_schema_guard_.get_table_schema(table_id, orig_data_table_schema_))) {
LOG_WARN("fail to get orig table schema", KR(ret), K(table_id));
} else if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_TABLE_NOT_EXIST;
LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(arg_.database_name_), to_cstring(arg_.table_name_));
LOG_WARN("table not exist", KR(ret), K_(arg));
} else if (OB_FAIL(add_lock_table_udt_id_(*orig_data_table_schema_))) {
LOG_WARN("fail to add lock table udt id", KR(ret));
} else {
const ObIArray<ObForeignKeyInfo> &foreign_key_infos = orig_data_table_schema_->get_foreign_key_infos();
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 = table_id == foreign_key_info.parent_table_id_
? foreign_key_info.child_table_id_
: foreign_key_info.parent_table_id_;
if (related_table_id == table_id) {
} else if (OB_FAIL(add_lock_object_by_id_(related_table_id,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock table id", KR(ret), K_(tenant_id));
}
}
if (OB_SUCC(ret)) {
for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
if (info.schema_id_ == table_id) {
// already have x lock
} else if (is_inner_pl_udt_id(info.schema_id_) || is_inner_pl_object_id(info.schema_id_)) {
// do nothing
} else if (OB_FAIL(add_lock_object_by_id_(info.schema_id_,
info.schema_type_,
transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock based object schema id", KR(ret), K_(tenant_id));
}
}
}
}
if (FAILEDx(lock_existed_objects_by_id_())) {
LOG_WARN("fail to lock objects by id", KR(ret));
}
return ret;
}
int ObCreateIndexHelper::check_table_legitimacy_()
{
int ret = OB_SUCCESS;
uint64_t table_id = OB_INVALID_ID;
bool in_tenant_space = true;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("data table schea is null", KR(ret), KP(orig_data_table_schema_));
} else if (FALSE_IT(table_id = orig_data_table_schema_->get_table_id())) {
} else if (OB_FAIL(ObSysTableChecker::is_tenant_space_table_id(table_id, in_tenant_space))) {
LOG_WARN("fail to check table in tenant space", KR(ret), K(table_id));
} else if (OB_UNLIKELY(is_inner_table(table_id))) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("create index on inner table not support", KR(ret), K(table_id));
} else if (OB_UNLIKELY(!arg_.is_inner_ && orig_data_table_schema_->is_in_recyclebin())) {
ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
LOG_WARN("can not add index on table in recyclebin", KR(ret), K_(arg));
} else if (OB_UNLIKELY(orig_data_table_schema_->is_in_splitting())) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN( "con not create index during splitting", KR(ret), K_(arg));
// There used to be check_restore_point_allow() here, but it is currently useless.
// Meanwhile, the frequent addition and deletion of __all_acquired_snapshot during the index creation
// will cause it's buffer table to bloat,
// resulting in performance decline during long periods of concentrated index building.
} else if (!orig_data_table_schema_->check_can_do_ddl()) {
ret = OB_OP_NOT_ALLOW;
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "execute ddl while table is executing offline ddl");
LOG_WARN("offline ddl is being executed, other ddl operations are not allowed", KR(ret), KPC(orig_data_table_schema_));
} else if (OB_UNLIKELY(orig_data_table_schema_->get_index_tid_count() >= OB_MAX_INDEX_PER_TABLE)) {
ret = OB_ERR_TOO_MANY_KEYS;
LOG_USER_ERROR(OB_ERR_TOO_MANY_KEYS, OB_MAX_INDEX_PER_TABLE);
LOG_WARN("too many index for table", KR(ret), K(OB_MAX_INDEX_PER_TABLE), K(orig_data_table_schema_->get_index_tid_count()));
} else if (OB_FAIL(check_table_udt_exist_(*orig_data_table_schema_))) {
LOG_WARN("fail to check table udt exist", KR(ret));
} else if (OB_FAIL(check_fk_related_table_ddl_(*orig_data_table_schema_, ObDDLType::DDL_CREATE_INDEX))) {
LOG_WARN("check whether the forign key related table is executing ddl failed", KR(ret));
}
RS_TRACE(check_schemas);
return ret;
}
int ObCreateIndexHelper::is_local_generate_schema_(bool &is_local_generate)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig data table schema is nullptr", KR(ret));
} else if (INDEX_TYPE_NORMAL_LOCAL == arg_.index_type_
|| INDEX_TYPE_UNIQUE_LOCAL == arg_.index_type_
|| INDEX_TYPE_DOMAIN_CTXCAT_DEPRECATED == arg_.index_type_
|| INDEX_TYPE_SPATIAL_LOCAL == arg_.index_type_
|| is_fts_index(arg_.index_type_)
|| is_multivalue_index(arg_.index_type_)) {
is_local_generate = true;
} else if (INDEX_TYPE_NORMAL_GLOBAL == arg_.index_type_
|| INDEX_TYPE_UNIQUE_GLOBAL == arg_.index_type_
|| INDEX_TYPE_SPATIAL_GLOBAL == arg_.index_type_) {
if (!orig_data_table_schema_->is_partitioned_table() && !arg_.index_schema_.is_partitioned_table()) {
is_local_generate = true;
} else {
is_local_generate = false;
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected index type", KR(ret), K_(arg_.index_type));
}
return ret;
}
int ObCreateIndexHelper::generate_index_schema_()
{
int ret = OB_SUCCESS;
bool is_local_generate = false;
bool global_index_without_column_info = false;
ObTableSchema *index_schema = nullptr;
void *new_arg_ptr = nullptr;
// not used when is global generate
HEAP_VAR(ObTableSchema, tmp_index_schema){
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(new_arg_ptr = allocator_.alloc(sizeof(obrpc::ObCreateIndexArg)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail alloc memory", KR(ret), KP(new_arg_ptr));
} else if (FALSE_IT(new_arg_ = new (new_arg_ptr)obrpc::ObCreateIndexArg)) {
} else if (OB_ISNULL(new_arg_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new_arg_ is null", KR(ret));
} else if (OB_FAIL(new_arg_->assign(arg_))) {
LOG_WARN("fail to assign arg", KR(ret));
} else if (OB_UNLIKELY(!new_arg_->is_valid())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new arg invalid", KR(ret), KP_(new_arg));
} else if (OB_FAIL(is_local_generate_schema_(is_local_generate))) {
LOG_WARN("fail to check is local generate schema", KR(ret));
} else if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("data table schema is nullptr", KR(ret));
} else if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, *orig_data_table_schema_, new_data_table_schema_))) {
LOG_WARN("fail to allocate new table schema", KR(ret), K_(tenant_id));
} else if (OB_ISNULL(new_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new_data_table_schema_ is null", KR(ret));
} else if (is_local_generate) {
global_index_without_column_info = true;
index_schema = &tmp_index_schema;
if (INDEX_TYPE_NORMAL_GLOBAL == new_arg_->index_type_) {
new_arg_->index_type_ = INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE;
new_arg_->index_schema_.set_index_type(INDEX_TYPE_NORMAL_GLOBAL_LOCAL_STORAGE);
} else if (INDEX_TYPE_UNIQUE_GLOBAL == new_arg_->index_type_) {
new_arg_->index_type_ = INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE;
new_arg_->index_schema_.set_index_type(INDEX_TYPE_UNIQUE_GLOBAL_LOCAL_STORAGE);
} else if (INDEX_TYPE_SPATIAL_GLOBAL == new_arg_->index_type_) {
new_arg_->index_type_ = INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE;
new_arg_->index_schema_.set_index_type(INDEX_TYPE_SPATIAL_GLOBAL_LOCAL_STORAGE);
}
} else {
global_index_without_column_info = false;
index_schema = &new_arg_->index_schema_;
}
if (FAILEDx(ObIndexBuilderUtil::adjust_expr_index_args(
*new_arg_, *new_data_table_schema_, allocator_, gen_columns_))) {
LOG_WARN("fail to adjust expr index args", KR(ret));
} else if (OB_ISNULL(index_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index schema is null", KR(ret));
} else if (OB_FAIL(index_builder_.generate_schema(*new_arg_, *new_data_table_schema_, global_index_without_column_info,
false/*generate_id*/, *index_schema))) {
LOG_WARN("fail to generate schema", KR(ret));
} else if (gen_columns_.empty() || is_local_generate) {
if (OB_FAIL(new_data_table_schema_->check_create_index_on_hidden_primary_key(*index_schema))) {
LOG_WARN("fail to check create index on hidden primary key", KR(ret), KPC(index_schema));
}
}
bool is_oracle_mode = false;
if (FAILEDx(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(
tenant_id_, is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", KR(ret));
} else if (OB_FAIL(index_schema->generate_origin_index_name())) {
LOG_WARN("fail to generate origin index name", KR(ret), KPC(index_schema));
} else if (!is_oracle_mode) {
ObIndexSchemaInfo index_info;
if (OB_FAIL(latest_schema_guard_.get_coded_index_name_info_mysql(
allocator_,
database_id_,
orig_data_table_schema_->get_table_id(),
index_schema->get_table_name(),
false /*is built in index*/,
index_info))) {
LOG_WARN("fail to get index info", KR(ret), K(database_id_), K(index_schema->get_table_name()));
} else if (index_info.is_valid()) {
if (arg_.if_not_exist_) {
// executor rely on invalid index id when arg_.if_not_exists_
res_.schema_version_ = index_info.get_schema_version();
}
ret = OB_ERR_KEY_NAME_DUPLICATE;
LOG_WARN("duplicate index name", KR(ret), K_(tenant_id),
"database_id", orig_data_table_schema_->get_database_id(),
"data_table_id", orig_data_table_schema_->get_table_id(),
"index_name", arg_.index_name_);
}
} else {
bool name_exist = false;
if (OB_FAIL(ddl_service_->get_index_name_checker().check_index_name_exist(tenant_id_,
index_schema->get_database_id(),
index_schema->get_table_name_str(),
name_exist))) {
LOG_WARN("fail to check index name exist", KR(ret), K_(tenant_id), K(index_schema->get_table_name_str()));
} else if (name_exist) {
ret = OB_ERR_KEY_NAME_DUPLICATE;
LOG_WARN("duplicate index name", KR(ret), K_(tenant_id),
"database_id", orig_data_table_schema_->get_database_id(),
"data_table_id", orig_data_table_schema_->get_table_id(),
"index_name", arg_.index_name_);
}
}
uint64_t object_id = OB_INVALID_ID;
ObIDGenerator id_generator;
if (FAILEDx(index_schemas_.push_back(*index_schema))) {
LOG_WARN("fail to push back index schema", KR(ret));
} else if (OB_FAIL(gen_partition_object_and_tablet_ids_(index_schemas_))) {
LOG_WARN("fail to gen partition object and tablet ids", KR(ret));
} else if (OB_FAIL(gen_object_ids_(1/*object_cnt*/, id_generator))) {
LOG_WARN("fail to gen object ids", KR(ret), K_(tenant_id));
} else if (OB_FAIL(id_generator.next(object_id))) {
LOG_WARN("fail to get next object id", KR(ret));
} else {
index_schemas_.at(0).set_table_id(object_id);
}
} // end heapvar
RS_TRACE(generate_schemas);
return ret;
}
int ObCreateIndexHelper::calc_schema_version_cnt_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig_data_table_schema is null", KR(ret));
} else {
schema_version_cnt_ = 0;
if (!gen_columns_.empty()) {
// gen columns & alter table option
schema_version_cnt_++;
uint64_t table_id = orig_data_table_schema_->get_table_id();
const ObIArray<ObForeignKeyInfo> &foreign_key_infos = orig_data_table_schema_->get_foreign_key_infos();
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 = table_id == foreign_key_info.parent_table_id_
? foreign_key_info.child_table_id_
: foreign_key_info.parent_table_id_;
if (related_table_id == table_id) {
schema_version_cnt_++;
} else if (foreign_key_info.is_parent_table_mock_) {
schema_version_cnt_++; // for now, when parent table is mock
schema_version_cnt_++; // update table option will push schema version twice
} else {
schema_version_cnt_++;
}
}
}
// index table
schema_version_cnt_++;
// data table
schema_version_cnt_++;
// 1503
schema_version_cnt_++;
}
return ret;
}
int ObCreateIndexHelper::create_index_()
{
int ret = OB_SUCCESS;
ObSchemaService *schema_service_impl = nullptr;
int64_t new_schema_version = OB_INVALID_VERSION;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check iner stat", KR(ret));
} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema_service impl is null", KR(ret));
} else if (OB_UNLIKELY(index_schemas_.count() != 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index schemas count not expected", KR(ret), K(index_schemas_.count()));
} else if (OB_ISNULL(new_data_table_schema_) || OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new/orig table schema is nullptr", KR(ret), KP(new_data_table_schema_), KP(orig_data_table_schema_));
} else {
ObDDLOperator ddl_operator(*schema_service_, *sql_proxy_);
ObTableSchema &index_schema = index_schemas_.at(0);
if (!gen_columns_.empty()) {
if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
LOG_WARN("fail to gen new schema_version", KR(ret), K_(tenant_id));
}
for (int64_t i = 0; OB_SUCC(ret) && i < gen_columns_.count(); ++i) {
ObColumnSchemaV2 *new_column_schema = gen_columns_.at(i);
if (OB_ISNULL(new_column_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new column schema is null", KR(ret));
} else if (FALSE_IT(new_column_schema->set_schema_version(new_schema_version))) {
} else if (OB_FAIL(schema_service_impl->get_table_sql_service().insert_single_column(
trans_, *new_data_table_schema_, *new_column_schema, false/*record_ddl_option*/))) {
LOG_WARN("insert single column failed", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (FALSE_IT(new_data_table_schema_->set_schema_version(new_schema_version))) {
} else if (OB_FAIL(schema_service_impl->get_table_sql_service().update_table_options(
trans_, *orig_data_table_schema_, *new_data_table_schema_, OB_DDL_ALTER_TABLE))) {
LOG_WARN("fail to alter table option", KR(ret));
}
}
uint64_t tenant_data_version = OB_INVALID_VERSION;
if (FAILEDx(create_table_())) {
LOG_WARN("fail to create table", KR(ret));
} else if (index_schema.has_tablet() && OB_FAIL(create_tablets_())) {
LOG_WARN("fail to create tablets", KR(ret));
} else if (OB_ISNULL(new_arg_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new arg is null", KR(ret));
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id_, tenant_data_version))) {
LOG_WARN("fail to get data version", K(ret), K_(tenant_id));
} else if (OB_FAIL(index_builder_.submit_build_index_task(trans_,
*new_arg_,
new_data_table_schema_,
nullptr/*inc_data_tablet_ids*/,
nullptr/*del_data_tablet_ids*/,
&index_schema,
arg_.parallelism_,
arg_.consumer_group_id_,
tenant_data_version,
allocator_,
task_record_))) {
LOG_WARN("fail to submit build local index task", KR(ret));
}
}
RS_TRACE(submit_task);
return ret;
}
int ObCreateIndexHelper::create_table_()
{
int ret = OB_SUCCESS;
int64_t new_schema_version = OB_INVALID_VERSION;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_UNLIKELY(index_schemas_.count() != 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index schemas count not expected", KR(ret));
} else {
ObDDLOperator ddl_operator(*schema_service_, *sql_proxy_);
ObSchemaService *schema_service_impl = schema_service_->get_schema_service();
int64_t last_schema_version = OB_INVALID_VERSION;
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
ObTableSchema &index_schema = index_schemas_.at(0);
if (OB_ISNULL(tsi_generator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tsi generator is null", KR(ret));
} else if (OB_ISNULL(schema_service_impl)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema service must not by null", KR(ret));
} else if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
LOG_WARN("fail to gen new schema version", KR(ret), K_(tenant_id));
} else if (FALSE_IT(index_schema.set_schema_version(new_schema_version))) {
} else if (OB_FAIL(schema_service_impl->get_table_sql_service().create_table(
index_schema, trans_,
nullptr/*ddl_stmt_str*/, true/*need_sync_schema_version*/, false/*is_truncate_table*/))) {
LOG_WARN("fail to create table", KR(ret));
} else if (OB_FAIL(schema_service_impl->get_table_sql_service().insert_temp_table_info(trans_, index_schema))) {
LOG_WARN("insert temp table info", KR(ret), K(index_schema));
} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_UNLIKELY(last_schema_version <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("last schema version is invalid", KR(ret), K_(tenant_id), K(last_schema_version));
} else if (OB_FAIL(ddl_operator.insert_ori_schema_version(trans_, tenant_id_, index_schema.get_table_id(), last_schema_version))) {
LOG_WARN("fail to insert ori schema version", KR(ret), K_(tenant_id), K(new_schema_version));
}
}
RS_TRACE(create_schemas);
return ret;
}
int ObCreateIndexHelper::create_tablets_()
{
int ret = OB_SUCCESS;
SCN frozen_scn;
ObSchemaGetterGuard schema_guard;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("check inner stat failed", KR(ret));
} else if (OB_UNLIKELY(index_schemas_.count() != 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index schemas count not expected", KR(ret), K(index_schemas_.count()));
} else if (OB_ISNULL(orig_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig_data_table_schema is null", KR(ret));
} else if(OB_FAIL(ObMajorFreezeHelper::get_frozen_scn(tenant_id_, frozen_scn))) {
LOG_WARN("fail to get frozen status for create tablet", KR(ret), K_(tenant_id));
} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) {
LOG_WARN("fail to get tenant schema guard", KR(ret), K_(tenant_id));
} else {
ObTableSchema &index_schema = index_schemas_.at(0);
ObTableCreator table_creator(tenant_id_, frozen_scn, trans_);
ObNewTableTabletAllocator new_table_tablet_allocator(
tenant_id_,
schema_guard,
sql_proxy_,
true /*use parallel ddl*/,
orig_data_table_schema_);
common::ObArray<share::ObLSID> ls_id_array;
const ObTablegroupSchema *data_tablegroup_schema = NULL; // keep NULL if no tablegroup
ObSEArray<bool, 1> need_create_empty_majors;
uint64_t tenant_data_version = 0;
if (OB_FAIL(table_creator.init(true/*need_tablet_cnt_check*/))) {
LOG_WARN("fail to init table craetor", KR(ret));
} else if (OB_FAIL(new_table_tablet_allocator.init())) {
LOG_WARN("fail to init new table tablet allocator", KR(ret));
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id_, tenant_data_version))) {
LOG_WARN("fail to get data version", K(ret), K_(tenant_id));
} else if (OB_INVALID_ID != orig_data_table_schema_->get_tablegroup_id()) {
if (OB_FAIL(latest_schema_guard_.get_tablegroup_schema(
orig_data_table_schema_->get_tablegroup_id(),
data_tablegroup_schema))) {
LOG_WARN("get tablegroup_schema failed", KR(ret), KPC(orig_data_table_schema_));
} else if (OB_ISNULL(data_tablegroup_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("data_tablegroup_schema is null", KR(ret), KPC(orig_data_table_schema_));
}
}
if (OB_FAIL(ret)) {
} else if (index_schema.is_index_local_storage()) {
ObSEArray<const share::schema::ObTableSchema*, 1> schemas;
if (OB_FAIL(schemas.push_back(&index_schema))
|| OB_FAIL(need_create_empty_majors.push_back(false))) {
LOG_WARN("fail to push back index schema", KR(ret), K(index_schema));
} else if (OB_FAIL(new_table_tablet_allocator.prepare(trans_, index_schema, data_tablegroup_schema))) {
LOG_WARN("fail to prepare ls for index schema tablets", KR(ret));
} else if (OB_FAIL(new_table_tablet_allocator.get_ls_id_array(ls_id_array))) {
LOG_WARN("fail to get ls id array", KR(ret));
} else if (OB_FAIL(table_creator.add_create_tablets_of_local_aux_tables_arg(
schemas,
orig_data_table_schema_,
ls_id_array,
tenant_data_version,
need_create_empty_majors))) {
LOG_WARN("create table tablet failed", KR(ret), K(index_schema), K(ls_id_array));
}
} else {
if (OB_FAIL(new_table_tablet_allocator.prepare(trans_, index_schema, data_tablegroup_schema))) {
LOG_WARN("fail to prepare ls for index schema tablets", KR(ret));
} else if (OB_FAIL(new_table_tablet_allocator.get_ls_id_array(ls_id_array))) {
LOG_WARN("fail to get ls id array", KR(ret));
} else if (OB_FAIL(table_creator.add_create_tablets_of_table_arg(index_schema, ls_id_array,
tenant_data_version, false/*need create major sstable*/))) {
LOG_WARN("create table tablet failed", KR(ret), K(index_schema));
}
}
if (FAILEDx(table_creator.execute())) {
LOG_WARN("execute create partition failed", KR(ret));
}
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = new_table_tablet_allocator.finish(OB_SUCCESS == ret))) {
LOG_WARN("fail to finish new table tablet allocator", KR(tmp_ret));
}
}
RS_TRACE(create_tablets);
return ret;
}
int ObCreateIndexHelper::add_index_name_to_cache_()
{
int ret = OB_SUCCESS;
ObIndexNameChecker &checker = ddl_service_->get_index_name_checker();
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_UNLIKELY(index_schemas_.count() != 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index schemas count not expected", KR(ret), K(index_schemas_.count()));
} else {
ObTableSchema &index_schema = index_schemas_.at(0);
if (OB_FAIL(checker.add_index_name(index_schema))) {
LOG_WARN("fail to add index name", KR(ret), K(index_schema));
}
}
return ret;
}
// self ref table no need to check
// for mock fk table, should check it is exist
// for fk table, should check not doing long ddl
int ObCreateIndexHelper::check_fk_related_table_ddl_(const share::schema::ObTableSchema &data_table_schema,
const share::ObDDLType &ddl_type)
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == tenant_id_ || share::ObDDLType::DDL_INVALID == ddl_type)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", KR(ret), K_(tenant_id), K(ddl_type));
} 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_?
foreign_key_info.child_table_id_ : foreign_key_info.parent_table_id_;
if (data_table_schema.get_table_id() == related_table_id) {
// self no need to check
} else if (foreign_key_info.is_parent_table_mock_) {
const ObMockFKParentTableSchema *related_schema = nullptr;
if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema(related_table_id, related_schema))) {
LOG_WARN("fail to get related mock fk parent table schema", KR(ret), K_(tenant_id), K(related_table_id));
} else if (OB_ISNULL(related_schema)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("mock fk parent table schema is null ptr, may be dropped", KR(ret), K_(tenant_id), K(related_table_id), K(foreign_key_info));
}
} else {
const ObTableSchema *related_schema = nullptr;
bool has_long_running_ddl = false;
if (OB_FAIL(latest_schema_guard_.get_table_schema(related_table_id, related_schema))) {
LOG_WARN("fail to get related table schema", KR(ret), K_(tenant_id), K(related_table_id));
} else if (OB_ISNULL(related_schema)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("related schema is null ptr, may be dropped", KR(ret), K_(tenant_id), 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 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", KR(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", KR(ret), K(check_mode), K_(tenant_id), K(related_table_id));
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "execute ddl while foreign key related table is executing long running ddl");
}
}
}
}
return ret;
}

View File

@ -0,0 +1,78 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OCEANBASE_ROOTSERVER_OB_CREATE_INDEX_HELPER_H_
#define OCEANBASE_ROOTSERVER_OB_CREATE_INDEX_HELPER_H_
#include "rootserver/parallel_ddl/ob_ddl_helper.h"
#include "rootserver/ob_index_builder.h"
namespace oceanbase
{
namespace share
{
namespace schema
{
class ObMultiVersionSchemaService;
}
}
namespace obrpc
{
class ObCreateIndexArg;
class ObAlterTableRes;
}
namespace rootserver
{
class ObCreateIndexHelper : public ObDDLHelper
{
public:
ObCreateIndexHelper(
share::schema::ObMultiVersionSchemaService *schema_service,
const uint64_t tenant_id,
rootserver::ObDDLService &ddl_service,
const obrpc::ObCreateIndexArg &arg,
obrpc::ObAlterTableRes &res);
virtual ~ObCreateIndexHelper();
virtual int execute() override;
private:
int lock_objects_();
int lock_database_by_obj_name_();
int lock_objects_by_name_();
int check_database_legitimacy_();
int lock_objects_by_id_();
int check_table_legitimacy_();
int generate_index_schema_();
int calc_schema_version_cnt_();
int create_index_();
int is_local_generate_schema_(bool &is_local_generate);
int create_table_();
int create_tablets_();
int add_index_name_to_cache_();
int check_fk_related_table_ddl_(const share::schema::ObTableSchema &data_table_schema,
const share::ObDDLType &ddl_type);
private:
const obrpc::ObCreateIndexArg &arg_;
obrpc::ObCreateIndexArg *new_arg_;
obrpc::ObAlterTableRes &res_;
uint64_t database_id_;
const ObTableSchema *orig_data_table_schema_;
ObTableSchema* new_data_table_schema_;
ObArray<ObTableSchema> index_schemas_;
ObSEArray<ObColumnSchemaV2*, 1> gen_columns_;
ObIndexBuilder index_builder_;
ObDDLTaskRecord task_record_;
private:
DISALLOW_COPY_AND_ASSIGN(ObCreateIndexHelper);
};
}
}
#endif//OCEANBASE_ROOTSERVER_OB_CREATE_TABLE_HELPER_H_

View File

@ -139,7 +139,7 @@ int ObCreateTableHelper::execute()
}
if (OB_SUCC(ret)) {
auto *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
int64_t last_schema_version = OB_INVALID_VERSION;
int64_t end_schema_version = OB_INVALID_VERSION;
if (OB_UNLIKELY(new_tables_.count() <= 0)) {
@ -149,7 +149,7 @@ int ObCreateTableHelper::execute()
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tsi schema version generator is null", KR(ret));
} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
LOG_WARN("fail to get current version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_FAIL(tsi_generator->get_end_version(end_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_UNLIKELY(last_schema_version != end_schema_version)) {
@ -204,11 +204,11 @@ int ObCreateTableHelper::lock_objects_()
DEBUG_SYNC(AFTER_PARALLEL_DDL_LOCK_OBJ_BY_NAME);
// 3. prefetch schemas
if (FAILEDx(prefetch_schemas_())) {
LOG_WARN("fail to prefech schemas", KR(ret), K_(tenant_id));
LOG_WARN("fail to prefetch schemas", KR(ret), K_(tenant_id));
}
// 4. lock objects by id
if (FAILEDx(lock_objects_by_id_())) {
LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
LOG_WARN("fail to lock objects by id", KR(ret), K_(tenant_id));
}
// 5. lock objects by id after related objects are locked.
if (FAILEDx(post_lock_objects_by_id_())) {
@ -355,6 +355,7 @@ int ObCreateTableHelper::lock_objects_by_name_()
}
// lock related objects' id for create table (`X` for EXCLUSIVE, `S` for SHARE):
// 0. database (S)
// 1. tablegroup (S)
// 2. audit (S)
// - add share lock for OB_AUDIT_MOCK_USER_ID
@ -377,6 +378,11 @@ int ObCreateTableHelper::lock_objects_by_id_()
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
}
// 0. database
if (FAILEDx(add_lock_object_by_id_(arg_.schema_.get_database_id(),
share::schema::DATABASE_SCHEMA, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database id", KR(ret), K(arg_.schema_.get_database_id()));
}
// 1. tablegroup
const uint64_t tablegroup_id = table.get_tablegroup_id();
if (OB_SUCC(ret) && OB_INVALID_ID != tablegroup_id) {
@ -430,35 +436,8 @@ int ObCreateTableHelper::lock_objects_by_id_()
}
}
// 6. udt
if (OB_SUCC(ret)) {
ObTableSchema::const_column_iterator begin = table.column_begin();
ObTableSchema::const_column_iterator end = table.column_end();
ObSchemaGetterGuard guard;
if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
LOG_WARN("fail to get schema guard", KR(ret));
}
for (; OB_SUCC(ret) && begin != end; begin++) {
ObColumnSchemaV2 *col = (*begin);
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get column schema failed", KR(ret));
} else if (col->get_meta_type().is_user_defined_sql_type()) {
const uint64_t udt_id = col->get_sub_data_type();
if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
// can't add object lock across tenant, assumed that sys inner udt won't be changed.
const ObUDTTypeInfo *udt_info = NULL;
if (OB_FAIL(guard.get_udt_info(OB_SYS_TENANT_ID, udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("inner udt not found", KR(ret), K(udt_id));
}
} else if (OB_FAIL(add_lock_object_by_id_(udt_id,
share::schema::UDT_SCHEMA, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock udt id", KR(ret), K_(tenant_id), K(udt_id));
}
}
} // end for
if (FAILEDx(add_lock_table_udt_id_(table))) {
LOG_WARN("fail to add lock table udt id", KR(ret));
}
if (FAILEDx(lock_existed_objects_by_id_())) {
@ -537,8 +516,6 @@ int ObCreateTableHelper::check_ddl_conflict_()
} else if (!arg_.is_need_check_based_schema_objects()) {
// skip
} else {
ObArray<uint64_t> parent_table_ids;
ObArray<uint64_t> mock_fk_parent_table_ids;
// check schema object infos are all existed.
for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
@ -562,86 +539,11 @@ int ObCreateTableHelper::check_ddl_conflict_()
LOG_WARN("parent table may change, ddl need retry",
KR(ret), K_(tenant_id), K(info));
}
if (OB_FAIL(ret)) {
} else if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_) {
if (!has_exist_in_array(mock_fk_parent_table_ids, info.schema_id_)
&& OB_FAIL(mock_fk_parent_table_ids.push_back(info.schema_id_))) {
LOG_WARN("fail to push back mock fk parent table id", KR(ret), K(info));
}
} else if (TABLE_SCHEMA == info.schema_type_) {
if (!has_exist_in_array(parent_table_ids, info.schema_id_)
&& OB_FAIL(parent_table_ids.push_back(info.schema_id_))) {
LOG_WARN("fail to push back parent table id", KR(ret), K(info));
}
}
}
} // end for
ObArray<ObSchemaIdVersion> parent_table_versions;
if (OB_SUCC(ret) && parent_table_ids.count() > 0) {
if (OB_FAIL(parent_table_versions.reserve(parent_table_ids.count()))) {
LOG_WARN("fail to reserve array", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_table_schema_versions(
parent_table_ids, parent_table_versions))) {
LOG_WARN("fail to get table schema versions", KR(ret));
} else if (parent_table_ids.count() != parent_table_versions.count()) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("parent table may be deleted, ddl need retry",
KR(ret), K_(tenant_id), "base_objs_cnt", parent_table_ids.count(),
"fetch_cnt", parent_table_versions.count());
}
}
ObArray<ObSchemaIdVersion> mock_fk_parent_table_versions;
if (OB_SUCC(ret) && mock_fk_parent_table_ids.count() > 0) {
if (OB_FAIL(mock_fk_parent_table_versions.reserve(mock_fk_parent_table_ids.count()))) {
LOG_WARN("fail to reserve array", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema_versions(
mock_fk_parent_table_ids, mock_fk_parent_table_versions))) {
LOG_WARN("fail to get table schema versions", KR(ret));
} else if (mock_fk_parent_table_ids.count() != mock_fk_parent_table_versions.count()) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("mock fk parent table may be deleted, ddl need retry",
KR(ret), K_(tenant_id), "base_objs_cnt", mock_fk_parent_table_ids.count(),
"fetch_cnt", mock_fk_parent_table_versions.count());
}
}
if (OB_SUCC(ret)) {
for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_
|| TABLE_SCHEMA == info.schema_type_) {
bool find = false;
for (int64_t j = 0; OB_SUCC(ret) && !find && j < parent_table_versions.count(); j++) {
const ObSchemaIdVersion &version = parent_table_versions.at(j);
if (version.get_schema_id() == info.schema_id_) {
find = true;
if (version.get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("parent table may be changed, ddl need retry",
KR(ret), K_(tenant_id), K(info), K(version));
}
}
} // end for
for (int64_t j = 0; OB_SUCC(ret) && !find && j < mock_fk_parent_table_versions.count(); j++) {
const ObSchemaIdVersion &version = mock_fk_parent_table_versions.at(j);
if (version.get_schema_id() == info.schema_id_) {
find = true;
if (version.get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("mock fk parent table may be changed, ddl need retry",
KR(ret), K_(tenant_id), K(info), K(version));
}
}
} // end for
if (OB_SUCC(ret) && !find) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("parent table may be deleted, ddl need retry",
KR(ret), K_(tenant_id), K(info));
}
}
} // end for
if (FAILEDx(check_parallel_ddl_conflict_(arg_.based_schema_object_infos_))) {
LOG_WARN("fail to check parallel ddl conflict", KR(ret));
}
// for replace mock fk parent table:
@ -671,25 +573,6 @@ int ObCreateTableHelper::check_ddl_conflict_()
} // end for
}
// check udt exist & not changed
for (int64_t i = 0; OB_SUCC(ret) && (i < arg_.based_schema_object_infos_.count()); ++i) {
const ObBasedSchemaObjectInfo &info = arg_.based_schema_object_infos_.at(i);
if (UDT_SCHEMA == info.schema_type_) {
const uint64_t udt_id = info.schema_id_;
const ObUDTTypeInfo *udt_info = NULL;
if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
// can't add object lock across tenant, assumed that sys inner udt won't be changed.
} else if (OB_FAIL(latest_schema_guard_.get_udt_info(udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K_(tenant_id), K(udt_id), K(info));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
} else if (udt_info->get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt changed", KR(ret), K(info), KPC(udt_info));
}
}
} // end for
}
const int64_t cost_ts = ObTimeUtility::current_time() - start_ts;
LOG_INFO("check ddl confict", KR(ret), K_(tenant_id), K(cost_ts));
@ -1038,37 +921,8 @@ int ObCreateTableHelper::generate_table_schema_()
}
}
if (OB_SUCC(ret)) {
ObTableSchema::const_column_iterator begin = new_table.column_begin();
ObTableSchema::const_column_iterator end = new_table.column_end();
ObSchemaGetterGuard guard;
if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
LOG_WARN("fail to get schema guard", KR(ret));
}
for (; OB_SUCC(ret) && begin != end; begin++) {
ObColumnSchemaV2 *col = (*begin);
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get column schema failed", KR(ret));
} else if (col->get_meta_type().is_user_defined_sql_type()) {
const uint64_t udt_id = col->get_sub_data_type();
const ObUDTTypeInfo *udt_info = NULL;
if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
// can't add object lock across tenant, assumed that sys inner udt won't be changed.
if (OB_FAIL(guard.get_udt_info(OB_SYS_TENANT_ID, udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("inner udt not found", KR(ret), K(udt_id));
}
} else if (OB_FAIL(latest_schema_guard_.get_udt_info(udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K_(tenant_id), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
}
}
} // end for
if (FAILEDx(check_table_udt_exist_(new_table))) {
LOG_WARN("fail to check table udt exist", KR(ret));
}
// check if constraint name duplicated
@ -2380,7 +2234,7 @@ int ObCreateTableHelper::create_tablets_()
true /*use parallel ddl*/);
const ObTablegroupSchema *data_tablegroup_schema = NULL; // keep NULL if no tablegroup
int64_t last_schema_version = OB_INVALID_VERSION;
auto *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
if (OB_FAIL(table_creator.init(true/*need_tablet_cnt_check*/))) {
LOG_WARN("fail to init table creator", KR(ret));
} else if (OB_FAIL(new_table_tablet_allocator.init())) {

View File

@ -70,7 +70,7 @@ private:
int lock_objects_();
int generate_schemas_();
int calc_schema_version_cnt_();
virtual int calc_schema_version_cnt_() override;
int create_schemas_();
int create_tablets_();
int add_index_name_to_cache_();

View File

@ -83,6 +83,16 @@ int ObCreateViewHelper::generate_schemas_()
return ret;
}
//TODO:(wenyu.ffz) to implement
int ObCreateViewHelper::calc_schema_version_cnt_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
}
return ret;
}
//TODO:(yanmu.ztl) to implement
int ObCreateViewHelper::create_schemas_()
{

View File

@ -44,6 +44,7 @@ public:
private:
int lock_objects_();
int generate_schemas_();
virtual int calc_schema_version_cnt_() override;
int create_schemas_();
private:
const obrpc::ObCreateTableArg &arg_;

View File

@ -126,6 +126,34 @@ int ObDDLHelper::init(rootserver::ObDDLService &ddl_service)
return ret;
}
uint64_t ObDDLHelper::cast_database_name_to_id_(const ObString &database_name)
{
// use OB_ORIGIN_AND_INSENSITIVE and ignore end space to make more conficts for safety.
common::ObCollationType cs_type = ObSchema::get_cs_type_with_cmp_mode(OB_ORIGIN_AND_INSENSITIVE);
bool calc_end_space = false;
uint64_t lock_obj_id = 0;
lock_obj_id = common::ObCharset::hash(
cs_type, database_name.ptr(), database_name.length(),
lock_obj_id, calc_end_space, NULL);
return lock_obj_id;
}
uint64_t ObDDLHelper::cast_obj_name_to_id_(const ObString &database_name, const ObString &obj_name)
{
// 1. use OB_ORIGIN_AND_INSENSITIVE and ignore end space to make more conficts for safety.
// 2. encoded with database name to make less conficts between different databases/users.
common::ObCollationType cs_type = ObSchema::get_cs_type_with_cmp_mode(OB_ORIGIN_AND_INSENSITIVE);
bool calc_end_space = false;
uint64_t lock_obj_id = 0;
lock_obj_id = common::ObCharset::hash(
cs_type, database_name.ptr(), database_name.length(),
lock_obj_id, calc_end_space, NULL);
lock_obj_id = common::ObCharset::hash(
cs_type, obj_name.ptr(), obj_name.length(),
lock_obj_id, calc_end_space, NULL);
return lock_obj_id;
}
int ObDDLHelper::check_inner_stat_()
{
int ret = OB_SUCCESS;
@ -461,13 +489,7 @@ int ObDDLHelper::add_lock_object_by_database_name_(
ret = OB_INVALID_ARGUMENT;
LOG_WARN("database_name is invalid", KR(ret), K(database_name));
} else {
// use OB_ORIGIN_AND_INSENSITIVE and ignore end space to make more conficts for safety.
common::ObCollationType cs_type = ObSchema::get_cs_type_with_cmp_mode(OB_ORIGIN_AND_INSENSITIVE);
bool calc_end_space = false;
uint64_t lock_obj_id = 0;
lock_obj_id = common::ObCharset::hash(
cs_type, database_name.ptr(), database_name.length(),
lock_obj_id, calc_end_space, NULL);
uint64_t lock_obj_id = cast_database_name_to_id_(database_name);
if (OB_FAIL(add_lock_object_to_map_(lock_obj_id, lock_mode, lock_database_name_map_))) {
LOG_WARN("fail to add lock object to map", KR(ret), K(lock_obj_id), K(lock_mode));
}
@ -494,17 +516,7 @@ int ObDDLHelper::add_lock_object_by_name_(
ret = OB_INVALID_ARGUMENT;
LOG_WARN("database_name/object_name is invalid", KR(ret), K(database_name), K(object_name));
} else {
// 1. use OB_ORIGIN_AND_INSENSITIVE and ignore end space to make more conficts for safety.
// 2. encoded with database name to make less conficts between different databases/users.
common::ObCollationType cs_type = ObSchema::get_cs_type_with_cmp_mode(OB_ORIGIN_AND_INSENSITIVE);
bool calc_end_space = false;
uint64_t lock_obj_id = 0;
lock_obj_id = common::ObCharset::hash(
cs_type, database_name.ptr(), database_name.length(),
lock_obj_id, calc_end_space, NULL);
lock_obj_id = common::ObCharset::hash(
cs_type, object_name.ptr(), object_name.length(),
lock_obj_id, calc_end_space, NULL);
uint64_t lock_obj_id = cast_obj_name_to_id_(database_name, object_name);
if (OB_FAIL(add_lock_object_to_map_(lock_obj_id, lock_mode, lock_object_name_map_))) {
LOG_WARN("fail to add lock object to map", KR(ret), K(lock_obj_id), K(lock_mode));
}
@ -635,3 +647,328 @@ int ObDDLHelper::gen_partition_object_and_tablet_ids_(
}
return ret;
}
int ObDDLHelper::obj_lock_database_name(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const ObString &name,
const transaction::tablelock::ObTableLockMode lock_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id || name.empty())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("parallel ddl lock name is invalid", KR(ret), K(name));
} else {
uint64_t lock_obj_id = cast_database_name_to_id_(name);
if (OB_FAIL(obj_lock_with_lock_id_(trans, tenant_id, lock_obj_id, lock_mode, ObLockOBJType::OBJ_TYPE_DATABASE_NAME))) {
LOG_WARN("fail to lock id", KR(ret), K(lock_obj_id), K(lock_mode));
}
}
return ret;
}
int ObDDLHelper::obj_lock_obj_name(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const ObString &database_name,
const ObString &obj_name,
const transaction::tablelock::ObTableLockMode lock_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id || database_name.empty() || obj_name.empty())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("parallel ddl lock name is invalid", KR(ret), K(database_name), K(obj_name));
} else {
uint64_t lock_obj_id = cast_obj_name_to_id_(database_name, obj_name);
if (OB_FAIL(obj_lock_with_lock_id_(trans, tenant_id, lock_obj_id, lock_mode, ObLockOBJType::OBJ_TYPE_OBJECT_NAME))) {
LOG_WARN("fail to lock id", KR(ret), K(lock_obj_id), K(lock_mode));
}
}
return ret;
}
int ObDDLHelper::obj_lock_obj_id(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const uint64_t obj_id,
const transaction::tablelock::ObTableLockMode lock_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id || OB_INVALID_ID == obj_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("parallel ddl lock name is invalid", KR(ret), K(obj_id));
} else if (OB_FAIL(obj_lock_with_lock_id_(trans, tenant_id, obj_id, lock_mode, ObLockOBJType::OBJ_TYPE_COMMON_OBJ))) {
LOG_WARN("fail to lock id", KR(ret), K(obj_id), K(lock_mode));
}
return ret;
}
int ObDDLHelper::obj_lock_with_lock_id_(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const uint64_t obj_id,
const transaction::tablelock::ObTableLockMode lock_mode,
const ObLockOBJType obj_type)
{
int ret = OB_SUCCESS;
observer::ObInnerSQLConnection *conn = nullptr;
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id || OB_INVALID_ID == obj_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("parallel ddl lock name is invalid", KR(ret), K(obj_id));
} else if (OB_ISNULL(conn = dynamic_cast<observer::ObInnerSQLConnection *>
(trans.get_connection()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("trans conn is NULL", KR(ret));
} else {
ObTimeoutCtx ctx;
transaction::tablelock::ObLockObjRequest lock_arg;
lock_arg.obj_type_ = obj_type;
lock_arg.owner_id_ = ObTableLockOwnerID::default_owner();
lock_arg.obj_id_ = obj_id;
lock_arg.lock_mode_ = lock_mode;
lock_arg.op_type_ = ObTableLockOpType::IN_TRANS_COMMON_LOCK;
if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(ctx, GCONF.rpc_timeout))) {
LOG_WARN("fail to set timeout ctx", KR(ret));
} else if (FALSE_IT(lock_arg.timeout_us_ = ctx.get_timeout())) {
} else if (OB_FAIL(ObInnerConnectionLockUtil::lock_obj(tenant_id, lock_arg, conn))) {
LOG_WARN("lock obj failed", KR(ret), K(tenant_id), K(lock_arg));
}
}
return ret;
}
int ObDDLHelper::check_database_legitimacy_(const ObString &database_name, uint64_t &database_id)
{
int ret = OB_SUCCESS;
const ObDatabaseSchema *database_schema = NULL;
database_id = OB_INVALID_ID;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_database_id(database_name, database_id))) {
LOG_WARN("fail to get database id", KR(ret), K_(tenant_id), K(database_name));
} else if (OB_UNLIKELY(OB_INVALID_ID == database_id)) {
ret = OB_ERR_BAD_DATABASE;
LOG_WARN("database not exist", KR(ret), K_(tenant_id), K(database_name));
LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr());
} else if (OB_UNLIKELY(OB_RECYCLEBIN_SCHEMA_ID == database_id)) {
ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
LOG_WARN("can not do parallel ddl in recyclebin database" , KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_database_schema(database_id, database_schema))) {
LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K(database_id), K(database_name));
} else if (OB_ISNULL(database_schema)) {
ret = OB_ERR_BAD_DATABASE;
LOG_WARN("database not exist", KR(ret), K_(tenant_id), K(database_id), K(database_name));
LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr());
} else if (OB_UNLIKELY(database_schema->is_in_recyclebin())) {
ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
LOG_WARN("can not do parallel ddl on table in database which is in recyclebin",
KR(ret), K_(tenant_id), K(database_id), K(database_name));
}
return ret;
}
int ObDDLHelper::check_parallel_ddl_conflict_(const common::ObIArray<share::schema::ObBasedSchemaObjectInfo> &based_schema_object_infos)
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else {
ObArray<uint64_t> parent_table_ids;
ObArray<uint64_t> mock_fk_parent_table_ids;
ObSchemaGetterGuard local_guard;
if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, local_guard))) {
LOG_WARN("fail to get local guard", KR(ret), K_(tenant_id));
}
// check schema object infos are all existed.
for (int64_t i = 0; OB_SUCC(ret) && (i < based_schema_object_infos.count()); ++i) {
const ObBasedSchemaObjectInfo &info = based_schema_object_infos.at(i);
if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_) {
if (!has_exist_in_array(mock_fk_parent_table_ids, info.schema_id_)
&& OB_FAIL(mock_fk_parent_table_ids.push_back(info.schema_id_))) {
LOG_WARN("fail to push back mock fk parent table id", KR(ret), K(info));
}
} else if (TABLE_SCHEMA == info.schema_type_) {
if (!has_exist_in_array(parent_table_ids, info.schema_id_)
&& OB_FAIL(parent_table_ids.push_back(info.schema_id_))) {
LOG_WARN("fail to push back parent table id", KR(ret), K(info));
}
} else if (UDT_SCHEMA == info.schema_type_) {
const uint64_t udt_id = info.schema_id_;
const ObUDTTypeInfo *udt_info = NULL;
const ObUDTTypeInfo *local_udt_info = nullptr;
if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
// can't add object lock across tenant, assumed that sys inner udt won't be changed.
} else if (OB_FAIL(latest_schema_guard_.get_udt_info(udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K_(tenant_id), K(udt_id), K(info));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
} else if (udt_info->get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt changed", KR(ret), K(info), KPC(udt_info));
} else if (OB_FAIL(local_guard.get_udt_info(tenant_id_, udt_id, local_udt_info))) {
LOG_WARN("fail to get local udt info", KR(ret), K_(tenant_id), K(udt_id), K(info));
} else if (OB_ISNULL(local_udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
} else if (local_udt_info->get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt changed", KR(ret), K(info), KPC(local_udt_info));
}
} else {
ret = OB_NOT_SUPPORTED;
LOG_WARN("not supported schema type", KR(ret), K_(tenant_id), K(info));
}
}// end for
ObArray<ObSchemaIdVersion> parent_table_versions;
if (OB_SUCC(ret) && parent_table_ids.count() > 0) {
if (OB_FAIL(parent_table_versions.reserve(parent_table_ids.count()))) {
LOG_WARN("fail to reserve array", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_table_schema_versions(
parent_table_ids, parent_table_versions))) {
LOG_WARN("fail to get table schema versions", KR(ret));
} else if (parent_table_ids.count() != parent_table_versions.count()) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("parent table may be deleted, ddl need retry",
KR(ret), K_(tenant_id), "base_objs_cnt", parent_table_ids.count(),
"fetch_cnt", parent_table_versions.count());
}
}
ObArray<ObSchemaIdVersion> mock_fk_parent_table_versions;
if (OB_SUCC(ret) && mock_fk_parent_table_ids.count() > 0) {
if (OB_FAIL(mock_fk_parent_table_versions.reserve(mock_fk_parent_table_ids.count()))) {
LOG_WARN("fail to reserve array", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_mock_fk_parent_table_schema_versions(
mock_fk_parent_table_ids, mock_fk_parent_table_versions))) {
LOG_WARN("fail to get table schema versions", KR(ret));
} else if (mock_fk_parent_table_ids.count() != mock_fk_parent_table_versions.count()) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("mock fk parent table may be deleted, ddl need retry",
KR(ret), K_(tenant_id), "base_objs_cnt", mock_fk_parent_table_ids.count(),
"fetch_cnt", mock_fk_parent_table_versions.count());
}
}
for (int64_t i = 0; OB_SUCC(ret) && (i < based_schema_object_infos.count()); ++i) {
const ObBasedSchemaObjectInfo &info = based_schema_object_infos.at(i);
if (MOCK_FK_PARENT_TABLE_SCHEMA == info.schema_type_
|| TABLE_SCHEMA == info.schema_type_) {
bool find = false;
for (int64_t j = 0; OB_SUCC(ret) && !find && j < parent_table_versions.count(); j++) {
const ObSchemaIdVersion &version = parent_table_versions.at(j);
if (version.get_schema_id() == info.schema_id_) {
find = true;
if (version.get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("parent table may be changed, ddl need retry",
KR(ret), K_(tenant_id), K(info), K(version));
}
}
} // end for
for (int64_t j = 0; OB_SUCC(ret) && !find && j < mock_fk_parent_table_versions.count(); j++) {
const ObSchemaIdVersion &version = mock_fk_parent_table_versions.at(j);
if (version.get_schema_id() == info.schema_id_) {
find = true;
if (version.get_schema_version() != info.schema_version_) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("mock fk parent table may be changed, ddl need retry",
KR(ret), K_(tenant_id), K(info), K(version));
}
}
} // end for
if (OB_SUCC(ret) && !find) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("parent table may be deleted, ddl need retry",
KR(ret), K_(tenant_id), K(info));
}
}
} // end for
}
return ret;
}
int ObDDLHelper::add_lock_table_udt_id_(const ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else {
ObTableSchema::const_column_iterator begin = table_schema.column_begin();
ObTableSchema::const_column_iterator end = table_schema.column_end();
ObSchemaGetterGuard guard;
if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
LOG_WARN("fail to get schema guard", KR(ret));
}
for (; OB_SUCC(ret) && begin != end; begin++) {
ObColumnSchemaV2 *col = (*begin);
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get column schema failed", KR(ret));
} else if (col->is_extend()) {
const uint64_t udt_id = col->get_sub_data_type();
if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
// can't add object lock across tenant, assumed that sys inner udt won't be changed.
const ObUDTTypeInfo *udt_info = NULL;
if (OB_FAIL(guard.get_udt_info(OB_SYS_TENANT_ID, udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("inner udt not found", KR(ret), K(udt_id));
}
} else if (OB_FAIL(add_lock_object_by_id_(udt_id,
share::schema::UDT_SCHEMA, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock udt id", KR(ret), K_(tenant_id), K(udt_id));
}
}
} // end for
}
return ret;
}
int ObDDLHelper::check_table_udt_exist_(const ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else {
ObTableSchema::const_column_iterator begin = table_schema.column_begin();
ObTableSchema::const_column_iterator end = table_schema.column_end();
ObSchemaGetterGuard guard;
ObSchemaGetterGuard local_guard;
if (OB_FAIL(schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
LOG_WARN("fail to get schema guard", KR(ret));
} else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, local_guard))) {
LOG_WARN("fail to get local guard", KR(ret), K_(tenant_id));
}
for (; OB_SUCC(ret) && begin != end; begin++) {
ObColumnSchemaV2 *col = (*begin);
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get column schema failed", KR(ret));
} else if (col->is_extend()) {
const uint64_t udt_id = col->get_sub_data_type();
const ObUDTTypeInfo *udt_info = NULL;
const ObUDTTypeInfo *local_udt_info = nullptr;
if (is_inner_object_id(udt_id) && !is_sys_tenant(tenant_id_)) {
// can't add object lock across tenant, assumed that sys inner udt won't be changed.
if (OB_FAIL(guard.get_udt_info(OB_SYS_TENANT_ID, udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("inner udt not found", KR(ret), K(udt_id));
}
} else if (OB_FAIL(latest_schema_guard_.get_udt_info(udt_id, udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K_(tenant_id), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt doesn't exist", KR(ret), K_(tenant_id), K(udt_id));
} else if (OB_FAIL(local_guard.get_udt_info(tenant_id_, udt_id, local_udt_info))) {
LOG_WARN("fail to get udt info in local guard", KR(ret), K_(tenant_id), K(udt_id));
} else if (OB_ISNULL(local_udt_info)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("udt doesn't exist in local guard", KR(ret), K_(tenant_id), K(udt_id));
}
}
} // end for
}
return ret;
}

View File

@ -68,11 +68,28 @@ public:
int init(rootserver::ObDDLService &ddl_service);
virtual int execute();
static int obj_lock_database_name(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const ObString &name,
const transaction::tablelock::ObTableLockMode lock_mode);
static int obj_lock_obj_name(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const ObString &database_name,
const ObString &obj_name,
const transaction::tablelock::ObTableLockMode lock_mode);
static int obj_lock_obj_id(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const uint64_t obj_id,
const transaction::tablelock::ObTableLockMode lock_mode);
protected:
virtual int check_inner_stat_();
/* main actions */
int start_ddl_trans_();
virtual int calc_schema_version_cnt_() = 0;
int gen_task_id_and_schema_versions_();
int serialize_inc_schema_dict_();
int wait_ddl_trans_();
@ -109,6 +126,11 @@ protected:
const common::ObString &constraint_name,
const bool is_foreign_key,
bool &exist);
int check_database_legitimacy_(const ObString &database_name, uint64_t &database_id);
int check_parallel_ddl_conflict_(const common::ObIArray<share::schema::ObBasedSchemaObjectInfo> &based_schema_object_infos);
int add_lock_table_udt_id_(const ObTableSchema &table_schema);
int check_table_udt_exist_(const ObTableSchema &table_schema);
private:
int add_lock_object_to_map_(
const uint64_t lock_obj_id,
@ -117,6 +139,14 @@ private:
int lock_objects_in_map_(
const transaction::tablelock::ObLockOBJType obj_type,
ObjectLockMap &lock_map);
static uint64_t cast_database_name_to_id_(const ObString &database_name);
static uint64_t cast_obj_name_to_id_(const ObString &database_name, const ObString &obj_name);
static int obj_lock_with_lock_id_(
ObDDLSQLTransaction &trans,
const uint64_t tenant_id,
const uint64_t obj_id,
const transaction::tablelock::ObTableLockMode lock_mode,
const ObLockOBJType obj_type);
protected:
bool inited_;
share::schema::ObMultiVersionSchemaService *schema_service_;

View File

@ -77,7 +77,7 @@ int ObIndexNameCache::check_index_name_exist(
data_table_id = OB_INVALID_ID;
} else {
uint64_t data_table_id = ObSimpleTableSchemaV2::extract_data_table_id_from_index_name(index_name);
if (OB_INVALID_ID == database_id) {
if (OB_INVALID_ID == data_table_id) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid index name", KR(ret), K(index_name));
} else if (OB_FAIL(ObSimpleTableSchemaV2::get_index_name(index_name, idx_name))) {

View File

@ -0,0 +1,392 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX RS
#include "rootserver/parallel_ddl/ob_set_comment_helper.h"
#include "share/ob_rpc_struct.h"
#include "share/schema/ob_table_sql_service.h"
#include "share/schema/ob_multi_version_schema_service.h"
#include "rootserver/ob_snapshot_info_manager.h"
#include "storage/ddl/ob_ddl_lock.h"
#include "share/ob_debug_sync.h"
using namespace oceanbase::lib;
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
using namespace oceanbase::rootserver;
ObSetCommentHelper::ObSetCommentHelper(
share::schema::ObMultiVersionSchemaService *schema_service,
const uint64_t tenant_id,
const obrpc::ObSetCommentArg &arg,
obrpc::ObParallelDDLRes &res)
: ObDDLHelper(schema_service, tenant_id),
arg_(arg),
res_(res),
database_id_(OB_INVALID_ID),
table_id_(OB_INVALID_ID),
orig_table_schema_(nullptr),
new_table_schema_(nullptr),
new_column_schemas_()
{}
ObSetCommentHelper::~ObSetCommentHelper()
{
}
int ObSetCommentHelper::check_inner_stat_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObDDLHelper::check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (!arg_.is_valid()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("arg is invalid", KR(ret), K(arg_));
}
return ret;
}
int ObSetCommentHelper::execute()
{
int ret = OB_SUCCESS;
RS_TRACE(parallel_ddl_begin);
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(start_ddl_trans_())) {
LOG_WARN("fail to start ddl trans", KR(ret));
} else if (OB_FAIL(lock_objects_())) {
LOG_WARN("fail to lock objects", KR(ret));
} else if (OB_FAIL(check_table_legitimacy_())) {
LOG_WARN("fail to check comment", KR(ret));
} else if (OB_FAIL(generate_schemas_())) {
LOG_WARN("fail to generate schemas", KR(ret));
} else if (OB_FAIL(calc_schema_version_cnt_())) {
LOG_WARN("fail to calc schema version cnt", KR(ret));
} else if (OB_FAIL(gen_task_id_and_schema_versions_())) {
LOG_WARN("fail to gen task id and schema versions", KR(ret));
} else if (OB_FAIL(alter_schema_())) {
LOG_WARN("fail to create schemas", KR(ret));
} else if (OB_FAIL(serialize_inc_schema_dict_())) {
LOG_WARN("fail to serialize inc schema dict", KR(ret));
} else if (OB_FAIL(wait_ddl_trans_())) {
LOG_WARN("fail to wait ddl trans", KR(ret));
}
if (OB_FAIL(end_ddl_trans_(ret))) { //won't overwrite ret
LOG_WARN("fail to end ddl trans", KR(ret));
} else {
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
int64_t last_schema_version = OB_INVALID_VERSION;
int64_t end_schema_version = OB_INVALID_VERSION;
if (OB_ISNULL(tsi_generator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tsi generator is null", KR(ret));
} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
LOG_WARN("fail to get current version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_FAIL(tsi_generator->get_end_version(end_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_UNLIKELY(last_schema_version != end_schema_version)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("too much schema versions may be allocated", KR(ret), KPC(tsi_generator));
} else {
res_.schema_version_ = last_schema_version;
}
}
RS_TRACE(parallel_ddl_end);
FORCE_PRINT_TRACE(THE_RS_TRACE, "[parallel set comment]");
return ret;
}
int ObSetCommentHelper::lock_objects_()
{
int ret = OB_SUCCESS;
DEBUG_SYNC(BEFORE_PARALLEL_DDL_LOCK);
const ObDatabaseSchema *database_schema = nullptr;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(lock_databases_by_obj_name_())) { // lock database name
LOG_WARN("fail to lock databases by obj name", KR(ret), K_(tenant_id));
} else if (OB_FAIL(check_database_legitimacy_())) { // check database legitimacy
LOG_WARN("fail to check database legitimacy", KR(ret), K_(tenant_id));
} else if (OB_FAIL(lock_objects_by_name_())) { // lock object name
LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
} else if (OB_FAIL(lock_objects_by_id_())) { // lock objects by id
LOG_WARN("fail to lock objects by id" , KR(ret), K_(tenant_id));
}
DEBUG_SYNC(AFTER_PARALLEL_DDL_LOCK);
RS_TRACE(lock_objects);
if (FAILEDx(lock_for_common_ddl_())) { // online ddl lock & table lock
LOG_WARN("fail to lock for common ddl", KR(ret));
} else if (OB_UNLIKELY(database_id_ != orig_table_schema_->get_database_id())) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("database_id_ is not equal to table schema's databse_id",
KR(ret), K_(database_id), K(orig_table_schema_->get_database_id()));
} else if (OB_FAIL(latest_schema_guard_.get_database_schema(database_id_, database_schema))) {
LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K_(database_id));
} else if (OB_ISNULL(database_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("databse_schema is null", KR(ret));
} else if (OB_UNLIKELY(database_schema->get_database_name_str() != arg_.database_name_)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("database_schema's database name not equal to arg",
KR(ret), K(database_schema->get_database_name_str()), K_(arg_.database_name));
}
return ret;
}
// Lock ddl related database by name
// 1. database (S)
// - to alter table
int ObSetCommentHelper::lock_databases_by_obj_name_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else {
const ObString &database_name = arg_.database_name_;
if (OB_FAIL(add_lock_object_by_database_name_(database_name, transaction::tablelock::SHARE))) {
LOG_WARN("fail to add lock database by name", KR(ret), K_(tenant_id), K(database_name));
} else if (OB_FAIL(lock_databases_by_name_())) {
LOG_WARN("fail to lock databases by name", KR(ret), K_(tenant_id));
}
}
return ret;
}
// check database not in recyclebin
int ObSetCommentHelper::check_database_legitimacy_()
{
int ret = OB_SUCCESS;
const ObString &database_name = arg_.database_name_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(ObDDLHelper::check_database_legitimacy_(database_name, database_id_))) {
LOG_WARN("fail to check database legitimacy", KR(ret), K(database_name));
}
return ret;
}
// lock table's name object lock (x)
int ObSetCommentHelper::lock_objects_by_name_()
{
int ret = OB_SUCCESS;
const ObString &database_name = arg_.database_name_;
const ObString &table_name = arg_.table_name_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(add_lock_object_by_name_(database_name, table_name,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock object by table name", KR(ret), K_(tenant_id), K(database_name), K(table_name));
} else if (OB_FAIL(lock_existed_objects_by_name_())) {
LOG_WARN("fail to lock objects by name", KR(ret), K_(tenant_id));
}
return ret;
}
// lock table' id for comment (x)
int ObSetCommentHelper::lock_objects_by_id_()
{
int ret = OB_SUCCESS;
ObTableType table_type;
int64_t schema_version = OB_INVALID_VERSION;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == database_id_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("database is not exist", KR(ret), K_(tenant_id), K_(arg_.database_name));
} else if (OB_FAIL(add_lock_object_by_id_(database_id_,
share::schema::DATABASE_SCHEMA, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database id", KR(ret), K_(database_id));
} else if (OB_FAIL(latest_schema_guard_.get_table_id(database_id_, arg_.session_id_, arg_.table_name_, table_id_, table_type, schema_version))) {
LOG_WARN("fail to get table id", KR(ret), K_(database_id), K_(arg_.session_id), K_(arg_.table_name));
} else if (OB_UNLIKELY(OB_INVALID_ID == table_id_)) {
ret = OB_ERR_OBJECT_NOT_EXIST;
LOG_WARN("table not exist", KR(ret), K_(database_id), K_(arg_.session_id), K_(arg_.table_name));
} else if (OB_FAIL(add_lock_object_by_id_(table_id_,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock table id", KR(ret), K_(tenant_id));
} else if (OB_FAIL(lock_existed_objects_by_id_())) {
LOG_WARN("fail to lock objects by id", KR(ret));
}
return ret;
}
int ObSetCommentHelper::check_table_legitimacy_()
{
int ret = OB_SUCCESS;
bool is_oracle_mode = false;
int64_t schema_version = OB_INVALID_VERSION;
bool is_exist = false;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(orig_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig_table_schema_ is nullptr", KR(ret), K_(table_id));
} else if (OB_UNLIKELY(orig_table_schema_->is_materialized_view())) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("alter materialized view is not supported", KR(ret));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter materialized view is");
} else if (OB_UNLIKELY(orig_table_schema_->is_ctas_tmp_table())) {
ret = OB_ERR_WRONG_OBJECT;
LOG_USER_ERROR(OB_ERR_WRONG_OBJECT,
to_cstring(arg_.database_name_), to_cstring(arg_.table_name_), "BASE TABLE");
} else if (OB_UNLIKELY((!orig_table_schema_->is_user_table()
&& !orig_table_schema_->is_tmp_table()
&& !orig_table_schema_->is_view_table()
&& !orig_table_schema_->is_external_table()))) {
ret = OB_ERR_WRONG_OBJECT;
LOG_USER_ERROR(OB_ERR_WRONG_OBJECT,
to_cstring(arg_.database_name_), to_cstring(arg_.table_name_), "BASE TABLE");
} else if (OB_UNLIKELY(orig_table_schema_->is_sys_view() && !GCONF.enable_sys_table_ddl)) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("comment on sys view is not allowed", KR(ret), K(orig_table_schema_->get_table_id()));
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter system view");
} else if (OB_UNLIKELY(orig_table_schema_->is_in_recyclebin())) {
ret = OB_ERR_OPERATION_ON_RECYCLE_OBJECT;
LOG_WARN("can not comment table in recyclebin", KR(ret), K(orig_table_schema_->is_in_recyclebin()));
} else if (OB_UNLIKELY(orig_table_schema_->is_in_splitting())) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("table is physical or logical split can not split", KR(ret), KPC(orig_table_schema_));
} else if (OB_FAIL(orig_table_schema_->check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check oracle compat mode", KR(ret));
} else if (OB_UNLIKELY(!is_oracle_mode)) {
// if need to support parallel comment on mysql mode,
// should check column name not duplicate to prevent modify the same column in one sql
ret = OB_NOT_SUPPORTED;
LOG_WARN("not support parallel comment on mysql mode right know", KR(ret));
} else if (OB_FAIL(ddl_service_->get_snapshot_mgr().check_restore_point(
ddl_service_->get_sql_proxy(), tenant_id_, orig_table_schema_->get_table_id(), is_exist))) {
LOG_WARN("failed to check restore point", KR(ret), K_(tenant_id));
} else if (OB_UNLIKELY(is_exist)) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("restore point exist, cannot alter ", KR(ret), K_(tenant_id), K(orig_table_schema_->get_table_id()));
}
RS_TRACE(check_schemas);
return ret;
}
// here get the table schema before lock it. it is rely on mutex between parallel ddl and serial ddl
int ObSetCommentHelper::lock_for_common_ddl_()
{
int ret = OB_SUCCESS;
int64_t schema_version = OB_INVALID_VERSION;
uint64_t tenant_data_version = 0;
if (OB_UNLIKELY(OB_INVALID_ID == database_id_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("database is not exist", KR(ret), K_(tenant_id), K_(arg_.database_name));
} else if (OB_UNLIKELY(OB_INVALID_ID == table_id_)) {
ret = OB_ERR_OBJECT_NOT_EXIST;
LOG_WARN("table not exist", KR(ret), K_(database_id), K_(arg_.session_id), K_(arg_.table_name));
} else if (OB_FAIL(latest_schema_guard_.get_table_schema(table_id_, orig_table_schema_))) {
LOG_WARN("fail to get orig table schema", KR(ret), K_(table_id));
} else if (OB_ISNULL(orig_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig_table_schema_ is nullptr", KR(ret), K_(table_id));
} else if (OB_UNLIKELY(!orig_table_schema_->check_can_do_ddl())) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("offline ddl is being executed, other ddl operations are not allowed", KR(ret), KP(orig_table_schema_));
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id_, tenant_data_version))) {
LOG_WARN("get min data version failed", KR(ret), K_(tenant_id));
} else {
if (OB_FAIL(ObDDLLock::lock_for_common_ddl_in_trans(*orig_table_schema_, false/*require_strict_binary_format*/,trans_))) {
LOG_WARN("fail to lock for common ddl", KR(ret));
}
}
RS_TRACE(lock_common_ddl);
return ret;
}
int ObSetCommentHelper::generate_schemas_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(orig_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("orig table schema is nullptr", KR(ret));
} else if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, *orig_table_schema_, new_table_schema_))) {
LOG_WARN("fail to alloc schema", KR(ret));
} else {
if (obrpc::ObSetCommentArg::COMMENT_TABLE == arg_.op_type_) {
if (OB_FAIL(new_table_schema_->set_comment(arg_.table_comment_))) {
LOG_WARN("fail to set table comment", KR(ret));
}
} else if (obrpc::ObSetCommentArg::COMMENT_COLUMN == arg_.op_type_) {
for (uint64_t column_idx = 0; OB_SUCC(ret) && column_idx < arg_.column_name_list_.size(); column_idx++) {
const ObString &orig_column_name = arg_.column_name_list_.at(column_idx);
ObColumnSchemaV2 *new_column_schema = nullptr;
new_column_schema = new_table_schema_->get_column_schema(orig_column_name);
if (OB_ISNULL(new_column_schema)) {
ret = OB_ERR_BAD_FIELD_ERROR;
LOG_USER_ERROR(OB_ERR_BAD_FIELD_ERROR, orig_column_name.length(), orig_column_name.ptr(),
orig_table_schema_->get_table_name_str().length(),
orig_table_schema_->get_table_name_str().ptr());
LOG_WARN("failed to find old column schema", KR(ret), K(orig_column_name));
} else if (FALSE_IT(new_column_schema->set_comment(arg_.column_comment_list_.at(column_idx)))){
} else if (OB_FAIL(new_column_schemas_.push_back(new_column_schema))) {
LOG_WARN("fail to assign column schema", KR(ret));
}
}
}
}
RS_TRACE(generate_schemas);
return ret;
}
int ObSetCommentHelper::calc_schema_version_cnt_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else {
// 0. data table
// for now just one comment at a once
schema_version_cnt_ = 1;
// 1503
schema_version_cnt_++;
}
return ret;
}
int ObSetCommentHelper::alter_schema_()
{
int ret = OB_SUCCESS;
const int64_t start_ts = ObTimeUtility::current_time();
ObSchemaService *schema_service_impl = nullptr;
int64_t new_schema_version = OB_INVALID_VERSION;
const ObString *ddl_stmt_str = &arg_.ddl_stmt_str_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(schema_service_impl = schema_service_->get_schema_service())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema_service impl is null", KR(ret));
} else if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
LOG_WARN("fail to gen new schema version", KR(ret), K_(tenant_id));
} else {
for (uint64_t column_idx = 0; OB_SUCC(ret) && column_idx < arg_.column_name_list_.size(); column_idx++) {
new_column_schemas_.at(column_idx)->set_schema_version(new_schema_version);
if (OB_FAIL(schema_service_impl->get_table_sql_service().update_single_column(
trans_, *orig_table_schema_, *new_table_schema_, *new_column_schemas_.at(column_idx), false /* record ddl operation*/))) {
LOG_WARN("fail to update single column", KR(ret));
}
}
new_table_schema_->set_schema_version(new_schema_version);
if (FAILEDx(schema_service_impl->get_table_sql_service().only_update_table_options(
trans_,
*new_table_schema_,
OB_DDL_ALTER_TABLE,
ddl_stmt_str))) {
LOG_WARN("fail to alter table option", KR(ret));
}
}
RS_TRACE(alter_schemas);
return ret;
}

View File

@ -0,0 +1,72 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OCEANBASE_ROOTSERVER_OB_COMMENT_H_
#define OCEANBASE_ROOTSERVER_OB_COMMENT_H_
#include "rootserver/parallel_ddl/ob_ddl_helper.h"
#include "lib/hash/ob_hashmap.h"
namespace oceanbase
{
namespace share
{
namespace schema
{
class ObMultiVersionSchemaService;
}
}
namespace obrpc
{
class ObSetCommentArg;
class ObSetCommenttRes;
}
namespace rootserver
{
class ObSetCommentHelper : public ObDDLHelper
{
public:
ObSetCommentHelper(
share::schema::ObMultiVersionSchemaService *schema_service,
const uint64_t tenant_id,
const obrpc::ObSetCommentArg &arg,
obrpc::ObParallelDDLRes &res);
virtual ~ObSetCommentHelper();
virtual int execute() override;
private:
virtual int check_inner_stat_() override;
int lock_objects_();
int check_database_legitimacy_();
int generate_schemas_();
virtual int calc_schema_version_cnt_() override;
int alter_schema_();
int lock_databases_by_obj_name_();
int lock_objects_by_id_();
int lock_objects_by_name_();
int lock_for_common_ddl_();
int check_table_legitimacy_();
private:
const obrpc::ObSetCommentArg &arg_;
obrpc::ObParallelDDLRes &res_;
uint64_t database_id_;
uint64_t table_id_;
const ObTableSchema* orig_table_schema_;
ObTableSchema* new_table_schema_;
common::ObSArray<ObColumnSchemaV2*> new_column_schemas_;
private:
DISALLOW_COPY_AND_ASSIGN(ObSetCommentHelper);
};
} // end namespace rootserver
} // end namespace oceanbase
#endif//OCEANBASE_ROOTSERVER_OB_COMMENT_H_

View File

@ -0,0 +1,262 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX RS
#include "rootserver/parallel_ddl/ob_update_index_status_helper.h"
#include "share/schema/ob_table_sql_service.h"
#include "src/storage/ddl/ob_ddl_lock.h"
using namespace oceanbase::lib;
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
using namespace oceanbase::rootserver;
ObUpdateIndexStatusHelper::ObUpdateIndexStatusHelper(
share::schema::ObMultiVersionSchemaService *schema_service,
const uint64_t tenant_id,
const obrpc::ObUpdateIndexStatusArg &arg,
obrpc::ObParallelDDLRes &res)
: ObDDLHelper(schema_service, tenant_id),
arg_(arg),
res_(res),
orig_index_table_schema_(nullptr),
new_data_table_schema_(nullptr),
new_status_(arg_.status_),
index_table_exist_(true),
database_id_(OB_INVALID_ID)
{}
ObUpdateIndexStatusHelper::~ObUpdateIndexStatusHelper()
{
}
int ObUpdateIndexStatusHelper::execute()
{
int ret = OB_SUCCESS;
RS_TRACE(parallel_ddl_begin);
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(start_ddl_trans_())) {
LOG_WARN("fail to start ddl trans", KR(ret));
} else if (OB_FAIL(lock_objects_())) {
LOG_WARN("fail to lock objects", KR(ret));
} else if (OB_FAIL(check_and_set_schema_())) {
LOG_WARN("fail to check update status", KR(ret));
} else if (OB_FAIL(calc_schema_version_cnt_())) {
LOG_WARN("fail to calc schema version cnt");
} else if (OB_FAIL(gen_task_id_and_schema_versions_())) {
LOG_WARN("fail to gen task id and schema versions");
} else if (OB_FAIL(update_status_())) {
LOG_WARN("fail to update status", KR(ret));
} else if (OB_FAIL(serialize_inc_schema_dict_())) {
LOG_WARN("fail to serialize inc schema dict", KR(ret));
} else if (OB_FAIL(wait_ddl_trans_())) {
LOG_WARN("fail to wait ddl trans", KR(ret));
}
if (OB_FAIL(end_ddl_trans_(ret))) { // won't lose err code
//overwrite ret
LOG_WARN("fail to end ddl trans", KR(ret));
} else {
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
int64_t last_schema_version = OB_INVALID_VERSION;
int64_t end_schema_version = OB_INVALID_VERSION;
if (OB_ISNULL(tsi_generator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tsi schema version generator is null", KR(ret));
} else if (OB_FAIL(tsi_generator->get_current_version(last_schema_version))) {
LOG_WARN("fail to get current version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_FAIL(tsi_generator->get_end_version(end_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_UNLIKELY(last_schema_version != end_schema_version)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("too much schema versions may be allocated", KR(ret), KPC(tsi_generator));
} else {
res_.schema_version_ = end_schema_version;
}
}
if (!index_table_exist_) {
// regard as the index table has been dropped and scheduler will clean up the task record in success state.
ret = OB_SUCCESS;
}
RS_TRACE(parallel_ddl_end);
FORCE_PRINT_TRACE(THE_RS_TRACE, "[parallel update index status]");
return ret;
}
int ObUpdateIndexStatusHelper::lock_objects_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(lock_database_by_obj_name_())) {
LOG_WARN("fail to lock databse by obj name", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_database_id(arg_.database_name_, database_id_))) {
LOG_WARN("fail to get database id", KR(ret), K_(tenant_id), K_(arg_.database_name));
} else if (OB_UNLIKELY(OB_INVALID_ID == database_id_)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("invalid database_id, database name may changed", KR(ret), K_(tenant_id), K_(arg_.database_name));
} else if (OB_FAIL(add_lock_object_by_id_(database_id_,
share::schema::DATABASE_SCHEMA, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database id", KR(ret), K_(database_id));
} else if (OB_FAIL(add_lock_object_by_id_(arg_.data_table_id_,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock data table", KR(ret), K_(arg_.data_table_id));
} else if (OB_FAIL(add_lock_object_by_id_(arg_.index_table_id_,
share::schema::TABLE_SCHEMA, transaction::tablelock::EXCLUSIVE))) {
LOG_WARN("fail to lock index table id", KR(ret), K_(arg_.index_table_id));
} else if (OB_FAIL(lock_existed_objects_by_id_())) {
LOG_WARN("fail to lock objects by id", KR(ret));
}
RS_TRACE(lock_objects);
return ret;
}
int ObUpdateIndexStatusHelper::lock_database_by_obj_name_()
{
int ret = OB_SUCCESS;
const ObString &database_name = arg_.database_name_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_FAIL(add_lock_object_by_database_name_(database_name, transaction::tablelock::SHARE))) {
LOG_WARN("fail to lock database by name", KR(ret), K_(tenant_id), K(database_name));
} else if (OB_FAIL(lock_databases_by_name_())) {
LOG_WARN("fail to lock databases by name", KR(ret), K_(tenant_id));
}
return ret;
}
int ObUpdateIndexStatusHelper::check_and_set_schema_()
{
int ret = OB_SUCCESS;
const ObTableSchema *orig_data_table_schema = nullptr;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (INDEX_STATUS_INDEX_ERROR == new_status_ && arg_.convert_status_) {
const ObTenantSchema *tenant_schema = nullptr;
if (OB_FAIL(latest_schema_guard_.get_tenant_schema(tenant_id_, tenant_schema))) {
LOG_WARN("fail to get tenant schema", KR(ret));
} else if (OB_ISNULL(tenant_schema)) {
ret = OB_TENANT_NOT_EXIST;
LOG_WARN("tenant not exist", KR(ret), K_(tenant_id));
} else if (tenant_schema->is_restore()) {
new_status_ = INDEX_STATUS_RESTORE_INDEX_ERROR;
LOG_INFO("conver error index status", KR(ret), K_(new_status));
}
}
const ObDatabaseSchema *database_schema = NULL;
if (FAILEDx(latest_schema_guard_.get_table_schema(arg_.index_table_id_, orig_index_table_schema_))) {
LOG_WARN("fail to get index table schema", KR(ret), K_(arg_.index_table_id));
} else if (OB_ISNULL(orig_index_table_schema_)) {
ret = OB_ERR_OBJECT_NOT_EXIST;
index_table_exist_ = false;
LOG_WARN("index table schema is null, may be droped", KR(ret), K_(arg_.index_table_id));
} else if (OB_UNLIKELY(database_id_ != orig_index_table_schema_->get_database_id())) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("databse_id_ is not euqal to index_table's database_id",
KR(ret), K_(database_id), K(orig_index_table_schema_->get_database_id()));
} else if (OB_FAIL(latest_schema_guard_.get_database_schema(database_id_, database_schema))) {
LOG_WARN("fail to get database schema", KR(ret), K_(tenant_id), K_(database_id));
} else if (OB_ISNULL(database_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("databse_schema is null", KR(ret));
} else if (OB_UNLIKELY(database_schema->get_database_name_str() != arg_.database_name_)) {
ret = OB_ERR_PARALLEL_DDL_CONFLICT;
LOG_WARN("database_schema's database name not equal to arg",
KR(ret), K(database_schema->get_database_name_str()), K_(arg_.database_name));
} else if (is_available_index_status(new_status_) && !orig_index_table_schema_->is_unavailable_index()) {
ret = OB_EAGAIN;
LOG_WARN("set index status to available, but previous status is not unavailable, which is not expected", KR(ret));
} else if (OB_FAIL(latest_schema_guard_.get_table_schema(arg_.data_table_id_, orig_data_table_schema))) {
LOG_WARN("fail to get data table schema", KR(ret), K_(arg_.data_table_id));
} else if (OB_ISNULL(orig_data_table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail data table is null", KR(ret));
} else if (OB_FAIL(ObSchemaUtils::alloc_schema(allocator_, *orig_data_table_schema, new_data_table_schema_))) {
LOG_WARN("fail to alloc new table schema", KR(ret));
} else {
new_data_table_schema_->set_in_offline_ddl_white_list(arg_.in_offline_ddl_white_list_);
}
RS_TRACE(check_schemas);
return ret;
}
int ObUpdateIndexStatusHelper::calc_schema_version_cnt_()
{
int ret = OB_SUCCESS;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else {
// update index status
schema_version_cnt_ = 1;
// update data table schema version
schema_version_cnt_++;
// 1503
schema_version_cnt_++;
}
return ret;
}
int ObUpdateIndexStatusHelper::update_status_()
{
int ret = OB_SUCCESS;
int64_t new_schema_version = OB_INVALID_VERSION;
ObSchemaService *schema_service = schema_service_->get_schema_service();
const ObString *ddl_stmt_str = arg_.ddl_stmt_str_.empty() ? nullptr : &arg_.ddl_stmt_str_;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_ISNULL(schema_service)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema service is nullptr", KR(ret));
} else if (OB_ISNULL(orig_index_table_schema_)
|| OB_ISNULL(new_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table schema is null", KR(ret), KP(orig_index_table_schema_), KP(new_data_table_schema_));
} else {
ObSchemaService *schema_service = schema_service_->get_schema_service();
if (OB_ISNULL(schema_service)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema service is nullptr", KR(ret));
} else if (OB_FAIL(schema_service_->gen_new_schema_version(tenant_id_, new_schema_version))) {
LOG_WARN("fail to gen new schema version", KR(ret), K_(tenant_id));
} else if (OB_FAIL(schema_service->get_table_sql_service().update_index_status(
*new_data_table_schema_, arg_.index_table_id_, new_status_, new_schema_version, trans_, ddl_stmt_str))) {
LOG_WARN("fail to update index status", KR(ret), K_(arg_.index_table_id), K_(arg_.data_table_id), K_(new_status));
} else if (arg_.task_id_ != 0) {
ObSchemaVersionGenerator *tsi_generator = GET_TSI(TSISchemaVersionGenerator);
int64_t consensus_schema_version = OB_INVALID_VERSION;
if (OB_FAIL(tsi_generator->get_end_version(consensus_schema_version))) {
LOG_WARN("fail to get end version", KR(ret), K_(tenant_id), K_(arg));
} else if (OB_FAIL(ObDDLTaskRecordOperator::update_consensus_schema_version(
trans_, tenant_id_, arg_.task_id_, consensus_schema_version))) {
LOG_WARN("fail to update consensus_schema_version", KR(ret), K_(tenant_id), K_(arg_.task_id), K(consensus_schema_version));
} else if (orig_index_table_schema_->get_index_status() != new_status_ && new_status_ == INDEX_STATUS_AVAILABLE) {
ObTableLockOwnerID owner_id;
if (OB_ISNULL(new_data_table_schema_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("data_table_schema is null", KR(ret));
} else if (OB_FAIL(owner_id.convert_from_value(ObLockOwnerType::DEFAULT_OWNER_TYPE,
arg_.task_id_))) {
LOG_WARN("failed to get owner id", K(ret), K_(arg_.task_id));
} else if (OB_FAIL(ObDDLLock::unlock_for_add_drop_index(*new_data_table_schema_,
orig_index_table_schema_->get_table_id(),
orig_index_table_schema_->is_global_index_table(),
owner_id,
trans_))) {
LOG_WARN("failed to unlock ddl lock", KR(ret));
}
}
}
}
RS_TRACE(alter_schemas);
return ret;
}

View File

@ -0,0 +1,60 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OCEANBASE_ROOTSERVER_OB_UPDATE_INDEX_STATUS_HELPER_H_
#define OCEANBASE_ROOTSERVER_OB_UPDATE_INDEX_STATUS_HELPER_H_
#include "rootserver/parallel_ddl/ob_ddl_helper.h"
namespace oceanbase
{
namespace share
{
namespace schema
{
class ObMultiVersionSchemaService;
}
}
namespace obrpc
{
class ObUpdateIndexStatusArg;
}
namespace rootserver
{
class ObUpdateIndexStatusHelper : public ObDDLHelper
{
public:
ObUpdateIndexStatusHelper(
share::schema::ObMultiVersionSchemaService *schema_service,
const uint64_t tenant_id,
const obrpc::ObUpdateIndexStatusArg &arg,
obrpc::ObParallelDDLRes &res);
virtual ~ObUpdateIndexStatusHelper();
virtual int execute() override;
private:
int lock_objects_();
int check_and_set_schema_();
int calc_schema_version_cnt_();
int update_status_();
int lock_database_by_obj_name_();
private:
const obrpc::ObUpdateIndexStatusArg &arg_;
obrpc::ObParallelDDLRes &res_;
const ObTableSchema *orig_index_table_schema_;
ObTableSchema* new_data_table_schema_;
share::schema::ObIndexStatus new_status_;
bool index_table_exist_;
uint64_t database_id_;
};
}
}
#endif

View File

@ -67,6 +67,7 @@ public:
RPC_S(PRD recover_restore_table_ddl, obrpc::OB_RECOVER_RESTORE_TABLE_DDL, (ObRecoverRestoreTableDDLArg));
RPC_S(PRD parallel_create_table, obrpc::OB_PARALLEL_CREATE_TABLE, (ObCreateTableArg), ObCreateTableRes);
RPC_S(PRD alter_table, obrpc::OB_ALTER_TABLE, (ObAlterTableArg), ObAlterTableRes);
RPC_S(PRD set_comment, obrpc::OB_PARALLEL_SET_COMMENT, (ObSetCommentArg), ObParallelDDLRes);
RPC_S(PRD split_global_index_tablet, obrpc::OB_SPLIT_GLOBAL_INDEX_TABLET, (ObAlterTableArg));
RPC_S(PRD create_hidden_table, obrpc::OB_CREATE_HIDDEN_TABLE, (obrpc::ObCreateHiddenTableArg), ObCreateHiddenTableRes);
RPC_S(PRD alter_database, obrpc::OB_ALTER_DATABASE, (ObAlterDatabaseArg));
@ -79,6 +80,7 @@ public:
RPC_S(PRD truncate_table_v2, obrpc::OB_TRUNCATE_TABLE_V2, (ObTruncateTableArg), ObDDLRes);
RPC_S(PRD create_aux_index, obrpc::OB_CREATE_AUX_INDEX, (obrpc::ObCreateAuxIndexArg), obrpc::ObCreateAuxIndexRes);
RPC_S(PRD create_index, obrpc::OB_CREATE_INDEX, (ObCreateIndexArg), ObAlterTableRes);
RPC_S(PRD parallel_create_index, obrpc::OB_PARALLEL_CREATE_INDEX, (ObCreateIndexArg), ObAlterTableRes);
RPC_S(PRD drop_index, obrpc::OB_DROP_INDEX, (ObDropIndexArg), ObDropIndexRes);
RPC_S(PRD drop_index_on_failed, obrpc::OB_DROP_INDEX_ON_FAILED, (ObDropIndexArg), ObDropIndexRes);
RPC_S(PRD rebuild_vec_index, obrpc::OB_REBUILD_VEC_INDEX, (ObRebuildIndexArg), ObAlterTableRes);
@ -208,6 +210,7 @@ public:
RPC_S(PRD alter_resource_tenant, obrpc::OB_ALTER_RESOURCE_TENANT, (ObAlterResourceTenantArg));
RPC_S(PRD update_index_status, obrpc::OB_UPDATE_INDEX_TABLE_STATUS, (ObUpdateIndexStatusArg));
RPC_S(PRD update_mview_status, obrpc::OB_UPDATE_MVIEW_TABLE_STATUS, (ObUpdateMViewStatusArg));
RPC_S(PRD parallel_update_index_status, obrpc::OB_PARALLEL_UPDATE_INDEX_STATUS, (ObUpdateIndexStatusArg), ObParallelDDLRes);
// define system admin rpc (alter system ...)
RPC_S(PR5 root_minor_freeze, obrpc::OB_ROOT_MINOR_FREEZE, (ObRootMinorFreezeArg));

View File

@ -48,7 +48,8 @@ int ObDDLErrorMessageTableOperator::ObBuildDDLErrorMessage::prepare_user_message
bool ObDDLErrorMessageTableOperator::ObBuildDDLErrorMessage::operator==(const ObBuildDDLErrorMessage &other) const
{
bool equal = ret_code_ == other.ret_code_ && ddl_type_ == other.ddl_type_
&& 0 == STRNCMP(dba_message_, other.dba_message_, OB_MAX_ERROR_MSG_LEN);
&& consensus_schema_version_ == other.consensus_schema_version_
&& 0 == STRNCMP(dba_message_, other.dba_message_, OB_MAX_ERROR_MSG_LEN);
if (equal) {
if (nullptr == user_message_ && nullptr == other.user_message_) {
} else if (nullptr == user_message_ || nullptr == other.user_message_) {
@ -219,6 +220,7 @@ int ObDDLErrorMessageTableOperator::get_ddl_error_message(
int ret = OB_SUCCESS;
ObSqlString sql;
forward_user_msg_len = 0;
uint64_t tenant_data_version = 0;
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
sqlclient::ObMySQLResult *result = NULL;
@ -226,18 +228,24 @@ int ObDDLErrorMessageTableOperator::get_ddl_error_message(
if (OB_UNLIKELY(OB_INVALID_ID == tenant_id || task_id <= 0 || target_object_id < -1)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(tenant_id), K(task_id), K(target_object_id), K(addr));
} else if (!is_ddl_retry_task && OB_FAIL(sql.assign_fmt(
"SELECT ret_code, ddl_type, affected_rows, dba_message, user_message from %s "
"WHERE tenant_id = %ld AND task_id = %ld AND target_object_id = %ld "
, OB_ALL_DDL_ERROR_MESSAGE_TNAME,
ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id), task_id, target_object_id))) {
LOG_WARN("fail to assign sql", K(ret));
} else if (is_ddl_retry_task && OB_FAIL(sql.assign_fmt(
"SELECT ret_code, ddl_type, affected_rows, dba_message, UNHEX(user_message) as user_message from %s "
"WHERE tenant_id = %ld AND task_id = %ld AND target_object_id = %ld "
, OB_ALL_DDL_ERROR_MESSAGE_TNAME,
ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id), task_id, target_object_id))) {
LOG_WARN("fail to assign sql", K(ret));
} else if (OB_FAIL(sql.append("SELECT ret_code, ddl_type, affected_rows, dba_message "))) {
LOG_WARN("fail to append sql", KR(ret));
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
LOG_WARN("get tenant data version failed", KR(ret), K(tenant_id));
} else if (((tenant_data_version >= DATA_VERSION_4_2_2_0 && tenant_data_version < DATA_VERSION_4_3_0_0)
|| (tenant_data_version >= DATA_VERSION_4_3_5_0))
&& OB_FAIL(sql.append(" ,consensus_schema_version "))) {
LOG_WARN("fail to append sql", KR(ret));
} else if (!is_ddl_retry_task && OB_FAIL(sql.append(" ,user_message "))) {
LOG_WARN("fail to append sql", KR(ret));
} else if (is_ddl_retry_task && OB_FAIL(sql.append(" ,UNHEX(user_message) as user_message "))) {
LOG_WARN("fail to append sql", KR(ret));
} else if (OB_FAIL(sql.append_fmt(" from %s "
" WHERE tenant_id = %ld AND task_id = %ld AND target_object_id = %ld ",
OB_ALL_DDL_ERROR_MESSAGE_TNAME,
ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id),
task_id, target_object_id))) {
LOG_WARN("fail to append sql", KR(ret));
} else if (addr.is_valid()) {
if (!addr.ip_to_string(ip, sizeof(ip))) {
ret = OB_INVALID_ARGUMENT;
@ -273,6 +281,9 @@ int ObDDLErrorMessageTableOperator::get_ddl_error_message(
EXTRACT_INT_FIELD_MYSQL(*result, "ret_code", error_message.ret_code_, int);
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "dba_message", str_dba_message);
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "user_message", str_user_message);
EXTRACT_INT_FIELD_MYSQL_WITH_DEFAULT_VALUE(*result, "consensus_schema_version",
error_message.consensus_schema_version_, int64_t, false /*skip null error*/,
true /*skip column error*/, OB_INVALID_VERSION);
forward_user_msg_len = str_user_message.length();
const int64_t buf_size = str_user_message.length() + 1;
if (OB_FAIL(ret)) {
@ -337,6 +348,9 @@ int ObDDLErrorMessageTableOperator::get_ddl_error_message(
EXTRACT_INT_FIELD_MYSQL(*result, "ret_code", error_message.ret_code_, int);
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "dba_message", str_dba_message);
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "user_message", str_user_message);
EXTRACT_INT_FIELD_MYSQL_WITH_DEFAULT_VALUE(*result, "consensus_schema_version",
error_message.consensus_schema_version_, int64_t, false /*skip null error*/,
true /*skip column error*/, OB_INVALID_VERSION);
forward_user_msg_len = str_user_message.length();
const int64_t buf_size = str_user_message.length() + 1;
if (OB_FAIL(ret)) {
@ -413,6 +427,12 @@ int ObDDLErrorMessageTableOperator::report_ddl_error_message(const ObBuildDDLErr
LOG_WARN("convert ip to string failed", K(ret), K(addr));
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
LOG_WARN("get tenant data version failed", K(ret));
} else if (OB_UNLIKELY((tenant_data_version < DATA_VERSION_4_2_2_0
|| (tenant_data_version >= DATA_VERSION_4_3_0_0 && tenant_data_version < DATA_VERSION_4_3_5_0))
&& OB_INVALID_VERSION != error_message.consensus_schema_version_)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("consensus schema version should be invalid before 4220", KR(ret), K(tenant_data_version),
K_(error_message.consensus_schema_version));
} else {
ObDMLSqlSplicer dml_splicer;
if (OB_FAIL(dml_splicer.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id)))) {
@ -444,6 +464,11 @@ int ObDDLErrorMessageTableOperator::report_ddl_error_message(const ObBuildDDLErr
LOG_WARN("failed to add column trace_id", KR(ret), K(trace_id));
} else if (OB_FAIL(dml_splicer.add_column(K(parent_task_id)))) {
LOG_WARN("failed to add column parent_task_id", KR(ret), K(parent_task_id));
} else if (((tenant_data_version >= DATA_VERSION_4_2_2_0 && tenant_data_version < DATA_VERSION_4_3_0_0)
|| (tenant_data_version >= DATA_VERSION_4_3_5_0))
&& 0 < error_message.consensus_schema_version_ // prevent of reset to invalid after been valid
&& OB_FAIL(dml_splicer.add_column("consensus_schema_version", error_message.consensus_schema_version_))) {
LOG_WARN("fail to add column consensus_schema_version", KR(ret), K_(error_message.consensus_schema_version));
}
}
if (OB_SUCC(ret)) {

View File

@ -35,13 +35,13 @@ public:
public:
ObBuildDDLErrorMessage()
: ret_code_(common::OB_NOT_INIT), ddl_type_(ObDDLType::DDL_INVALID), affected_rows_(0),
user_message_(nullptr), dba_message_("\0"), allocator_()
user_message_(nullptr), dba_message_("\0"), allocator_(), consensus_schema_version_(OB_INVALID_VERSION)
{}
virtual ~ObBuildDDLErrorMessage();
int prepare_user_message_buf(const int64_t len);
bool operator==(const ObBuildDDLErrorMessage &other) const;
bool operator!=(const ObBuildDDLErrorMessage &other) const;
TO_STRING_KV(K_(ret_code), K_(ddl_type), K_(affected_rows), K_(user_message), K_(dba_message));
TO_STRING_KV(K_(ret_code), K_(ddl_type), K_(affected_rows), K_(user_message), K_(dba_message), K_(consensus_schema_version));
public:
int ret_code_;
ObDDLType ddl_type_;
@ -49,6 +49,7 @@ public:
char *user_message_;
char dba_message_[common::OB_MAX_ERROR_MSG_LEN];
common::ObArenaAllocator allocator_;
int64_t consensus_schema_version_;
};
//for add_column in ddl_error_message

View File

@ -640,6 +640,8 @@ class ObString;
ACT(BEFORE_SEND_ALTER_TABLE,)\
ACT(BEFOR_EXEC_REBUILD_TASK,)\
ACT(BEFORE_CREATE_HIDDEN_TABLE_IN_LOAD,)\
ACT(BEFORE_PARALLEL_DDL_LOCK,)\
ACT(AFTER_PARALLEL_DDL_LOCK,)\
ACT(BEFORE_START_TRANSFER_IN_ON_PREPARE,)\
ACT(BEFORE_TRANSFER_SERVICE_RUNNING,)\
ACT(BEFORE_RESTORE_CREATE_TABLETS_SSTABLE,)\

View File

@ -2217,6 +2217,55 @@ OB_SERIALIZE_MEMBER((ObCreateTableLikeArg, ObDDLArg),
session_id_,
define_user_id_);
int ObSetCommentArg::assign(const ObSetCommentArg &other)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObDDLArg::assign(other))) {
LOG_WARN("fail to assign ObDDLArg", KR(ret));
} else if (OB_FAIL(column_name_list_.assign(other.column_name_list_))) {
LOG_WARN("fail to assign column name list", KR(ret), K(other));
} else if (OB_FAIL(column_comment_list_.assign(other.column_comment_list_))) {
LOG_WARN("fail to assign column comment list", KR(ret), K(other));
} else {
session_id_ = other.session_id_;
database_name_ = other.database_name_;
table_name_ = other.table_name_;
table_comment_ = other.table_comment_;
op_type_ = other.op_type_;
}
return ret;
}
void ObSetCommentArg::reset()
{
session_id_ = OB_INVALID_ID;
database_name_.reset();
table_name_.reset();
table_comment_.reset();
column_name_list_.reset();
column_comment_list_.reset();
op_type_ = MIN_OP_TYPE;
ObDDLArg::reset();
}
bool ObSetCommentArg::is_valid() const
{
return OB_INVALID_ID != exec_tenant_id_
&& !database_name_.empty()
&& !table_name_.empty()
&& op_type_ > MIN_OP_TYPE
&& op_type_ < MAX_OP_TYPE;
}
OB_SERIALIZE_MEMBER((ObSetCommentArg, ObDDLArg),
session_id_,
database_name_,
table_name_,
column_name_list_,
column_comment_list_,
table_comment_,
op_type_);
bool ObAlterTableArg::is_valid() const
{
// TODO(shaohang.lsh): add more check if needed
@ -7898,6 +7947,12 @@ int ObDDLRes::assign(const ObDDLRes &other)
OB_SERIALIZE_MEMBER(ObDDLRes, tenant_id_, schema_id_, task_id_);
void ObParallelDDLRes::reset()
{
schema_version_ = OB_INVALID_VERSION;
}
OB_SERIALIZE_MEMBER(ObParallelDDLRes, schema_version_);
void ObAlterTableRes::reset()
{
index_table_id_ = OB_INVALID_ID;

View File

@ -2199,6 +2199,51 @@ public:
int64_t start_time_;
bool is_mview_complete_refresh_;
};
struct ObSetCommentArg : public ObDDLArg
{
OB_UNIS_VERSION(1);
public:
enum OP_TYPE {
MIN_OP_TYPE = 1,
COMMENT_TABLE,
COMMENT_COLUMN,
MAX_OP_TYPE = 1000
};
ObSetCommentArg():
ObDDLArg(),
session_id_(common::OB_INVALID_ID),
database_name_(),
table_name_(),
table_comment_(),
column_name_list_(),
column_comment_list_(),
op_type_(MIN_OP_TYPE)
{
}
virtual ~ObSetCommentArg() {
}
void reset();
bool is_valid() const;
int assign(const ObSetCommentArg &other);
TO_STRING_KV(K(ObDDLArg()),
K_(session_id),
K_(database_name),
K_(table_name),
K_(column_name_list),
K_(column_comment_list),
K_(table_comment),
K_(op_type));
public:
uint64_t session_id_;
common::ObString database_name_;
common::ObString table_name_;
common::ObString table_comment_;
common::ObSArray<common::ObString> column_name_list_;
common::ObSArray<common::ObString> column_comment_list_;
OP_TYPE op_type_;
private:
DISALLOW_COPY_AND_ASSIGN(ObSetCommentArg);
};
struct ObAlterTableArg : public ObDDLArg
{
@ -9556,6 +9601,24 @@ public:
int64_t task_id_;
};
struct ObParallelDDLRes
{
OB_UNIS_VERSION(1);
public:
ObParallelDDLRes():
schema_version_(common::OB_INVALID_VERSION)
{}
void reset();
int assign(const ObParallelDDLRes &other) {
int ret = common::OB_SUCCESS;
schema_version_ = other.schema_version_;
return ret;
}
public:
TO_STRING_KV(K_(schema_version));
int64_t schema_version_;
};
struct ObAlterTableRes
{
OB_UNIS_VERSION(1);

View File

@ -804,3 +804,46 @@ int ObLatestSchemaGuard::get_udt_info(
}
return ret;
}
int ObLatestSchemaGuard::get_coded_index_name_info_mysql(
common::ObIAllocator &allocator,
const uint64_t database_id,
const uint64_t data_table_id,
const ObString &index_name,
const bool is_built_in,
ObIndexSchemaInfo &index_info)
{
int ret = OB_SUCCESS;
ObMySQLProxy *sql_proxy = nullptr;
ObSchemaService *schema_service_impl = nullptr;
bool is_oracle_mode = false;
ObArray<ObIndexSchemaInfo> index_infos;
if (OB_FAIL(check_inner_stat_())) {
LOG_WARN("fail to check inner stat", KR(ret));
} else if (OB_UNLIKELY(OB_INVALID_ID == database_id
|| OB_INVALID_ID == data_table_id
|| index_name.empty())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("should use in mysql mode", KR(ret), K_(tenant_id));
} else if (OB_FAIL(check_and_get_service_(schema_service_impl, sql_proxy))) {
LOG_WARN("fail to check and get service", KR(ret));
} else if (OB_FAIL(schema_service_impl->get_table_index_infos(allocator, *sql_proxy, tenant_id_, database_id,
data_table_id, index_infos))) {
LOG_WARN("fail to get table index name in mysql", KR(ret), K_(tenant_id), K(data_table_id), K(data_table_id));
}
for (uint64_t i = 0; OB_SUCC(ret) && i < index_infos.count(); ++i)
{
if (schema_service_impl->schema_name_is_equal(index_name,
index_infos.at(i).get_index_name(),
true/*case_compare*/,
true/*collation*/)) {
if (is_built_in == schema::is_built_in_index(index_infos.at(i).get_index_type())) {
if (OB_FAIL(index_info.assign(index_infos.at(i)))) {
LOG_WARN("fail to assign index info", KR(ret));
}
break;
}
}
}
return ret;
}

View File

@ -289,6 +289,17 @@ public:
const ObRoutineType &routine_type,
const bool is_or_replace);
// get index info by index name, database_id, data_table_id in mysql mode
// index name should be encoded and will be compared with CS_TYPE_UTF8MB4_GENERAL_CI (case insensitive)
// @param [out] index_info: invalid means index not exist
int get_coded_index_name_info_mysql(
common::ObIAllocator &allocator,
const uint64_t database_id,
const uint64_t data_table_id,
const ObString &index_name,
const bool is_built_in,
ObIndexSchemaInfo &index_info);
/* -------------- interfaces without cache end ---------------*/
/* -------------- interfaces with cache ---------------*/

View File

@ -373,6 +373,7 @@ int ObMultiVersionSchemaService::get_latest_schema(
ObTableSchema *new_table = static_cast<ObTableSchema *>(new_schema);
if (MATERIALIZED_VIEW == new_table->get_table_type()) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter materialized view is");
LOG_WARN("not support to fetch latest mv", KR(ret), "table_id", schema_id);
} else if (OB_ALL_CORE_TABLE_TID == schema_id) {
// do-nothing

View File

@ -1327,6 +1327,18 @@ public:
const common::ObIArray<uint64_t> &table_ids,
common::ObIArray<ObSchemaIdVersion> &versions) = 0;
virtual int get_table_index_infos(
common::ObIAllocator &allocator,
common::ObISQLClient &sql_client,
const uint64_t tenant_id,
const uint64_t database_id,
const uint64_t data_table_id,
common::ObIArray<ObIndexSchemaInfo> &index_infos) = 0;
virtual bool schema_name_is_equal(
const ObString &src,
const ObString &dst,
const bool case_compare,
const bool compare_with_collation) = 0;
/*----------- interfaces for latest schema end -------------*/
};

View File

@ -10041,7 +10041,7 @@ int ObSchemaServiceSQLImpl::retrieve_schema_id_with_name_(
EXTRACT_INT_FIELD_MYSQL(*result, id_col_name, tmp_schema_id, uint64_t);
EXTRACT_VARCHAR_FIELD_MYSQL(*result, name_col_name, tmp_schema_name);
if (OB_FAIL(ret)) {
} else if (schema_name_is_equal_(
} else if (schema_name_is_equal(
schema_name, tmp_schema_name,
case_compare, compare_with_collation)) {
schema_id = tmp_schema_id;
@ -10054,7 +10054,7 @@ int ObSchemaServiceSQLImpl::retrieve_schema_id_with_name_(
return ret;
}
bool ObSchemaServiceSQLImpl::schema_name_is_equal_(
bool ObSchemaServiceSQLImpl::schema_name_is_equal(
const ObString &src,
const ObString &dst,
const bool case_compare,
@ -10301,7 +10301,7 @@ int ObSchemaServiceSQLImpl::get_table_id(
// try fetch inner table id
if (is_system_table && OB_INVALID_ID == candidate_inner_table_id) { // case 3.3
bool tmp_case_compare = is_mysql_sys_database_id(database_id) ? true : case_compare;
if (schema_name_is_equal_(
if (schema_name_is_equal(
table_name, tmp_table_name,
case_compare, compare_with_collation)
&& 0 == tmp_session_id) {
@ -10311,7 +10311,7 @@ int ObSchemaServiceSQLImpl::get_table_id(
}
}
if (schema_name_is_equal_(
if (schema_name_is_equal(
table_name, tmp_table_name,
case_compare, compare_with_collation)) {
table_id = tmp_table_id;
@ -10355,6 +10355,9 @@ int ObSchemaServiceSQLImpl::get_index_id(
bool case_compare = false;
const bool compare_with_collation = true;
index_id = OB_INVALID_ID;
#define GET_INDEX_ID_SQL "SELECT table_id, table_name FROM %s " \
"WHERE tenant_id = %lu AND database_id = %lu AND table_name = '%s' " \
"AND table_type = %d "
if (OB_UNLIKELY(!check_inner_stat())) {
ret = OB_NOT_INIT;
LOG_WARN("check inner stat fail", KR(ret));
@ -10371,18 +10374,32 @@ int ObSchemaServiceSQLImpl::get_index_id(
LOG_WARN("fail to check oracle mode", KR(ret), K(tenant_id));
} else if (FALSE_IT(case_compare = (!is_oracle_mode
|| is_mysql_sys_database_id(database_id)))) {
} else if (OB_FAIL(sql.assign_fmt(
"SELECT table_id, table_name FROM %s "
"WHERE tenant_id = 0 AND database_id = %lu AND table_name = '%s' "
"AND table_type = %d ",
OB_ALL_TABLE_TNAME, database_id, idx_name, USER_INDEX))) {
LOG_WARN("fail to assign fmt", KR(ret), K(tenant_id), K(database_id),
K(index_name), "idx_name", idx_name);
} else if (OB_FAIL(retrieve_schema_id_with_name_(
sql_client, tenant_id, sql,
"table_id", "table_name",
index_name, case_compare,
compare_with_collation, index_id))) {
} else if (is_oceanbase_sys_database_id(database_id)) {
if (OB_FAIL(sql.assign_fmt(
"SELECT * FROM "
"( "
GET_INDEX_ID_SQL
"UNION ALL "
GET_INDEX_ID_SQL
") ",
OB_ALL_VIRTUAL_CORE_ALL_TABLE_TNAME, tenant_id, database_id, idx_name, USER_INDEX,
OB_ALL_TABLE_TNAME, OB_INVALID_TENANT_ID, database_id, idx_name, USER_INDEX))) {
LOG_WARN("fail to assign fmt", KR(ret), K(tenant_id), K(database_id),
K(index_name), "idx_name", idx_name);
}
} else {
if (OB_FAIL(sql.assign_fmt(
GET_INDEX_ID_SQL,
OB_ALL_TABLE_TNAME, OB_INVALID_TENANT_ID, database_id, idx_name, USER_INDEX))) {
LOG_WARN("fail to assign fmt", KR(ret), K(tenant_id), K(database_id),
K(index_name), "idx_name", idx_name);
}
}
if (FAILEDx(retrieve_schema_id_with_name_(
sql_client, tenant_id, sql,
"table_id", "table_name",
index_name, case_compare,
compare_with_collation, index_id))) {
LOG_WARN("fail to retrieve schema id with name",
KR(ret), K(tenant_id), K(database_id),
K(index_name), "idx_name", idx_name);
@ -10566,7 +10583,7 @@ int ObSchemaServiceSQLImpl::get_constraint_id(
// skip
// (TODO):for mysql tmp table, it may has risk that constraint name duplicated in one table?
// here just make the logic same with int ObSchemaMgr::add_constraints_in_table().
} else if (schema_name_is_equal_(
} else if (schema_name_is_equal(
constraint_name, tmp_constraint_name,
case_compare, compare_with_collation)) {
constraint_id = tmp_constraint_id;
@ -10655,7 +10672,7 @@ int ObSchemaServiceSQLImpl::get_foreign_key_id(
|| is_index_table(tmp_table_type)
|| is_aux_lob_table(tmp_table_type)) {
// skip
} else if (schema_name_is_equal_(
} else if (schema_name_is_equal(
foreign_key_name, tmp_foreign_key_name,
case_compare, compare_with_collation)) {
foreign_key_id = tmp_foreign_key_id;
@ -10732,7 +10749,7 @@ int ObSchemaServiceSQLImpl::get_sequence_id(
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "sequence_name", tmp_sequence_name);
EXTRACT_BOOL_FIELD_MYSQL(*result, "is_system_generated", tmp_is_system_generated);
if (OB_FAIL(ret)) {
} else if (schema_name_is_equal_(
} else if (schema_name_is_equal(
sequence_name, tmp_sequence_name,
case_compare, compare_with_collation)) {
sequence_id = tmp_sequence_id;
@ -10879,7 +10896,7 @@ int ObSchemaServiceSQLImpl::get_routine_id(
EXTRACT_INT_FIELD_MYSQL(*result, "routine_type", tmp_routine_type, ObRoutineType);
if (OB_FAIL(ret)) {
} else if (schema_name_is_equal_(
} else if (schema_name_is_equal(
routine_name, tmp_routine_name,
case_compare, compare_with_collation)) {
if (OB_FAIL(routine_pairs.push_back(
@ -11164,6 +11181,91 @@ int ObSchemaServiceSQLImpl::get_audits_in_owner(
return ret;
}
int ObSchemaServiceSQLImpl::get_table_index_infos(
common::ObIAllocator &allocator,
common::ObISQLClient &sql_client,
const uint64_t tenant_id,
const uint64_t database_id,
const uint64_t data_table_id,
common::ObIArray<ObIndexSchemaInfo> &index_infos)
{
int ret = OB_SUCCESS;
ObSqlString sql;
index_infos.reset();
#define GET_INDEX_INFO_SQL "SELECT table_name, table_id, schema_version, index_type FROM %s " \
"WHERE tenant_id = %lu AND database_id = %lu AND data_table_id = %lu " \
"AND table_type = %d "
if (OB_UNLIKELY(!check_inner_stat())) {
ret = OB_NOT_INIT;
LOG_WARN("check inner stat fail", KR(ret));
} else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
|| OB_INVALID_ID == database_id
|| OB_INVALID_ID == data_table_id)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", KR(ret), KR(ret), K(tenant_id), K(database_id), K(data_table_id));
} else if (is_oceanbase_sys_database_id(database_id)) {
if (OB_FAIL(sql.assign_fmt(
"SELECT * FROM "
"( "
GET_INDEX_INFO_SQL
"UNION ALL "
GET_INDEX_INFO_SQL
") ",
OB_ALL_VIRTUAL_CORE_ALL_TABLE_TNAME, tenant_id, database_id, data_table_id, USER_INDEX,
OB_ALL_TABLE_TNAME, OB_INVALID_TENANT_ID, database_id, data_table_id, USER_INDEX))) {
LOG_WARN("fail to assign fmt", KR(ret), K(tenant_id), K(database_id), K(data_table_id));
}
} else {
if (OB_FAIL(sql.assign_fmt(
GET_INDEX_INFO_SQL,
OB_ALL_TABLE_TNAME, OB_INVALID_TENANT_ID, database_id, data_table_id, USER_INDEX))) {
LOG_WARN("fail to assign fmt", KR(ret), K(tenant_id), K(database_id), K(data_table_id));
}
}
if (OB_SUCC(ret)) {
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
ObMySQLResult *result = nullptr;
if (OB_FAIL(sql_client.read(res, tenant_id, sql.ptr()))) {
LOG_WARN("fail to read", KR(ret), K(tenant_id), K(sql));
} else if (OB_ISNULL(result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("result is null", KR(ret), K(tenant_id));
}
ObString tmp_schema_name;
uint64_t tmp_index_id = OB_INVALID_ID;
int64_t tmp_schema_version = OB_INVALID_VERSION;
ObIndexType tmp_index_type = INDEX_TYPE_IS_NOT;
while (OB_SUCC(ret)) {
if (OB_FAIL(result->next())) {
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
break;
} else {
LOG_WARN("fail to get next", KR(ret));
}
} else {
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "table_name", tmp_schema_name);
EXTRACT_INT_FIELD_MYSQL(*result, "table_id", tmp_index_id, uint64_t);
EXTRACT_INT_FIELD_MYSQL(*result, "schema_version", tmp_schema_version, int64_t);
EXTRACT_INT_FIELD_MYSQL(*result, "index_type", tmp_index_type, ObIndexType);
ObIndexSchemaInfo tmp_index_info;
ObString tmp_index_name;
if (FAILEDx(ob_write_string(allocator, tmp_schema_name, tmp_index_name, true/*c_style*/))) {
LOG_WARN("fail to write string", KR(ret));
} else if (OB_FAIL(tmp_index_info.init(tmp_index_name, tmp_index_id, tmp_schema_version, tmp_index_type))) {
LOG_WARN("fail to init tmp index info", KR(ret), K(tmp_schema_name), K(tmp_index_id), K(tmp_schema_version));
} else if (OB_FAIL(index_infos.push_back(tmp_index_info))) {
LOG_WARN("fail to push back tmp index info", KR(ret), K(tenant_id), K(tmp_schema_name));
}
}
}// end while
}// end smart_var
}
LOG_TRACE("get table index name", KR(ret), K(tenant_id), K(database_id), K(data_table_id));
return ret;
}
}//namespace schema
}//namespace share
}//namespace oceanbase

View File

@ -822,6 +822,19 @@ public:
const uint64_t owner_id,
common::ObIArray<ObSAuditSchema> &audit_schemas) override;
virtual int get_table_index_infos(
common::ObIAllocator &allocator,
common::ObISQLClient &sql_client,
const uint64_t tenant_id,
const uint64_t database_id,
const uint64_t data_table_id,
common::ObIArray<ObIndexSchemaInfo> &index_infos) override;
virtual bool schema_name_is_equal(
const ObString &src,
const ObString &dst,
const bool case_compare,
const bool compare_with_collation) override;
/*----------- interfaces for latest schema end -------------*/
private:
@ -1238,11 +1251,6 @@ private:
const bool compare_with_collation,
uint64_t &schema_id);
bool schema_name_is_equal_(
const ObString &src,
const ObString &dst,
const bool case_compare,
const bool compare_with_collation);
int fetch_table_latest_schema_versions_(
common::ObISQLClient &sql_client,

View File

@ -85,6 +85,49 @@ lib::Worker::CompatMode get_worker_compat_mode(const ObCompatibilityMode &mode)
return worker_mode;
}
int ObIndexSchemaInfo::init(
const ObString &index_name,
const uint64_t index_id,
const int64_t schema_version,
const ObIndexType index_type)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(index_name.empty()
|| OB_INVALID_ID == index_id
|| schema_version <= 0
|| index_type <= INDEX_TYPE_IS_NOT)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("index_name, index_id, schema_version invalid", KR(ret), K(index_name),
K(index_id), K(schema_version), K(index_type));
} else {
index_name_ = index_name;
index_id_ = index_id;
schema_version_ = schema_version;
index_type_ = index_type;
}
return ret;
}
void ObIndexSchemaInfo::reset()
{
index_name_.reset();
index_id_ = OB_INVALID_ID;
schema_version_ = OB_INVALID_VERSION;
index_type_ = INDEX_TYPE_IS_NOT;
}
bool ObIndexSchemaInfo::is_valid() const
{
return !index_name_.empty() && OB_INVALID_ID != index_id_ && schema_version_ > 0 && index_type_ != INDEX_TYPE_IS_NOT;
}
int ObIndexSchemaInfo::assign(const ObIndexSchemaInfo &other)
{
int ret = OB_SUCCESS;
index_name_ = other.get_index_name();
index_id_ = other.get_index_id();
schema_version_ = other.get_schema_version();
index_type_ = other.get_index_type();
return ret;
}
int ObSchemaIdVersion::init(
const uint64_t schema_id,
const int64_t schema_version)

View File

@ -494,6 +494,28 @@ public:
};
class ObIndexSchemaInfo
{
public:
ObIndexSchemaInfo()
: index_name_(), index_id_(common::OB_INVALID_ID), schema_version_(common::OB_INVALID_VERSION), index_type_(INDEX_TYPE_IS_NOT) {}
~ObIndexSchemaInfo() {}
int init(const ObString &index_name, const uint64_t index_id, const int64_t schema_version, const ObIndexType index_type);
void reset();
bool is_valid() const;
int assign(const ObIndexSchemaInfo &other);
const ObString &get_index_name() const { return index_name_; }
uint64_t get_index_id() const { return index_id_; }
int64_t get_schema_version() const {return schema_version_; }
ObIndexType get_index_type() const {return index_type_;}
TO_STRING_KV(K_(index_name), K_(index_id), K_(schema_version), K_(index_type));
private:
ObString index_name_;
uint64_t index_id_;
int64_t schema_version_;
ObIndexType index_type_;
};
class ObSchemaIdVersion
{
public:
@ -775,6 +797,8 @@ inline bool is_vec_index(const ObIndexType index_type)
return is_vec_delta_buffer_type(index_type) || is_built_in_vec_index(index_type);
}
// new built in index type should add case in built_in_index_not_visible.test
inline bool is_built_in_index(const ObIndexType index_type)
{
return is_built_in_vec_index(index_type) ||

View File

@ -1336,8 +1336,6 @@ const char* DDLType[]
const char* NOT_SUPPORT_DDLType[]
{
"SET_COMMENT",
"CREATE_INDEX",
"CREATE_VIEW",
"DROP_TABLE"
};

View File

@ -2130,33 +2130,8 @@ int ObTableSqlService::update_table_options(ObISQLClient &sql_client,
bool is_oracle_mode = false;
const uint64_t tenant_id = table_schema.get_tenant_id();
uint64_t table_id = table_schema.get_table_id();
ObDMLSqlSplicer dml;
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
const bool update_object_status_ignore_version = false;
if (OB_FAIL(check_ddl_allowed(new_table_schema))) {
LOG_WARN("check ddl allowd failed", K(ret), K(new_table_schema));
} else if (OB_FAIL(gen_table_options_dml(exec_tenant_id, new_table_schema, update_object_status_ignore_version, dml))) {
LOG_WARN("gen table options dml failed", K(ret));
} else {
int64_t affected_rows = 0;
const char *table_name = NULL;
if (OB_FAIL(ObSchemaUtils::get_all_table_name(exec_tenant_id, table_name))) {
LOG_WARN("fail to get all table name", K(ret), K(exec_tenant_id));
} else if (OB_FAIL(exec_update(sql_client, tenant_id, table_id,
table_name, dml, affected_rows))) {
LOG_WARN("exec update failed", K(ret));
} else if (affected_rows > 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected value", K(ret), K(affected_rows));
}
}
// add to __all_table_history table
if (OB_SUCC(ret)) {
const bool only_history = true;
if (OB_FAIL(add_table(sql_client, new_table_schema, update_object_status_ignore_version, only_history))) {
LOG_WARN("add_table failed", K(new_table_schema), K(only_history), K(ret));
}
if (OB_FAIL(inner_update_table_options_(sql_client, new_table_schema))) {
LOG_WARN("fail to do inner update table option", KR(ret), KPC(ddl_stmt_str));
}
if (OB_SUCC(ret)) {
@ -5491,7 +5466,7 @@ int ObTableSqlService::check_table_options(const ObTableSchema &table)
return ret;
}
// for now, this interface is just used for parallel_set_comment
// this interface have been used by parallel set comment
// since parallel ddl have to allocate schema version previously
// any modification of this interface should think the times of generate schema version carefully
int ObTableSqlService::only_update_table_options(ObISQLClient &sql_client,

View File

@ -90,6 +90,27 @@ int ObDDLExecutorUtil::wait_ddl_finish(
} else {
FORWARD_USER_ERROR(ret, error_message.user_message_);
}
} else if (error_message.consensus_schema_version_ != OB_INVALID_VERSION) {
ObTimeoutCtx ctx;
int64_t consensus_timeout = 30 * 1000 * 1000L; // 30s;
omt::ObTenantConfigGuard tenant_config(OTC_MGR.get_tenant_config_with_lock(tenant_id));
if (tenant_config.is_valid()) {
consensus_timeout = tenant_config->_wait_interval_after_parallel_ddl;
}
if (THIS_WORKER.is_timeout_ts_valid()) {
consensus_timeout = min(consensus_timeout, THIS_WORKER.get_timeout_remain());
}
int64_t start_time = ObTimeUtility::current_time();
if (OB_FAIL(ctx.set_timeout(consensus_timeout))) {
LOG_WARN("fail to set timeout ctx", KR(ret));
} else if (OB_FAIL(ObSchemaUtils::try_check_parallel_ddl_schema_in_sync(
ctx, session, tenant_id, error_message.consensus_schema_version_, false /*skip_consensus*/))) {
LOG_WARN("fail to check parallel ddl schema in sync", KR(ret), K_(error_message.consensus_schema_version));
} else {
int64_t refresh_time = ObTimeUtility::current_time() - start_time;
LOG_INFO("parallel ddl wait schema", KR(ret), K(tenant_id), K(refresh_time),
K_(error_message.consensus_schema_version));
}
}
break;
} else {

View File

@ -57,6 +57,12 @@ int ObCreateIndexExecutor::execute(ObExecContext &ctx, ObCreateIndexStmt &stmt)
obrpc::ObAlterTableRes res;
ObString first_stmt;
bool is_sync_ddl_user = false;
uint64_t tenant_id = create_index_arg.exec_tenant_id_;
uint64_t data_version = 0;
int64_t start_time = 0;
int64_t refresh_time = 0;
int64_t ddl_task_time = 0;
int64_t end_time = 0;
ObSArray<ObIndexArg *> index_arg_list;
ObPartitionPreSplit pre_split;
ObArenaAllocator allocator("CreateIndexExec");
@ -83,23 +89,59 @@ int ObCreateIndexExecutor::execute(ObExecContext &ctx, ObCreateIndexStmt &stmt)
} else if (OB_INVALID_ID == create_index_arg.session_id_
&& FALSE_IT(create_index_arg.session_id_ = my_session->get_sessid_for_table())) {
//impossible
} else if (FALSE_IT(create_index_arg.is_inner_ = my_session->is_inner())) {
} else if (FALSE_IT(create_index_arg.parallelism_ = stmt.get_parallelism())) {
} else if (FALSE_IT(create_index_arg.consumer_group_id_ = THIS_WORKER.get_group_id())) {
} else if (OB_FAIL(index_arg_list.push_back(&create_index_arg))) {
LOG_WARN("fail to push back create index arg", K(ret));
} else if (OB_FAIL(pre_split.get_global_index_pre_split_schema_if_need(
create_index_arg.tenant_id_, create_index_arg.session_id_, create_index_arg.database_name_, create_index_arg.table_name_, index_arg_list))) {
LOG_WARN("fail to get global index pre split schema if need", K(ret));
//overwrite ret code
ret = OB_SUCCESS;
} else {
create_index_arg.is_inner_ = my_session->is_inner();
create_index_arg.parallelism_ = stmt.get_parallelism();
create_index_arg.consumer_group_id_ = THIS_WORKER.get_group_id();
if (OB_FAIL(index_arg_list.push_back(&create_index_arg))) {
LOG_WARN("fail to push back create index arg", KR(ret));
} else if (OB_FAIL(pre_split.get_global_index_pre_split_schema_if_need(
create_index_arg.tenant_id_, create_index_arg.session_id_, create_index_arg.database_name_,
create_index_arg.table_name_, index_arg_list))) {
LOG_WARN("fail to get global index pre split schema if need", K(ret));
//overwrite ret code
ret = OB_SUCCESS;
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(common_rpc_proxy->create_index(create_index_arg, res))) { //send the signal of creating index to rs
LOG_WARN("rpc proxy create index failed", K(create_index_arg),
"dst", common_rpc_proxy->get_server(), K(ret));
} else if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(my_session, is_sync_ddl_user))) {
if (FAILEDx(GET_MIN_DATA_VERSION(tenant_id, data_version))) {
LOG_WARN("fail to get data version", KR(ret), K(tenant_id));
} else {
bool is_parallel_ddl = true;
if (OB_FAIL(ObParallelDDLControlMode::is_parallel_ddl_enable(
ObParallelDDLControlMode::CREATE_INDEX,
tenant_id, is_parallel_ddl))) {
LOG_WARN("fail to get whether create index is parallel", KR(ret), K(tenant_id));
} else if (!is_parallel_ddl
|| data_version < DATA_VERSION_4_2_2_0
|| (data_version >= DATA_VERSION_4_3_0_0 && data_version < DATA_VERSION_4_3_5_0)
|| share::schema::is_fts_or_multivalue_index(create_index_arg.index_type_)
|| share::schema::is_vec_index(create_index_arg.index_type_)) {
start_time = ObTimeUtility::current_time();
if (OB_FAIL(common_rpc_proxy->create_index(create_index_arg, res))) { //send the signal of creating index to rs
LOG_WARN("rpc proxy create index failed", K(create_index_arg),
"dst", common_rpc_proxy->get_server(), K(ret));
}
refresh_time = ObTimeUtility::current_time();
ddl_task_time = refresh_time;
} else {
ObTimeoutCtx ctx;
start_time = ObTimeUtility::current_time();
const int64_t rpc_timeout = (static_cast<obrpc::ObRpcProxy*>(common_rpc_proxy))->timeout();
if (OB_FAIL(ctx.set_timeout(rpc_timeout))) {
LOG_WARN("fail to set timeout ctx", KR(ret));
} else if (OB_FAIL(common_rpc_proxy->parallel_create_index(create_index_arg, res))) {
LOG_WARN("fail to parallel create index", KR(ret), "dst", common_rpc_proxy->get_server());
} else {
refresh_time = ObTimeUtility::current_time();
if (OB_FAIL(ObSchemaUtils::try_check_parallel_ddl_schema_in_sync(
ctx, my_session, tenant_id, res.schema_version_, false /*skip_consensus*/))) {
LOG_WARN("fail to check parallel ddl schema in sync", KR(ret), K(res));
}
ddl_task_time = ObTimeUtility::current_time();
}
}
}
if (FAILEDx(ObResolverUtils::check_sync_ddl_user(my_session, is_sync_ddl_user))) {
LOG_WARN("Failed to check sync_dll_user", K(ret));
} else if (!is_sys_index && !is_sync_ddl_user) {
// 只考虑非系统表和非备份恢复时的索引同步检查
@ -124,6 +166,14 @@ int ObCreateIndexExecutor::execute(ObExecContext &ctx, ObCreateIndexStmt &stmt)
"table_id", res.index_table_id_,
"schema_version", res.schema_version_);
SQL_ENG_LOG(INFO, "finish create index execute.", K(ret), "ddl_event_info", ObDDLEventInfo());
end_time = ObTimeUtility::current_time();
LOG_INFO("[create_index]", KR(ret),
"tenant_id", tenant_id,
"cost", end_time - start_time,
"execute_time", refresh_time - start_time,
"wait_schema", ddl_task_time - refresh_time,
"wait_ddl_task", end_time - ddl_task_time,
"index_name", create_index_arg.index_name_);
return ret;
}

View File

@ -1988,6 +1988,104 @@ int ObAlterTableExecutor::set_index_arg_list(ObExecContext &ctx, ObAlterTableStm
return ret;
}
ObCommentExecutor::ObCommentExecutor()
{
}
ObCommentExecutor::~ObCommentExecutor()
{
}
int ObCommentExecutor::execute(ObExecContext &ctx, ObAlterTableStmt &stmt)
{
int ret = OB_SUCCESS;
ObTaskExecutorCtx *task_exec_ctx = nullptr;
obrpc::ObCommonRpcProxy *common_rpc_proxy = nullptr;
obrpc::ObAlterTableArg &alter_table_arg = stmt.get_alter_table_arg();
LOG_TRACE("start of comment execute", K(alter_table_arg));
ObString first_stmt;
if (OB_FAIL(stmt.get_first_stmt(first_stmt))) {
LOG_WARN("fail to get first stmt", KR(ret));
} else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) {
ret = OB_NOT_INIT;
LOG_WARN("task_exec_ctx is null", KR(ret));
} else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) {
LOG_WARN("fail to get common rpc", KR(ret));
} else if (OB_ISNULL(common_rpc_proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("common_rpc_proxy is nullptr", KR(ret));
} else {
ObSQLSessionInfo *my_session = nullptr;
obrpc::ObSetCommentArg set_comment_arg;
obrpc::ObParallelDDLRes set_comment_res;
const int64_t tenant_id = alter_table_arg.alter_table_schema_.get_tenant_id();
alter_table_arg.ddl_stmt_str_ = first_stmt;
alter_table_arg.is_parallel_ = true;
my_session = ctx.get_my_session();
int64_t start_time = ObTimeUtility::current_time();
ObTimeoutCtx tctx;
const int64_t rpc_timeout = (static_cast<obrpc::ObRpcProxy*>(common_rpc_proxy))->timeout();
if (OB_ISNULL(my_session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get my session", KR(ret));
} else if (OB_INVALID_ID == alter_table_arg.session_id_
&& FALSE_IT(alter_table_arg.session_id_ = my_session->get_sessid_for_table())) {
// should not in this field
} else if (OB_FAIL(tctx.set_timeout(rpc_timeout))) {
LOG_WARN("fail to set timeout ctx", KR(ret));
} else if (OB_FAIL(assign_alter_to_comment_(alter_table_arg, set_comment_arg))) {
LOG_WARN("fail to assign alter table arg to set comment arg", KR(ret));
} else if (OB_FAIL(common_rpc_proxy->set_comment(set_comment_arg, set_comment_res))) {
LOG_WARN("rpc proxy set comment failed", KR(ret), K(common_rpc_proxy->get_server()), K(set_comment_arg));
} else {
int64_t refresh_time = ObTimeUtility::current_time();
if (OB_FAIL(ObSchemaUtils::try_check_parallel_ddl_schema_in_sync(
tctx, my_session, tenant_id, set_comment_res.schema_version_, false /*skip_consensus*/))) {
LOG_WARN("fail to check paralleld ddl schema in sync", KR(ret), K(set_comment_res));
}
int64_t end_time = ObTimeUtility::current_time();
LOG_INFO("[parallel_comment_table]", KR(ret),
"tenant_id", tenant_id,
"cost", end_time - start_time,
"execute_time", refresh_time - start_time,
"wait_schema", end_time - refresh_time,
"table_name", set_comment_arg.table_name_);
}
}
return ret;
}
int ObCommentExecutor::assign_alter_to_comment_(const obrpc::ObAlterTableArg &alter_table_arg, obrpc::ObSetCommentArg &set_comment_arg)
{
int ret = OB_SUCCESS;
const AlterTableSchema &alter_table_schema = alter_table_arg.alter_table_schema_;
set_comment_arg.session_id_ = alter_table_arg.session_id_;
set_comment_arg.database_name_ = alter_table_schema.get_origin_database_name();
set_comment_arg.table_name_ = alter_table_schema.get_origin_table_name();
if (OB_FAIL(set_comment_arg.ObDDLArg::assign(alter_table_arg))) {
LOG_WARN("fail to assign ob ddl arg", KR(ret));
} else if (alter_table_arg.alter_table_schema_.alter_option_bitset_.has_member(obrpc::ObAlterTableArg::COMMENT)) {
set_comment_arg.op_type_ = ObSetCommentArg::COMMENT_TABLE;
set_comment_arg.table_comment_ = alter_table_schema.get_comment();
} else {
set_comment_arg.op_type_ = ObSetCommentArg::COMMENT_COLUMN;
ObTableSchema::const_column_iterator it_begin = alter_table_schema.column_begin();
ObTableSchema::const_column_iterator it_end = alter_table_schema.column_end();
for(; OB_SUCC(ret) && it_begin != it_end; it_begin++) {
ObColumnSchemaV2 *column_schema = static_cast<ObColumnSchemaV2 *>(*it_begin);
if (OB_ISNULL(column_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column schema is null ptr", KR(ret));
} else if (OB_FAIL(set_comment_arg.column_name_list_.push_back(column_schema->get_column_name()))) {
LOG_WARN("fail to push back column name", KR(ret));
} else if (OB_FAIL(set_comment_arg.column_comment_list_.push_back(column_schema->get_comment()))) {
LOG_WARN("fail to push back column comment", KR(ret));
}
}
}
return ret;
}
/**
*
*/

View File

@ -200,6 +200,18 @@ private:
//DISALLOW_COPY_AND_ASSIGN(ObAlterTableExecutor);
};
class ObCommentExecutor
{
public:
ObCommentExecutor();
virtual ~ObCommentExecutor();
int execute(ObExecContext &ctx, ObAlterTableStmt &stmt);
private:
// because of the lack of the assign in alter table schema and alter column schema, this function is implemented for
// assigning args needed for parallel comment.
int assign_alter_to_comment_(const obrpc::ObAlterTableArg &alter_table_arg, obrpc::ObSetCommentArg &set_comment_arg);
};
class ObDropTableStmt;
class ObDropTableExecutor
{

View File

@ -12,6 +12,7 @@
#define USING_LOG_PREFIX SQL_EXE
#include "share/ob_cluster_version.h"
#include "sql/resolver/ob_cmd.h"
#include "sql/executor/ob_cmd_executor.h"
#include "lib/ob_name_def.h"
@ -879,7 +880,22 @@ int ObCmdExecutor::execute(ObExecContext &ctx, ObICmd &cmd)
}
case stmt::T_SET_TABLE_COMMENT:
case stmt::T_SET_COLUMN_COMMENT: {
DEFINE_EXECUTE_CMD(ObAlterTableStmt, ObAlterTableExecutor);
ObAlterTableStmt &stmt = *(static_cast<ObAlterTableStmt*>(&cmd));
const uint64_t tenant_id = stmt.get_tenant_id();
uint64_t data_version = OB_INVALID_VERSION;
bool is_parallel_ddl = true;
if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, data_version))) {
LOG_WARN("fail to get data version", KR(ret), K(tenant_id));
} else if (OB_FAIL(ObParallelDDLControlMode::is_parallel_ddl_enable(
ObParallelDDLControlMode::SET_COMMENT, tenant_id, is_parallel_ddl))) {
LOG_WARN("fail to get whether is parallel set comment", KR(ret), K(tenant_id));
} else if (!(data_version >= DATA_VERSION_4_3_5_0
|| (data_version >= DATA_VERSION_4_2_2_0 && data_version <= DATA_VERSION_4_3_0_0))
|| !is_parallel_ddl) {
DEFINE_EXECUTE_CMD(ObAlterTableStmt, ObAlterTableExecutor);
} else {
DEFINE_EXECUTE_CMD(ObAlterTableStmt, ObCommentExecutor);
}
break;
}
case stmt::T_XA_START: {

View File

@ -774,6 +774,8 @@ int ObCreateIndexResolver::resolve(const ParseNode &parse_tree)
SQL_RESV_LOG(WARN, "failed to add based_schema_object_info to arg",
K(ret), K(tbl_schema->get_table_id()),
K(tbl_schema->get_schema_version()));
} else if (OB_FAIL(add_based_udt_info(*tbl_schema))) {
SQL_RESV_LOG(WARN, "failed to add based_schema_object_info to arg", KR(ret));
}
}
DEBUG_SYNC(HANG_BEFORE_RESOLVER_FINISH);
@ -934,5 +936,45 @@ int ObCreateIndexResolver::set_table_option_to_stmt(const uint64_t data_table_id
}
return ret;
}
int ObCreateIndexResolver::add_based_udt_info(const share::schema::ObTableSchema &tbl_schema)
{
int ret = OB_SUCCESS;
ObCreateIndexStmt *create_index_stmt = static_cast<ObCreateIndexStmt*>(stmt_);
if (OB_ISNULL(create_index_stmt) || OB_ISNULL(session_info_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("create index stmt is nullptr", KR(ret));
} else {
ObTableSchema::const_column_iterator begin = tbl_schema.column_begin();
ObTableSchema::const_column_iterator end = tbl_schema.column_end();
ObCreateIndexArg &arg = create_index_stmt->get_create_index_arg();
for (; OB_SUCC(ret) && begin != end; begin++) {
ObColumnSchemaV2 *col = (*begin);
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get column schema failed", KR(ret));
} else if (col->is_extend()) {
const ObUDTTypeInfo *udt_info = nullptr;
const uint64_t udt_id = col->get_sub_data_type();
const uint64_t tenant_id = pl::get_tenant_id_by_object_id(udt_id);
if (OB_FAIL(schema_checker_->get_udt_info(tenant_id,
udt_id,
udt_info))) {
LOG_WARN("fail to get udt info", KR(ret), K(tenant_id), K(udt_id));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_OBJECT_NOT_EXIST;
LOG_WARN("udt not exist", KR(ret), K(tenant_id), K(udt_id));
} else if (OB_FAIL(ob_udt_check_and_add_ddl_dependency(udt_id, UDT_SCHEMA,
udt_info->get_schema_version(),
udt_info->get_tenant_id(),
arg))) {
LOG_WARN("fail to push back udt info", KR(ret), K(udt_id), K(tenant_id));
}
}
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -60,6 +60,7 @@ protected:
int add_new_indexkey_for_oracle_temp_table();
int fill_session_info_into_arg(const sql::ObSQLSessionInfo *session,
ObCreateIndexStmt *crt_idx_stmt);
int add_based_udt_info(const share::schema::ObTableSchema &tbl_schema);
private:
bool is_oracle_temp_table_; //是否创建oracle的临时表上索引
bool is_spec_block_size; //是否指定block size

View File

@ -3659,6 +3659,9 @@ int ObDDLResolver::resolve_column_definition(ObColumnSchemaV2 &column,
if (OB_ISNULL(ddl_arg)) {
} else if (OB_FAIL(schema_checker_->get_udt_info(tenant_id, udt_id, udt_info))) {
LOG_WARN("failed to get udt info", K(ret));
} else if (OB_ISNULL(udt_info)) {
ret = OB_ERR_OBJECT_NOT_EXIST;
LOG_WARN("udt not exist", KR(ret), K(tenant_id), K(udt_id));
} else if (OB_FAIL(ob_udt_check_and_add_ddl_dependency(udt_id,
UDT_SCHEMA,
udt_info->get_schema_version(),

View File

@ -133,6 +133,7 @@ int ObSetCommentResolver::resolve(const ParseNode &parse_tree)
LOG_WARN("version before 4.3.1 or 4.2.2 not support comment on view", K(ret));
} else {
alter_table_stmt->set_table_id(table_schema->get_table_id());
alter_table_stmt->set_stmt_type(stmt::T_SET_TABLE_COMMENT);
}
} else if (T_SET_COLUMN_COMMENT == parse_tree.type_) {
// COMMENT ON COLUMN
@ -202,6 +203,7 @@ int ObSetCommentResolver::resolve(const ParseNode &parse_tree)
SQL_RESV_LOG(WARN, "column doesn't exist", K(ret), K(col_name));
} else {
alter_table_stmt->set_table_id(table_schema->get_table_id());
alter_table_stmt->set_stmt_type(stmt::T_SET_COLUMN_COMMENT);
}
}
} else {