[CP] Optimize slow performance when adding not null columns to empty table in oracle mode

Co-authored-by: Someti1mes <chenguo.chen@qq.com>
This commit is contained in:
obdev 2024-06-20 14:08:23 +00:00 committed by ob-robot
parent 92546c111b
commit 2383698d81
8 changed files with 495 additions and 62 deletions

View File

@ -10628,7 +10628,8 @@ int ObDDLService::alter_table_column(const ObTableSchema &origin_table_schema,
LOG_WARN("failed to check new table schema skip index", K(ret));
} else if (!is_origin_table_has_lob_column) {
if (OB_FAIL(create_aux_lob_table_if_need(
new_table_schema, schema_guard, ddl_operator, trans, is_add_lob))) {
new_table_schema, schema_guard, ddl_operator, trans,
false/*need_sync_schema_version*/, is_add_lob))) {
LOG_WARN("fail to create_aux_lob_table_if_need", K(ret), K(new_table_schema));
}
}
@ -10646,12 +10647,13 @@ int ObDDLService::create_aux_lob_table_if_need(ObTableSchema &data_table_schema,
ObSchemaGetterGuard &schema_guard,
ObDDLOperator &ddl_operator,
common::ObMySQLTransaction &trans,
const bool need_sync_schema_version,
bool &is_add_lob)
{
int ret = OB_SUCCESS;
is_add_lob = false;
ObArray<ObTableSchema> aux_table_schemas;
const uint64_t tenant_id = data_table_schema.get_tenant_id();
bool need_sync_schema_version = false;
SCN frozen_scn;
uint64_t tenant_data_version = 0;
ObArray<bool> need_create_empty_majors;
@ -10694,7 +10696,8 @@ int ObDDLService::create_aux_lob_table_if_need(ObTableSchema &data_table_schema,
ObSEArray<const ObTableSchema*, 2> schemas;
for (int64_t i = 0; OB_SUCC(ret) && i < aux_table_schemas.count(); i++) {
share::schema::ObTableSchema &table_schema = aux_table_schemas.at(i);
if (OB_FAIL(ddl_operator.create_table(table_schema, trans, NULL, need_sync_schema_version))) {
if (OB_FAIL(ddl_operator.create_table(table_schema, trans, NULL,
need_sync_schema_version && (i == aux_table_schemas.count() - 1)))) {
LOG_WARN("failed to create table schema", K(ret));
} else if (OB_FAIL(schemas.push_back(&table_schema))
|| OB_FAIL(need_create_empty_majors.push_back(true))) {
@ -10958,7 +10961,7 @@ int ObDDLService::alter_table_auto_increment(
int ObDDLService::alter_table_constraints(const ObAlterTableArg::AlterConstraintType op_type,
share::schema::ObSchemaGetterGuard &schema_guard,
const ObTableSchema &orig_table_schema,
AlterTableSchema &inc_table_schema,
const AlterTableSchema &inc_table_schema,
ObTableSchema &new_table_schema,
ObDDLOperator &ddl_operator,
ObMySQLTransaction &trans)
@ -12375,7 +12378,7 @@ int ObDDLService::alter_table_in_trans(obrpc::ObAlterTableArg &alter_table_arg,
const uint64_t tenant_data_version)
{
int ret = OB_SUCCESS;
const ObDDLType ddl_type = res.ddl_type_;
ObDDLType &ddl_type = res.ddl_type_;
if (OB_FAIL(check_inner_stat())) {
LOG_WARN("variable is not init");
@ -13063,9 +13066,10 @@ int ObDDLService::alter_table_in_trans(obrpc::ObAlterTableArg &alter_table_arg,
} else {
ObDDLTaskRecord task_record;
ObTableLockOwnerID owner_id;
ddl_type = is_add_not_null_col ?
ObDDLType::DDL_ADD_NOT_NULL_COLUMN : ObDDLType::DDL_CHECK_CONSTRAINT;
ObCreateDDLTaskParam param(new_table_schema.get_tenant_id(),
is_add_not_null_col ?
ObDDLType::DDL_ADD_NOT_NULL_COLUMN : ObDDLType::DDL_CHECK_CONSTRAINT,
ddl_type,
&new_table_schema,
nullptr,
(*iter)->get_constraint_id(),
@ -13388,6 +13392,71 @@ int ObDDLService::check_has_domain_index(
return ret;
}
int ObDDLService::check_is_oracle_mode_add_column_not_null_ddl(const obrpc::ObAlterTableArg &alter_table_arg,
ObSchemaGetterGuard &schema_guard,
bool &is_oracle_mode_add_column_not_null_ddl,
bool &is_default_value_null)
{
int ret = OB_SUCCESS;
is_oracle_mode_add_column_not_null_ddl = false;
is_default_value_null = false;
bool is_oracle_mode = false;
const AlterTableSchema &alter_table_schema = alter_table_arg.alter_table_schema_;
const ObTableSchema *table_schema = nullptr;
if (OB_FAIL(check_inner_stat())) {
LOG_WARN("variable is not init", K(ret));
} else if (OB_FAIL(get_and_check_table_schema(alter_table_arg,
schema_guard,
alter_table_schema,
table_schema))) {
LOG_WARN("fail to get and check table schema", K(ret));
} else if (OB_FAIL(table_schema->check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", KR(ret), KPC(table_schema));
} else if (is_oracle_mode
&& alter_table_arg.is_alter_columns_
&& !alter_table_arg.is_alter_indexs_
&& !alter_table_arg.is_alter_partitions_
&& !alter_table_arg.is_convert_to_character_
&& obrpc::ObAlterTableArg::ADD_CONSTRAINT == alter_table_arg.alter_constraint_type_) {
is_oracle_mode_add_column_not_null_ddl = true;
ObTableSchema::const_column_iterator it_begin = alter_table_schema.column_begin();
ObTableSchema::const_column_iterator it_end = alter_table_schema.column_end();
AlterColumnSchema *alter_column_schema = nullptr;
for(; OB_SUCC(ret) && is_oracle_mode_add_column_not_null_ddl && it_begin != it_end; it_begin++) {
if (OB_ISNULL(*it_begin)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("*it_begin is NULL", K(ret));
} else {
alter_column_schema = static_cast<AlterColumnSchema *>(*it_begin);
if (OB_DDL_ADD_COLUMN == alter_column_schema->alter_type_
&& alter_column_schema->get_orig_default_value().is_null()
&& !alter_column_schema->is_identity_column()
&& !alter_column_schema->is_xmltype()
&& !alter_column_schema->is_first_
&& !alter_column_schema->get_next_column_name()
&& !alter_column_schema->get_prev_column_name()
&& !is_lob_storage(alter_column_schema->get_data_type())) {
// MDS can not register more than 1 buffer ctx in the same trans(RW defensive and create lob),
// so that add not null lob will not hit the fast path.
} else {
is_oracle_mode_add_column_not_null_ddl = false;
}
// Check is not null column default value null
if (!is_default_value_null && alter_column_schema->has_not_null_constraint()) {
const ObObj &cur_default_value = alter_column_schema->get_cur_default_value();
is_default_value_null = (cur_default_value.is_null_oracle() ||
(cur_default_value.is_character_type()
&& (0 == cur_default_value.get_string().case_compare(N_NULL)
|| 0 == cur_default_value.get_string().case_compare("''"))));
}
}
}
} else {
is_oracle_mode_add_column_not_null_ddl = false;
}
return ret;
}
// check whether there is index operation, including add index and drop index.
int ObDDLService::check_has_index_operation(ObSchemaGetterGuard &schema_guard,
const uint64_t tenant_id,
@ -13842,6 +13911,228 @@ int ObDDLService::do_offline_ddl_in_trans(obrpc::ObAlterTableArg &alter_table_ar
return ret;
}
int ObDDLService::add_not_null_column_to_table_schema(
obrpc::ObAlterTableArg &alter_table_arg,
const ObTableSchema &origin_table_schema,
ObTableSchema &new_table_schema,
ObSchemaGetterGuard &schema_guard,
ObDDLOperator &ddl_operator,
ObDDLSQLTransaction &trans)
{
int ret = OB_SUCCESS;
const uint64_t tenant_id = origin_table_schema.get_tenant_id();
const AlterTableSchema &alter_table_schema = alter_table_arg.alter_table_schema_;
AlterColumnSchema *alter_column_schema = nullptr;
ObSEArray<ObString, 4> gen_col_expr_arr;
share::schema::ObTableSchema::const_column_iterator iter = origin_table_schema.column_begin();
share::schema::ObTableSchema::const_column_iterator end = origin_table_schema.column_end();
for (; OB_SUCC(ret) && iter != end; ++iter) {
const share::schema::ObColumnSchemaV2 *column = *iter;
if (OB_ISNULL(column)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid column schema", K(column));
} else if (column->is_generated_column()) {
const common::ObObj* ObObjtmp = &column->get_cur_default_value();
if (OB_FAIL(gen_col_expr_arr.push_back(ObObjtmp->get_string()))) {
LOG_WARN("fail to push back ObSEArray gen_col_expr_arr", K(ret));
}
}
}
const common::ObTimeZoneInfoWrap &tz_info_wrap = alter_table_arg.tz_info_wrap_;
const common::ObString *nls_formats = alter_table_arg.nls_formats_;
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(tz_info_wrap.get_time_zone_info())
|| OB_ISNULL(tz_info_wrap.get_time_zone_info()->get_tz_info_map())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid tz_info_wrap", K(tz_info_wrap), K(ret));
} else if (OB_ISNULL(nls_formats)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid nls_formats", K(ret));
} else {
uint64_t curr_udt_set_id = 0;
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++) {
if (OB_ISNULL(alter_column_schema = static_cast<AlterColumnSchema *>(*it_begin))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("*it_begin is NULL", K(ret));
} else if (OB_FAIL(add_new_column_to_table_schema(origin_table_schema,
alter_table_schema,
tz_info_wrap,
*nls_formats,
alter_table_arg.local_session_var_,
alter_table_arg.sequence_ddl_arg_,
alter_table_arg.allocator_,
new_table_schema,
*alter_column_schema,
gen_col_expr_arr,
schema_guard,
curr_udt_set_id,
&ddl_operator,
&trans))) {
LOG_WARN("failed to add new column to table schema", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(check_has_multi_autoinc(new_table_schema))) {
LOG_WARN("failed to check table has multi autoinc", K(ret));
} else if (OB_FAIL(alter_table_constraints(
obrpc::ObAlterTableArg::ADD_CONSTRAINT,
schema_guard,
origin_table_schema,
alter_table_schema,
new_table_schema,
ddl_operator,
trans))) {
LOG_WARN("alter table constraints failed", K(ret));
} else if (OB_FAIL(add_column_to_column_group(origin_table_schema,
alter_table_schema, new_table_schema, ddl_operator, trans))) {
LOG_WARN("fail to add_column_to_column_group", K(ret), K(alter_table_schema), K(new_table_schema));
} else if (OB_FAIL(new_table_schema.check_skip_index_valid())) {
LOG_WARN("failed to check new table schema skip index", K(ret));
} else if (OB_FAIL(ddl_operator.update_table_attribute(new_table_schema, trans,
OB_DDL_ALTER_TABLE, &alter_table_arg.ddl_stmt_str_))) {
LOG_WARN("failed to update data table schema attribute", K(ret));
} else {
ObArray<ObTabletID> new_tablet_ids;
if (OB_FAIL(new_table_schema.get_tablet_ids(new_tablet_ids))) {
LOG_WARN("failed to get tablet ids", K(ret));
} else if (OB_FAIL(build_single_table_rw_defensive(tenant_id, new_tablet_ids, new_table_schema.get_schema_version(), trans))) {
LOG_WARN("failed to build rw defensive", K(ret));
}
}
}
return ret;
}
int ObDDLService::add_not_null_column_default_null_to_table_schema(
obrpc::ObAlterTableArg &alter_table_arg,
const ObTableSchema &origin_table_schema,
ObTableSchema &new_table_schema,
ObSchemaGetterGuard &schema_guard,
ObDDLOperator &ddl_operator,
ObDDLSQLTransaction &trans)
{
int ret = OB_SUCCESS;
bool is_table_empty = false;
bool is_oracle_mode = false;
const uint64_t tenant_id = origin_table_schema.get_tenant_id();
if (OB_FAIL(origin_table_schema.check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", K(ret), K(origin_table_schema));
} else if (OB_UNLIKELY(!is_oracle_mode)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("add column not null in mysql mode is online ddl, not offline ddl", K(ret), K(is_oracle_mode));
} else if (OB_FAIL(lock_table(trans, origin_table_schema))) {
LOG_WARN("failed to lock ddl lock", K(ret));
} else if (OB_FAIL(ObDDLUtil::check_table_empty_in_oracle_mode(tenant_id,
origin_table_schema.get_table_id(),
schema_guard,
is_table_empty))) {
LOG_WARN("failed to check table empty in oracle mode", K(ret));
} else if (!is_table_empty) {
ret = OB_ERR_TABLE_ADD_NOT_NULL_COLUMN_NOT_EMPTY;
LOG_WARN("table add not null column to is not empty", K(ret), K(tenant_id), K(origin_table_schema.get_table_id()));
} else if (OB_FAIL(add_not_null_column_to_table_schema(alter_table_arg,
origin_table_schema,
new_table_schema,
schema_guard,
ddl_operator,
trans))) {
LOG_WARN("failed to add new column to table schema");
}
return ret;
}
int ObDDLService::do_oracle_add_column_not_null_in_trans(obrpc::ObAlterTableArg &alter_table_arg,
ObSchemaGetterGuard &schema_guard,
const bool is_default_value_null)
{
int ret = OB_SUCCESS;
const AlterTableSchema &alter_table_schema = alter_table_arg.alter_table_schema_;
const uint64_t tenant_id = alter_table_schema.get_tenant_id();
if (OB_FAIL(check_inner_stat())) {
LOG_WARN("variable is not init", K(ret));
} else {
SMART_VAR(ObTableSchema, new_table_schema) {
const ObTableSchema *origin_table_schema = nullptr;
bool is_oracle_mode = false;
const common::ObTimeZoneInfoWrap &tz_info_wrap = alter_table_arg.tz_info_wrap_;
const common::ObString *nls_formats = alter_table_arg.nls_formats_;
if (OB_FAIL(get_and_check_table_schema(alter_table_arg,
schema_guard,
alter_table_schema,
origin_table_schema))) {
LOG_WARN("fail to get and check table schema", K(ret));
} else if (OB_FAIL(origin_table_schema->check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", K(ret), K(origin_table_schema));
} else if (OB_UNLIKELY(!is_oracle_mode)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("add column not null in mysql mode is online ddl, not offline ddl", K(ret), K(is_oracle_mode));
} else if (OB_ISNULL(tz_info_wrap.get_time_zone_info())
|| OB_ISNULL(tz_info_wrap.get_time_zone_info()->get_tz_info_map())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid tz_info_wrap", K(tz_info_wrap), K(ret));
} else if (OB_ISNULL(nls_formats)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid nls_formats", K(ret));
} else if (OB_FAIL(new_table_schema.assign(*origin_table_schema))) {
LOG_WARN("fail to assign schema", K(ret));
} else {
ObDDLSQLTransaction trans(schema_service_);
int64_t refreshed_schema_version = 0;
if (OB_FAIL(schema_guard.get_schema_version(tenant_id, refreshed_schema_version))) {
LOG_WARN("failed to get tenant schema version", KR(ret), K(tenant_id));
} else if (OB_FAIL(trans.start(sql_proxy_, tenant_id, refreshed_schema_version))) {
LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));
} else {
ObDDLOperator ddl_operator(*schema_service_, *sql_proxy_);
if (is_default_value_null) {
if (OB_FAIL(add_not_null_column_default_null_to_table_schema(
alter_table_arg,
*origin_table_schema,
new_table_schema,
schema_guard,
ddl_operator,
trans))) {
LOG_WARN("failed to add default value null column to table schema", K(ret));
}
} else if (OB_FAIL(add_not_null_column_to_table_schema(alter_table_arg,
*origin_table_schema,
new_table_schema,
schema_guard,
ddl_operator,
trans))) {
LOG_WARN("failed to add column to table schema", K(ret));
}
if (OB_SUCC(ret)) {
// add lob.
if (!origin_table_schema->has_lob_column() && new_table_schema.has_lob_column()) {
// ATTENTION.
// MDS can not register more than 1 buffer ctx in the same trans(RW defensive and create lob),
// so that add not null lob will not hit the fast path.
ret = OB_NOT_SUPPORTED;
LOG_WARN("Not supported to fast add not null lob column in this path", K(ret), K(alter_table_arg));
}
}
}
if (trans.is_started()) {
int temp_ret = OB_SUCCESS;
if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {
LOG_WARN_RET(temp_ret, "trans end failed", "is_commit", OB_SUCCESS == ret, K(temp_ret));
ret = (OB_SUCC(ret)) ? temp_ret : ret;
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(publish_schema(tenant_id))) {
LOG_WARN("publish_schema failed", K(ret));
}
}
}
}
}
return ret;
}
int ObDDLService::create_hidden_table(
const obrpc::ObCreateHiddenTableArg &create_hidden_table_arg,
obrpc::ObCreateHiddenTableRes &res)
@ -15533,6 +15824,8 @@ int ObDDLService::alter_table(obrpc::ObAlterTableArg &alter_table_arg,
//do alter table in transaction
if (OB_SUCC(ret)) {
uint64_t data_version = 0;
bool is_oracle_mode_add_column_not_null_ddl = false;
bool is_default_value_null = false;
if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, data_version))) {
LOG_WARN("failed to get tenant data version", K(ret), K(tenant_id), K(data_version));
} else if (is_alter_sess_active_time) {
@ -15545,6 +15838,21 @@ int ObDDLService::alter_table(obrpc::ObAlterTableArg &alter_table_arg,
}
} else if (OB_FAIL(check_is_offline_ddl(alter_table_arg, ddl_type, ddl_need_retry_at_executor))) {
LOG_WARN("failed to check is offline ddl", K(ret));
} else if (((MOCK_DATA_VERSION_4_2_1_3 <= data_version && DATA_VERSION_4_3_0_0 > data_version)
|| (DATA_VERSION_4_3_2_0 <= data_version)) // [4213, 430) & [4320, )
&& OB_FAIL(check_is_oracle_mode_add_column_not_null_ddl(alter_table_arg,
schema_guard,
is_oracle_mode_add_column_not_null_ddl,
is_default_value_null))) {
LOG_WARN("falied to check is oracle add column not null", K(ret));
} else if (is_oracle_mode_add_column_not_null_ddl) {
if (OB_FAIL(do_oracle_add_column_not_null_in_trans(alter_table_arg,
schema_guard,
is_default_value_null))) {
LOG_WARN("add column not null failed", K(ret));
} else {
ddl_type = ObDDLType::DDL_NORMAL_TYPE;
}
} else {
// offline ddl cannot appear at the same time with other ddl types
if (is_long_running_ddl(ddl_type)) {
@ -19084,7 +19392,6 @@ int ObDDLService::unbind_hidden_tablets(
int ObDDLService::write_ddl_barrier(
const ObTableSchema &hidden_table_schema,
const uint64_t session_id,
ObDDLSQLTransaction &trans)
{
int ret = OB_SUCCESS;
@ -19141,6 +19448,39 @@ int ObDDLService::write_ddl_barrier(
return ret;
}
int ObDDLService::build_single_table_rw_defensive(
const uint64_t tenant_id,
const ObArray<ObTabletID> &tablet_ids,
const int64_t schema_version,
ObDDLSQLTransaction &trans)
{
int ret = OB_SUCCESS;
ObArray<ObBatchUnbindTabletArg> args;
if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id || tablet_ids.empty() || schema_version <= 0)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", K(ret), K(tenant_id), K(tablet_ids), K(schema_version));
} else if (OB_FAIL(build_modify_tablet_binding_args(
tenant_id, tablet_ids, true/*is_hidden_tablets*/, schema_version, args, trans))) {
LOG_WARN("failed to build reuse index args", K(ret));
}
ObArenaAllocator allocator("DDLRWDefens");
for (int64_t i = 0; OB_SUCC(ret) && i < args.count(); i++) {
int64_t pos = 0;
int64_t size = args[i].get_serialize_size();
char *buf = nullptr;
allocator.reuse();
if (OB_ISNULL(buf = static_cast<char *>(allocator.alloc(size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to allocate", K(ret));
} else if (OB_FAIL(args[i].serialize(buf, size, pos))) {
LOG_WARN("failed to serialize arg", K(ret));
} else if (OB_FAIL(trans.register_tx_data(args[i].tenant_id_, args[i].ls_id_, transaction::ObTxDataSourceType::UNBIND_TABLET_NEW_MDS, buf, pos))) {
LOG_WARN("failed to register tx data", K(ret));
}
}
return ret;
}
int ObDDLSQLTransaction::register_tx_data(
const uint64_t tenant_id,
const share::ObLSID &ls_id,
@ -19343,7 +19683,7 @@ int ObDDLService::swap_orig_and_hidden_table_state(obrpc::ObAlterTableArg &alter
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(write_ddl_barrier(*hidden_table_schema, alter_table_arg.session_id_, trans))) {
if (OB_FAIL(write_ddl_barrier(*hidden_table_schema, trans))) {
LOG_WARN("failed to write ddl barrier", K(ret));
}
}
@ -19887,7 +20227,7 @@ int ObDDLService::make_recover_restore_tables_visible(obrpc::ObAlterTableArg &al
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(write_ddl_barrier(*hidden_table_schema, alter_table_arg.session_id_, trans))) {
if (OB_FAIL(write_ddl_barrier(*hidden_table_schema, trans))) {
LOG_WARN("failed to write ddl barrier", K(ret));
}
}

View File

@ -464,7 +464,7 @@ public:
virtual int alter_table_constraints(const obrpc::ObAlterTableArg::AlterConstraintType type,
share::schema::ObSchemaGetterGuard &schema_guard,
const share::schema::ObTableSchema &orig_table_schema,
share::schema::AlterTableSchema &inc_table_schema,
const share::schema::AlterTableSchema &inc_table_schema,
share::schema::ObTableSchema &new_table_schema,
ObDDLOperator &ddl_operator,
ObMySQLTransaction &trans);
@ -525,17 +525,17 @@ public:
ObMySQLTransaction &trans);
int get_tablets(
const uint64_t tenant_id,
const ObArray<common::ObTabletID> &tablet_ids,
ObIArray<LSTabletID> &tablets,
ObDDLSQLTransaction &trans);
const uint64_t tenant_id,
const ObArray<common::ObTabletID> &tablet_ids,
common::ObIArray<LSTabletID> &tablets,
ObDDLSQLTransaction &trans);
int build_modify_tablet_binding_args(
const uint64_t tenant_id,
const ObArray<ObTabletID> &tablet_ids,
const bool is_hidden_tablets,
const int64_t schema_version,
ObIArray<ObBatchUnbindTabletArg> &modify_args,
ObDDLSQLTransaction &trans);
const uint64_t tenant_id,
const ObArray<common::ObTabletID> &tablet_ids,
const bool is_hidden_tablets,
const int64_t schema_version,
common::ObIArray<storage::ObBatchUnbindTabletArg> &args,
ObDDLSQLTransaction &trans);
int unbind_hidden_tablets(
const share::schema::ObTableSchema &orig_table_schema,
const share::schema::ObTableSchema &hidden_table_schema,
@ -543,7 +543,13 @@ public:
ObDDLSQLTransaction &trans);
int write_ddl_barrier(
const share::schema::ObTableSchema &hidden_table_schema,
const uint64_t session_id,
ObDDLSQLTransaction &trans);
// Register MDS for read and write defense verification after single table ddl
// like add column not null default null.
int build_single_table_rw_defensive(
const uint64_t tenant_id,
const ObArray<common::ObTabletID> &tablet_ids,
const int64_t schema_version,
ObDDLSQLTransaction &trans);
int check_hidden_table_constraint_exist(
const ObTableSchema *hidden_table_schema,
@ -1499,12 +1505,33 @@ private:
int check_is_offline_ddl(obrpc::ObAlterTableArg &alter_table_arg,
share::ObDDLType &ddl_type,
bool &ddl_need_retry_at_executor);
int check_is_oracle_mode_add_column_not_null_ddl(const obrpc::ObAlterTableArg &alter_table_arg,
ObSchemaGetterGuard &schema_guard,
bool &is_oracle_mode_add_column_not_null_ddl,
bool &is_default_value_null);
int check_can_bind_tablets(const share::ObDDLType ddl_type,
bool &bind_tablets);
int check_ddl_with_primary_key_operation(const obrpc::ObAlterTableArg &alter_table_arg,
bool &with_primary_key_operation);
int do_offline_ddl_in_trans(obrpc::ObAlterTableArg &alter_table_arg,
obrpc::ObAlterTableRes &res);
int add_not_null_column_to_table_schema(
obrpc::ObAlterTableArg &alter_table_arg,
const ObTableSchema &origin_table_schema,
ObTableSchema &new_table_schema,
ObSchemaGetterGuard &schema_guard,
ObDDLOperator &ddl_operator,
ObDDLSQLTransaction &trans);
int add_not_null_column_default_null_to_table_schema(
obrpc::ObAlterTableArg &alter_table_arg,
const ObTableSchema &origin_table_schema,
ObTableSchema &new_table_schema,
ObSchemaGetterGuard &schema_guard,
ObDDLOperator &ddl_operator,
ObDDLSQLTransaction &trans);
int do_oracle_add_column_not_null_in_trans(obrpc::ObAlterTableArg &alter_table_arg,
ObSchemaGetterGuard &schema_guard,
const bool is_default_value_null);
int gen_new_index_table_name(
const common::ObString &orig_index_table_name,
const uint64_t orig_table_id,
@ -2072,6 +2099,7 @@ private:
ObSchemaGetterGuard &schema_guard,
ObDDLOperator &ddl_operator,
common::ObMySQLTransaction &trans,
const bool need_sync_schema_version,
bool &is_add_lob);
int lock_tables_of_database(const share::schema::ObDatabaseSchema &database_schema,
ObMySQLTransaction &trans);

View File

@ -2191,6 +2191,7 @@ bool ObDDLUtil::reach_time_interval(const int64_t i, volatile int64_t &last_time
}
return bret;
}
int ObDDLUtil::get_temp_store_compress_type(const ObCompressorType schema_compr_type,
const int64_t parallel,
ObCompressorType &compr_type)
@ -2310,6 +2311,85 @@ int ObDDLUtil::check_tablet_checksum_error(
return ret;
}
int ObDDLUtil::check_table_empty_in_oracle_mode(
const uint64_t tenant_id,
const uint64_t table_id,
ObSchemaGetterGuard &schema_guard,
bool &is_table_empty)
{
int ret = OB_SUCCESS;
is_table_empty = false;
const ObSimpleTableSchemaV2 *table_schema = nullptr;
const ObSimpleDatabaseSchema *database_schema = nullptr;
bool is_oracle_mode = false;
if (OB_INVALID_TENANT_ID == tenant_id || OB_INVALID_ID == table_id) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(tenant_id), K(table_id));
} else if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id, table_id, table_schema))) {
LOG_WARN("get table schema failed", K(ret), K(tenant_id), K(table_id));
} else if (OB_ISNULL(table_schema)) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("table schema not exist", K(ret), K(table_id));
} else if (OB_FAIL(table_schema->check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("fail to check is oracle mode", K(ret), K(table_schema));
} else if (!is_oracle_mode) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("check table empty in mysql mode support later", K(ret), K(is_oracle_mode));
} else if (OB_FAIL(schema_guard.get_database_schema(tenant_id, table_schema->get_database_id(), database_schema))) {
LOG_WARN("get database schema failed", K(ret), K(tenant_id));
} else if (OB_ISNULL(database_schema)) {
ret = OB_ERR_SYS;
LOG_WARN("get database schema failed", K(ret), K(table_id));
} else {
const ObString &check_expr_str = "1 != 1";
const ObString &database_name = database_schema->get_database_name_str();
const ObString &table_name = table_schema->get_table_name_str();
ObSqlString sql_string;
ObSessionParam session_param;
session_param.sql_mode_ = nullptr;
session_param.tz_info_wrap_ = nullptr;
session_param.ddl_info_.set_is_ddl(true);
session_param.ddl_info_.set_source_table_hidden(table_schema->is_user_hidden_table());
session_param.ddl_info_.set_dest_table_hidden(false);
ObTimeoutCtx timeout_ctx;
ObCommonSqlProxy *sql_proxy = nullptr;
SMART_VAR(ObMySQLProxy::MySQLResult, res) {
common::sqlclient::ObMySQLResult *result = nullptr;
ObSqlString ddl_schema_hint_str;
if (OB_FAIL(ObShareUtil::set_default_timeout_ctx(timeout_ctx, GCONF.internal_sql_execute_timeout))) {
LOG_WARN("failed to set default timeout ctx", K(ret), K(timeout_ctx));
} else if (OB_FAIL(ObDDLUtil::generate_ddl_schema_hint_str(table_name, table_schema->get_schema_version(), true, ddl_schema_hint_str))) {
LOG_WARN("failed to generate ddl schema hint str", K(ret));
} else if (OB_FAIL(sql_string.assign_fmt(
"SELECT /*+ %.*s */ 1 FROM \"%.*s\".\"%.*s\" WHERE NOT (%.*s) AND ROWNUM = 1",
static_cast<int>(ddl_schema_hint_str.length()), ddl_schema_hint_str.ptr(),
static_cast<int>(database_name.length()), database_name.ptr(),
static_cast<int>(table_name.length()), table_name.ptr(),
static_cast<int>(check_expr_str.length()), check_expr_str.ptr()))) {
LOG_WARN("fail to assign format", K(ret));
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(sql_proxy = GCTX.ddl_oracle_sql_proxy_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sql proxy is null", K(ret));
} else if (OB_FAIL(GCTX.ddl_oracle_sql_proxy_->read(res, table_schema->get_tenant_id(), sql_string.ptr(), &session_param))) {
LOG_WARN("execute sql failed", K(ret), K(sql_string.ptr()));
} else if (OB_ISNULL(result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("execute sql failed", K(ret), K(table_schema->get_tenant_id()), K(sql_string));
} else if (OB_FAIL(result->next())) {
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
is_table_empty = true;
} else {
LOG_WARN("iterate next result fail", K(ret), K(sql_string));
}
}
}
}
return ret;
}
int ObDDLUtil::batch_check_tablet_checksum(
const uint64_t tenant_id,
const int64_t start_idx,

View File

@ -674,6 +674,12 @@ public:
share::schema::ObSchemaGetterGuard *&src_tenant_schema_guard,
share::schema::ObSchemaGetterGuard *&dst_tenant_schema_guard);
static int check_table_empty_in_oracle_mode(
const uint64_t tenant_id,
const uint64_t table_id,
share::schema::ObSchemaGetterGuard &schema_guard,
bool &is_table_empty);
static int check_tenant_status_normal(
ObISQLClient *proxy,
const uint64_t check_tenant_id);

View File

@ -1257,36 +1257,7 @@ int ObAlterTableExecutor::need_check_constraint_validity(obrpc::ObAlterTableArg
} else if (CONSTRAINT_TYPE_NOT_NULL == (*iter)->get_constraint_type()) {
if (1 != (*iter)->get_column_cnt()) {
ret = OB_ERR_UNEXPECTED;
} else if (OB_INVALID_ID == *(*iter)->cst_col_begin()) {
// alter table add column not null.
ObTableSchema::const_column_iterator target_col_iter = NULL;
ObTableSchema::const_column_iterator cst_col_iter =
alter_table_arg.alter_table_schema_.column_begin();
ObString cst_col_name;
if (OB_FAIL((*iter)->get_not_null_column_name(cst_col_name))) {
LOG_WARN("get not null column name failed", K(ret));
} else {
for(; NULL == target_col_iter
&& cst_col_iter != alter_table_arg.alter_table_schema_.column_end();
cst_col_iter++) {
if ((*cst_col_iter)->get_column_name_str().length() == cst_col_name.length()
&& 0 == (*cst_col_iter)->get_column_name_str().compare(cst_col_name)) {
target_col_iter = cst_col_iter;
}
}
if (OB_ISNULL(target_col_iter)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column schema not found", K(ret),K(alter_table_arg.alter_table_schema_),
K(cst_col_name));
} else {
const ObObj &cur_default_value = (*target_col_iter)->get_cur_default_value();
need_check = cur_default_value.is_null() ||
(cur_default_value.is_string_type()
&& (0 == cur_default_value.get_string().case_compare(N_NULL)
|| 0 == cur_default_value.get_string().case_compare("''")));
}
}
} else {
} else if (OB_INVALID_ID != *(*iter)->cst_col_begin()) {
// alter table modify column not null.
need_check = (*iter)->is_validated();
}

View File

@ -1991,8 +1991,8 @@ int ObLSTabletService::inner_table_scan(
if (OB_UNLIKELY(timeout <= 0)) {
ret = OB_TIMEOUT;
LOG_WARN("table scan timeout", K(ret), K(current_time), "table_scan_param_timeout", param.timeout_, K(lbt()));
} else if (OB_FAIL(tablet_handle.get_obj()->check_snapshot_readable_with_cache(snapshot_version, timeout))) {
LOG_WARN("failed to check snapshot readable", K(ret), K(snapshot_version), K(timeout));
} else if (OB_FAIL(tablet_handle.get_obj()->check_snapshot_readable_with_cache(snapshot_version, param.schema_version_, timeout))) {
LOG_WARN("failed to check snapshot readable", K(ret), K(snapshot_version), K(param.schema_version_), K(timeout));
} else if (param.need_switch_param_) {
if (OB_FAIL(iter.switch_param(param, tablet_handle))) {
LOG_WARN("failed to init table scan iterator, ", K(ret));

View File

@ -7043,6 +7043,7 @@ int ObTablet::check_schema_version_with_cache(
int ObTablet::check_snapshot_readable_with_cache(
const int64_t snapshot_version,
const int64_t schema_version,
const int64_t timeout)
{
int ret = OB_SUCCESS;
@ -7058,7 +7059,7 @@ int ObTablet::check_snapshot_readable_with_cache(
{
SpinRLockGuard guard(mds_cache_lock_);
if (ddl_data_cache_.is_valid()) {
if (OB_FAIL(check_snapshot_readable(ddl_data_cache_, snapshot_version))) {
if (OB_FAIL(check_snapshot_readable(ddl_data_cache_, snapshot_version, schema_version))) {
LOG_WARN("fail to check schema version", K(ret));
}
r_valid = true;
@ -7068,7 +7069,7 @@ int ObTablet::check_snapshot_readable_with_cache(
if (OB_SUCC(ret) && !r_valid) {
SpinWLockGuard guard(mds_cache_lock_);
if (ddl_data_cache_.is_valid()) {
if (OB_FAIL(check_snapshot_readable(ddl_data_cache_, snapshot_version))) {
if (OB_FAIL(check_snapshot_readable(ddl_data_cache_, snapshot_version, schema_version))) {
LOG_WARN("fail to check snapshot version", K(ret));
}
} else {
@ -7108,7 +7109,7 @@ int ObTablet::check_snapshot_readable_with_cache(
} else if (OB_ISNULL(candidate_cache)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("ddl data cache is null", K(ret), KP(candidate_cache), K(tablet_meta_.ls_id_), K(tablet_id));
} else if (OB_FAIL(check_snapshot_readable(*candidate_cache, snapshot_version))) {
} else if (OB_FAIL(check_snapshot_readable(*candidate_cache, snapshot_version, schema_version))) {
LOG_WARN("fail to check snapshot version", K(ret), K(tablet_meta_.ls_id_), K(tablet_id));
}
}
@ -7119,15 +7120,19 @@ int ObTablet::check_snapshot_readable_with_cache(
return ret;
}
int ObTablet::check_snapshot_readable(const ObDDLInfoCache& ddl_info_cache, const int64_t snapshot_version)
int ObTablet::check_snapshot_readable(const ObDDLInfoCache& ddl_info_cache, const int64_t snapshot_version, const int64_t schema_version)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ddl_info_cache.is_redefined() && snapshot_version >= ddl_info_cache.get_snapshot_version())) {
ret = OB_SCHEMA_EAGAIN;
LOG_WARN("read data after ddl, need to retry on new tablet", K(ret), K(snapshot_version), K(ddl_info_cache));
} else if (OB_UNLIKELY(!ddl_info_cache.is_redefined() && snapshot_version < ddl_info_cache.get_snapshot_version())) {
ret = OB_SNAPSHOT_DISCARDED;
LOG_WARN("read data before ddl", K(ret), K(snapshot_version), K(ddl_info_cache));
if (schema_version < ddl_info_cache.get_schema_version()) {
LOG_DEBUG("allow old schema and old snapshot read", K(ret), K(ddl_info_cache), K(snapshot_version), K(schema_version));
} else {
ret = OB_SNAPSHOT_DISCARDED;
LOG_WARN("read data before ddl", K(ret), K(ddl_info_cache), K(snapshot_version), K(schema_version));
}
}
return ret;
}

View File

@ -527,7 +527,10 @@ public:
int check_new_mds_with_cache(const int64_t snapshot_version, const int64_t timeout);
int check_tablet_status_for_read_all_committed();
int check_schema_version_with_cache(const int64_t schema_version, const int64_t timeout);
int check_snapshot_readable_with_cache(const int64_t snapshot_version, const int64_t timeout);
int check_snapshot_readable_with_cache(
const int64_t snapshot_version,
const int64_t schema_version,
const int64_t timeout);
int set_tablet_status(
const ObTabletCreateDeleteMdsUserData &tablet_status,
mds::MdsCtx &ctx);
@ -609,7 +612,7 @@ private:
int self_serialize(char *buf, const int64_t len, int64_t &pos) const;
int64_t get_self_serialize_size() const;
static int check_schema_version(const ObDDLInfoCache& ddl_info_cache, const int64_t schema_version);
static int check_snapshot_readable(const ObDDLInfoCache& ddl_info_cache, const int64_t snapshot_version);
static int check_snapshot_readable(const ObDDLInfoCache& ddl_info_cache, const int64_t snapshot_version, const int64_t schema_version);
int get_column_store_sstable_checksum(common::ObIArray<int64_t> &column_checksums, ObCOSSTableV2 &co_sstable);
logservice::ObLogHandler *get_log_handler() const { return log_handler_; } // TODO(bowen.gbw): get log handler from tablet pointer handle