diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index b000d4837b..b68f3542c6 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -1842,6 +1842,28 @@ int ObDDLOperator::reinit_autoinc_row(const ObTableSchema &table_schema, return ret; } +int ObDDLOperator::try_reinit_autoinc_row(const ObTableSchema &table_schema, + common::ObMySQLTransaction &trans) +{ + int ret = OB_SUCCESS; + bool need_reinit_inner_table = false; + const uint64_t table_id = table_schema.get_table_id(); + const uint64_t tenant_id = table_schema.get_tenant_id(); + const int64_t truncate_version = table_schema.get_truncate_version(); + const uint64_t column_id = table_schema.get_autoinc_column_id(); + ObAutoincrementService &autoinc_service = share::ObAutoincrementService::get_instance(); + if (OB_FAIL(autoinc_service.try_lock_autoinc_row(tenant_id, table_id, column_id, truncate_version, + need_reinit_inner_table, trans))) { + LOG_WARN("fail to check inner autoinc version", KR(ret), K(tenant_id), K(table_id), K(column_id)); + } else if (need_reinit_inner_table) { + if (OB_FAIL(autoinc_service.reset_autoinc_row(tenant_id, table_id, column_id, + truncate_version, trans))) { + LOG_WARN("fail to reinit autoinc row", KR(ret), K(tenant_id), K(table_id), K(column_id)); + } + } + return ret; +} + // Notice: this function process index. int ObDDLOperator::alter_table_drop_aux_column( ObTableSchema &new_table_schema, diff --git a/src/rootserver/ob_ddl_operator.h b/src/rootserver/ob_ddl_operator.h index b80026244c..4c59b677ff 100644 --- a/src/rootserver/ob_ddl_operator.h +++ b/src/rootserver/ob_ddl_operator.h @@ -311,6 +311,9 @@ public: const common::ObString *ddl_stmt_str = NULL); int reinit_autoinc_row(const ObTableSchema &table_schema, common::ObMySQLTransaction &trans); + // for alter table autoinc to check __all_auto_increment + int try_reinit_autoinc_row(const ObTableSchema &table_schema, + common::ObMySQLTransaction &trans); int create_sequence_in_create_table(share::schema::ObTableSchema &table_schema, common::ObMySQLTransaction &trans, share::schema::ObSchemaGetterGuard &schema_guard, diff --git a/src/rootserver/ob_ddl_service.cpp b/src/rootserver/ob_ddl_service.cpp index 4c1366caaa..a626d81bbb 100755 --- a/src/rootserver/ob_ddl_service.cpp +++ b/src/rootserver/ob_ddl_service.cpp @@ -5056,16 +5056,29 @@ int ObDDLService::update_autoinc_schema(obrpc::ObAlterTableArg &alter_table_arg) LOG_WARN("unexpected alter_column_num or iter is NULL", K(ret), K(alter_column_num)); } else { const ObString &orig_column_name = alter_column_schema->get_origin_column_name(); + const ObColumnSchemaV2 *curr_column_schema = curr_table_schema->get_column_schema(orig_column_name); new_column_schema = new_table_schema.get_column_schema(orig_column_name); if (OB_ISNULL(new_column_schema)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("alter column schema is null"); + LOG_WARN("alter column schema is null", KR(ret), K(new_table_schema.get_table_id()), + K(orig_column_name)); + } else if (OB_ISNULL(curr_column_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cur column schema is null", KR(ret), K(curr_table_schema->get_table_id()), + K(orig_column_name)); } else { new_column_schema->set_autoincrement(alter_column_schema->is_autoincrement()); new_column_schema->set_nullable(alter_column_schema->is_nullable()); new_table_schema.set_auto_increment(alter_table_schema.get_auto_increment()); new_table_schema.set_autoinc_column_id(alter_column_schema->get_column_id()); - if (OB_FAIL(ddl_operator.update_single_column(trans, + + // we need clear inner autoinc when add autoinc attribute bug/53305960 + if (new_column_schema->is_autoincrement() && !curr_column_schema->is_autoincrement()) { + if (OB_FAIL(ddl_operator.try_reinit_autoinc_row(new_table_schema, trans))) { + LOG_WARN("fail to reinit autoinc row", KR(ret), K(new_table_schema)); + } + } + if (FAILEDx(ddl_operator.update_single_column(trans, *curr_table_schema, new_table_schema, *new_column_schema))) { diff --git a/src/share/ob_autoincrement_service.cpp b/src/share/ob_autoincrement_service.cpp index 43460580af..16f4c73389 100644 --- a/src/share/ob_autoincrement_service.cpp +++ b/src/share/ob_autoincrement_service.cpp @@ -702,6 +702,66 @@ int ObAutoincrementService::reinit_autoinc_row(const uint64_t &tenant_id, return ret; } +// use for alter table add autoincrement +int ObAutoincrementService::try_lock_autoinc_row(const uint64_t &tenant_id, + const uint64_t &table_id, + const uint64_t &column_id, + const int64_t &autoinc_version, + bool &need_update_inner_table, + common::ObMySQLTransaction &trans) +{ + int ret = OB_SUCCESS; + ObSqlString lock_sql; + need_update_inner_table = false; + SMART_VAR(ObMySQLProxy::MySQLResult, res) { + ObMySQLResult *result = NULL; + if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id + || OB_INVALID_ID == table_id + || 0 == column_id)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("arg is not invalid", KR(ret), K(tenant_id), K(table_id), K(column_id)); + } else if (OB_FAIL(lock_sql.assign_fmt("SELECT truncate_version " + "FROM %s WHERE tenant_id = %lu AND sequence_key = %lu " + "AND column_id = %lu FOR UPDATE", + OB_ALL_AUTO_INCREMENT_TNAME, + ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id), + ObSchemaUtils::get_extract_schema_id(tenant_id, table_id), + column_id))) { + LOG_WARN("failed to assign sql", KR(ret)); + } else if (OB_FAIL(trans.read(res, tenant_id, lock_sql.ptr()))) { + LOG_WARN("failded to execute sql", KR(ret), K(lock_sql)); + } else if (OB_ISNULL(result = res.get_result())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get result, result is NULL", KR(ret)); + } else if (OB_FAIL(result->next())) { + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + LOG_INFO("autoinc row not exist", K(tenant_id), K(table_id), K(column_id)); + } else { + LOG_WARN("iterate next result fail", KR(ret), K(lock_sql)); + } + } else { + int64_t inner_autoinc_version = OB_INVALID_VERSION; + if (OB_FAIL(result->get_int(0l, inner_autoinc_version))) { + LOG_WARN("fail to get truncate_version", KR(ret)); + } else if (inner_autoinc_version > autoinc_version) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("autoincrement's newest version can not less than inner version", + KR(ret), K(tenant_id), K(table_id), K(column_id), + K(inner_autoinc_version), K(autoinc_version)); + } else if (inner_autoinc_version < autoinc_version) { + need_update_inner_table = true; + LOG_INFO("inner autoinc version is old, we need to update inner table", + K(tenant_id), K(table_id), K(column_id), K(inner_autoinc_version), K(autoinc_version)); + } else { + LOG_TRACE("inner autoinc version is equal, not need to update inner table", + K(tenant_id), K(table_id), K(column_id)); + } + } + } + return ret; +} + int ObAutoincrementService::clear_autoinc_cache_all(const uint64_t tenant_id, const uint64_t table_id, const uint64_t column_id, diff --git a/src/share/ob_autoincrement_service.h b/src/share/ob_autoincrement_service.h index 9391f282e4..c0da659c7d 100644 --- a/src/share/ob_autoincrement_service.h +++ b/src/share/ob_autoincrement_service.h @@ -402,6 +402,13 @@ public: const uint64_t &column_id, const int64_t &autoinc_version, common::ObMySQLTransaction &trans); + // for alter table autoinc to recognize old autoincrement value in inner table + int try_lock_autoinc_row(const uint64_t &tenant_id, + const uint64_t &table_id, + const uint64_t &column_id, + const int64_t &autoinc_version, + bool &need_update_inner_table, + common::ObMySQLTransaction &trans); static int calc_next_value(const uint64_t last_next_value, const uint64_t offset, const uint64_t increment,