[FEAT MERGE] log4100 branch

Co-authored-by: tino247 <tino247@126.com>
Co-authored-by: BinChenn <binchenn.bc@gmail.com>
Co-authored-by: HaHaJeff <jeffzhouhhh@gmail.com>
This commit is contained in:
obdev
2023-01-28 18:17:31 +08:00
committed by ob-robot
parent a269ffe6be
commit 50024b39cd
772 changed files with 60275 additions and 11301 deletions

View File

@ -18,9 +18,12 @@
#include "share/config/ob_server_config.h"//GCONF
#include "share/inner_table/ob_inner_table_schema.h"//ALL_TENANT_INFO_TNAME
#include "share/ls/ob_ls_i_life_manager.h"//TODO SCN VALUE
#include "share/ls/ob_ls_recovery_stat_operator.h"//ObLSRecoveryStatOperator
#include "lib/string/ob_sql_string.h"//ObSqlString
#include "lib/mysqlclient/ob_mysql_transaction.h"//ObMySQLTrans
#include "common/ob_timeout_ctx.h"//ObTimeoutCtx
#include "rootserver/ob_root_utils.h"//ObRootUtils
#include "rootserver/ob_rs_event_history_table_operator.h" // ROOTSERVICE_EVENT_ADD
using namespace oceanbase;
using namespace oceanbase::common;
@ -28,66 +31,72 @@ namespace oceanbase
{
namespace share
{
bool is_valid_tenant_scn(
const SCN &sync_scn,
const SCN &replayable_scn,
const SCN &standby_scn,
const SCN &recovery_until_scn)
{
return standby_scn <= replayable_scn && replayable_scn <= sync_scn && sync_scn <= recovery_until_scn;
}
SCN gen_new_sync_scn(const SCN &cur_sync_scn, const SCN &desired_sync_scn, const SCN &cur_recovery_until_scn)
{
return MIN(MAX(cur_sync_scn, desired_sync_scn), cur_recovery_until_scn);
}
SCN gen_new_replayable_scn(const SCN &cur_replayable_scn, const SCN &desired_replayable_scn, const SCN &new_sync_scn)
{
return MIN(MAX(cur_replayable_scn, desired_replayable_scn), new_sync_scn);
}
SCN gen_new_standby_scn(const SCN &cur_standby_scn, const SCN &desired_standby_scn, const SCN &new_replayable_scn)
{
return MIN(MAX(cur_standby_scn, desired_standby_scn), new_replayable_scn);
}
////////////ObAllTenantInfo
bool ObAllTenantInfo::is_valid() const
{
return OB_INVALID_TENANT_ID != tenant_id_
&& sync_scn_.is_valid()
&& (sync_scn_ != SCN::min_scn())
&& replayable_scn_.is_valid()
&& (replayable_scn_ != SCN::min_scn())
&& standby_scn_.is_valid()
&& (standby_scn_ != SCN::min_scn())
&& recovery_until_scn_.is_valid()
&& (recovery_until_scn_ != SCN::min_scn())
&& tenant_role_.is_valid();
}
const SCN ObAllTenantInfo::get_ref_scn() const
{
SCN ref_scn;
if (!sync_scn_.is_valid()) {
LOG_WARN("sync scn is invalid", K(sync_scn_));
} else {
ref_scn = sync_scn_;
}
return ref_scn;
}
int ObAllTenantInfo::init(const uint64_t tenant_id, const ObTenantRole tenant_role)
{
int ret = OB_SUCCESS;
reset();
if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
|| !tenant_role.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(tenant_role));
} else {
tenant_id_ = tenant_id;
tenant_role_ = tenant_role;
switchover_status_ = ObTenantSwitchoverStatus::NORMAL_STATUS;
switchover_epoch_ = 0;
sync_scn_.set_base();
replayable_scn_.set_base();
standby_scn_.set_base();
recovery_until_scn_.set_max();
}
return ret;
&& 0 <= switchover_epoch_
&& sync_scn_.is_valid_and_not_min()
&& replayable_scn_.is_valid_and_not_min()
&& standby_scn_.is_valid_and_not_min()
&& recovery_until_scn_.is_valid_and_not_min()
&& tenant_role_.is_valid()
&& switchover_status_.is_valid()
&& log_mode_.is_valid()
&& is_valid_tenant_scn(sync_scn_, replayable_scn_, standby_scn_, recovery_until_scn_);
}
int ObAllTenantInfo::init(
const uint64_t tenant_id, const ObTenantRole &tenant_role, const ObTenantSwitchoverStatus &switchover_status,
int64_t switchover_epoch, const SCN &sync_scn, const SCN &replayable_scn,
const SCN &standby_scn, const SCN &recovery_until_scn)
const uint64_t tenant_id,
const ObTenantRole &tenant_role,
const ObTenantSwitchoverStatus &switchover_status,
int64_t switchover_epoch,
const SCN &sync_scn,
const SCN &replayable_scn,
const SCN &standby_scn,
const SCN &recovery_until_scn,
const ObArchiveMode &log_mode)
{
int ret = OB_SUCCESS;
reset();
if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
|| !tenant_role.is_valid()
|| !switchover_status.is_valid())) {
|| !switchover_status.is_valid()
|| 0 > switchover_epoch
|| !sync_scn.is_valid_and_not_min()
|| !replayable_scn.is_valid_and_not_min()
|| !standby_scn.is_valid_and_not_min()
|| !recovery_until_scn.is_valid_and_not_min()
|| !log_mode.is_valid()
|| !is_valid_tenant_scn(sync_scn, replayable_scn, standby_scn, recovery_until_scn))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(tenant_role), K(switchover_status));
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(tenant_role), K(switchover_status),
K(switchover_epoch), K(sync_scn), K(replayable_scn), K(standby_scn), K(recovery_until_scn),
K(log_mode));
} else {
tenant_id_ = tenant_id;
tenant_role_ = tenant_role;
@ -97,11 +106,11 @@ int ObAllTenantInfo::init(
replayable_scn_ = replayable_scn;
standby_scn_ = standby_scn;
recovery_until_scn_ = recovery_until_scn;
log_mode_ = log_mode;
}
return ret;
}
int ObAllTenantInfo::assign(const ObAllTenantInfo &other)
{
int ret = OB_SUCCESS;
@ -115,6 +124,7 @@ int ObAllTenantInfo::assign(const ObAllTenantInfo &other)
replayable_scn_ = other.replayable_scn_;
standby_scn_ = other.standby_scn_;
recovery_until_scn_ = other.recovery_until_scn_;
log_mode_ = other.log_mode_;
}
return ret;
}
@ -129,10 +139,11 @@ void ObAllTenantInfo::reset()
replayable_scn_.set_min();
standby_scn_.set_min() ;
recovery_until_scn_.set_min();
log_mode_.reset();
}
OB_SERIALIZE_MEMBER(ObAllTenantInfo, tenant_id_, tenant_role_,
switchover_status_, switchover_epoch_, sync_scn_,
replayable_scn_, standby_scn_, recovery_until_scn_);
replayable_scn_, standby_scn_, recovery_until_scn_, log_mode_);
ObAllTenantInfo& ObAllTenantInfo::operator= (const ObAllTenantInfo &other)
{
@ -150,10 +161,12 @@ int ObAllTenantInfoProxy::init_tenant_info(
const ObAllTenantInfo &tenant_info,
ObISQLClient *proxy)
{
int64_t begin_time = ObTimeUtility::current_time();
int ret = OB_SUCCESS;
const uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_info.get_tenant_id());
ObSqlString sql;
int64_t affected_rows = 0;
ObTimeoutCtx ctx;
if (OB_UNLIKELY(!tenant_info.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant_info is invalid", KR(ret), K(tenant_info));
@ -163,18 +176,22 @@ int ObAllTenantInfoProxy::init_tenant_info(
} else if (!is_user_tenant(tenant_info.get_tenant_id())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("meta tenant no need init tenant info", KR(ret), K(tenant_info));
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"insert into %s (tenant_id, tenant_role, "
"switchover_status, switchover_epoch, "
"sync_scn, replayable_scn, readable_scn) "
"values(%lu, '%s', '%s', %ld, %lu, %lu, %lu)",
"sync_scn, replayable_scn, readable_scn, recovery_until_scn, log_mode) "
"values(%lu, '%s', '%s', %ld, %lu, %lu, %lu, %lu, '%s')",
OB_ALL_TENANT_INFO_TNAME, tenant_info.get_tenant_id(),
tenant_info.get_tenant_role().to_str(),
tenant_info.get_switchover_status().to_str(),
tenant_info.get_switchover_epoch(),
tenant_info.get_sync_scn().get_val_for_inner_table_field(),
tenant_info.get_replayable_scn().get_val_for_inner_table_field(),
tenant_info.get_standby_scn().get_val_for_inner_table_field()))) {
tenant_info.get_standby_scn().get_val_for_inner_table_field(),
tenant_info.get_recovery_until_scn().get_val_for_inner_table_field(),
tenant_info.get_log_mode().to_str()))) {
LOG_WARN("failed to assign sql", KR(ret), K(tenant_info), K(sql));
} else if (OB_FAIL(proxy->write(exec_tenant_id, sql.ptr(), affected_rows))) {
LOG_WARN("failed to execute sql", KR(ret), K(exec_tenant_id), K(sql));
@ -182,6 +199,11 @@ int ObAllTenantInfoProxy::init_tenant_info(
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect updating one row", KR(ret), K(affected_rows), K(sql));
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
ROOTSERVICE_EVENT_ADD("tenant_info", "init_tenant_info", K(ret),
K(tenant_info), K(affected_rows), K(cost));
return ret;
}
@ -258,6 +280,7 @@ int ObAllTenantInfoProxy::load_tenant_info(const uint64_t tenant_id,
{
int ret = OB_SUCCESS;
tenant_info.reset();
ObTimeoutCtx ctx;
if (OB_ISNULL(proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("proxy is null", KR(ret), KP(proxy));
@ -272,7 +295,9 @@ int ObAllTenantInfoProxy::load_tenant_info(const uint64_t tenant_id,
} else {
ObSqlString sql;
uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_id);
if (OB_FAIL(sql.assign_fmt("select * from %s where tenant_id = %lu ",
if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt("select * from %s where tenant_id = %lu ",
OB_ALL_TENANT_INFO_TNAME, tenant_id))) {
LOG_WARN("failed to assign sql", KR(ret), K(sql));
} else if(for_update && OB_FAIL(sql.append(" for update"))) {
@ -307,6 +332,7 @@ int ObAllTenantInfoProxy::update_tenant_recovery_status(
int64_t affected_rows = 0;
common::ObMySQLTransaction trans;
ObAllTenantInfo old_tenant_info;
ObTimeoutCtx ctx;
if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id ||
!status.is_valid())) {
ret = OB_INVALID_ARGUMENT;
@ -322,25 +348,24 @@ int ObAllTenantInfoProxy::update_tenant_recovery_status(
} else if (OB_FAIL(load_tenant_info(tenant_id, &trans, true, old_tenant_info))) {
LOG_WARN("failed to load all tenant info", KR(ret), K(tenant_id));
} else {
const SCN new_sync_scn = old_tenant_info.get_sync_scn() > sync_scn ? old_tenant_info.get_sync_scn() : sync_scn;
SCN new_replay_scn_tmp = old_tenant_info.get_replayable_scn() > replay_scn ? old_tenant_info.get_replayable_scn() : replay_scn;
SCN new_replay_scn = new_replay_scn_tmp < new_sync_scn ? new_replay_scn_tmp : new_sync_scn;
SCN new_sts_tmp = old_tenant_info.get_standby_scn() > readable_scn ? old_tenant_info.get_standby_scn() : readable_scn;
SCN new_sts = new_sts_tmp < new_replay_scn ? new_sts_tmp : new_replay_scn;
SCN new_sync_scn = gen_new_sync_scn(old_tenant_info.get_sync_scn(), sync_scn, old_tenant_info.get_recovery_until_scn());
SCN new_replay_scn = gen_new_replayable_scn(old_tenant_info.get_replayable_scn(), replay_scn, new_sync_scn);
SCN new_scn = gen_new_standby_scn(old_tenant_info.get_standby_scn(), readable_scn, new_replay_scn);
if (old_tenant_info.get_sync_scn() == new_sync_scn
&& old_tenant_info.get_replayable_scn() == new_replay_scn
&& old_tenant_info.get_standby_scn() == new_sts) {
LOG_DEBUG("no need update", K(old_tenant_info), K(new_sync_scn), K(new_replay_scn), K(new_sts));
&& old_tenant_info.get_standby_scn() == new_scn) {
LOG_DEBUG("no need update", K(old_tenant_info), K(new_sync_scn), K(new_replay_scn), K(new_scn));
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"update %s set sync_scn = %lu, replayable_scn = %lu, "
"readable_scn = %lu where tenant_id = %lu "
"and switchover_status = '%s'", OB_ALL_TENANT_INFO_TNAME,
"update %s set sync_scn = %ld, replayable_scn = %ld, "
"readable_scn = %ld where tenant_id = %lu "
"and switchover_status = '%s' and readable_scn <= replayable_scn and "
"replayable_scn <= sync_scn and sync_scn <= recovery_until_scn", OB_ALL_TENANT_INFO_TNAME,
new_sync_scn.get_val_for_inner_table_field(),
new_replay_scn.get_val_for_inner_table_field(),
new_sts.get_val_for_inner_table_field(),
new_scn.get_val_for_inner_table_field(),
tenant_id, status.to_str()))) {
LOG_WARN("failed to assign sql", KR(ret), K(tenant_id), K(status),
K(sql));
@ -373,38 +398,47 @@ int ObAllTenantInfoProxy::fill_cell(common::sqlclient::ObMySQLResult *result, Ob
ObString status_str;
uint64_t tenant_id = OB_INVALID_TENANT_ID;
int64_t switchover_epoch = OB_INVALID_TIMESTAMP;
int64_t sync_ts = OB_INVALID_SCN_VAL;
int64_t replay_ts = OB_INVALID_SCN_VAL;
int64_t sts = OB_INVALID_SCN_VAL;
uint64_t sync_scn_val = OB_INVALID_SCN_VAL;
uint64_t replay_scn_val = OB_INVALID_SCN_VAL;
uint64_t sts_scn_val = OB_INVALID_SCN_VAL;
uint64_t recovery_until_scn_val = OB_INVALID_SCN_VAL;
ObString log_mode_str;
ObString log_mode_default_value("NOARCHIVELOG");
SCN sync_scn;
SCN replay_scn;
SCN sts_scn;
SCN recovery_scn;
recovery_scn.set_base();
SCN recovery_until_scn;
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "tenant_role", tenant_role_str);
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "switchover_status", status_str);
EXTRACT_INT_FIELD_MYSQL(*result, "tenant_id", tenant_id, uint64_t);
EXTRACT_INT_FIELD_MYSQL(*result, "switchover_epoch", switchover_epoch, int64_t);
EXTRACT_UINT_FIELD_MYSQL(*result, "sync_scn", sync_ts, int64_t);
EXTRACT_UINT_FIELD_MYSQL(*result, "replayable_scn", replay_ts, int64_t);
EXTRACT_UINT_FIELD_MYSQL(*result, "readable_scn", sts, int64_t);
EXTRACT_UINT_FIELD_MYSQL(*result, "sync_scn", sync_scn_val, uint64_t);
EXTRACT_UINT_FIELD_MYSQL(*result, "replayable_scn", replay_scn_val, uint64_t);
EXTRACT_UINT_FIELD_MYSQL(*result, "readable_scn", sts_scn_val, uint64_t);
EXTRACT_UINT_FIELD_MYSQL_WITH_DEFAULT_VALUE(*result, "recovery_until_scn", recovery_until_scn_val, uint64_t, false /* skip_null_error */, true /* skip_column_error */, OB_MAX_SCN_TS_NS);
EXTRACT_VARCHAR_FIELD_MYSQL_WITH_DEFAULT_VALUE(*result, "log_mode", log_mode_str,
false /* skip_null_error */, true /* skip_column_error */, log_mode_default_value);
ObTenantRole tmp_tenant_role(tenant_role_str);
ObTenantSwitchoverStatus tmp_tenant_sw_status(status_str);
ObArchiveMode tmp_log_mode(log_mode_str);
if (OB_FAIL(ret)) {
LOG_WARN("failed to get result", KR(ret));
//tenant_id in inner table can be used directly
} else if (OB_FAIL(sync_scn.convert_for_inner_table_field(sync_ts))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(sync_ts));
} else if (OB_FAIL(replay_scn.convert_for_inner_table_field(replay_ts))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(replay_ts));
} else if (OB_FAIL(sts_scn.convert_for_inner_table_field(sts))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(sts));
} else if (OB_FAIL(sync_scn.convert_for_inner_table_field(sync_scn_val))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(sync_scn_val));
} else if (OB_FAIL(replay_scn.convert_for_inner_table_field(replay_scn_val))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(replay_scn_val));
} else if (OB_FAIL(sts_scn.convert_for_inner_table_field(sts_scn_val))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(sts_scn_val));
} else if (OB_FAIL(recovery_until_scn.convert_for_inner_table_field(recovery_until_scn_val))) {
LOG_WARN("failed to convert_for_inner_table_field", KR(ret), K(recovery_until_scn_val));
} else if (OB_FAIL(tenant_info.init(
tenant_id, tmp_tenant_role,
tmp_tenant_sw_status, switchover_epoch,
sync_scn, replay_scn, sts_scn, recovery_scn))) {
sync_scn, replay_scn, sts_scn, recovery_until_scn, tmp_log_mode))) {
LOG_WARN("failed to init tenant info", KR(ret), K(tenant_id), K(tmp_tenant_role), K(tenant_role_str),
K(tmp_tenant_sw_status), K(status_str), K(switchover_epoch), K(sync_ts));
K(tmp_tenant_sw_status), K(status_str), K(switchover_epoch), K(sync_scn), K(recovery_until_scn),
K(log_mode_str), K(tmp_log_mode));
}
}
return ret;
@ -414,40 +448,60 @@ int ObAllTenantInfoProxy::update_tenant_role(
const uint64_t tenant_id,
ObISQLClient *proxy,
int64_t old_switchover_epoch,
const ObTenantRole &new_role, const ObTenantSwitchoverStatus &status,
const ObTenantRole &new_role,
const ObTenantSwitchoverStatus &old_status,
const ObTenantSwitchoverStatus &new_status,
int64_t &new_switchover_ts)
{
int64_t begin_time = ObTimeUtility::current_time();
int ret = OB_SUCCESS;
const uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_id);
ObSqlString sql;
int64_t affected_rows = 0;
//update switchover epoch while role change
new_switchover_ts = max(old_switchover_epoch + 1, ObTimeUtility::current_time());
if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
|| OB_INVALID_VERSION == new_switchover_ts
|| !new_role.is_valid())) {
ObTimeoutCtx ctx;
if (OB_UNLIKELY(!is_user_tenant(tenant_id)
|| OB_INVALID_VERSION == old_switchover_epoch
|| !new_role.is_valid()
|| !old_status.is_valid()
|| !new_status.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant_info is invalid", KR(ret), K(tenant_id), K(old_switchover_epoch), K(new_role));
LOG_WARN("tenant_info is invalid", KR(ret), K(tenant_id), K(old_switchover_epoch), K(old_status),
K(new_role), K(new_status));
} else if (OB_ISNULL(proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("proxy is null", KR(ret), KP(proxy));
} else if (OB_FAIL(get_new_switchover_epoch_(old_switchover_epoch, old_status, new_status,
new_switchover_ts))) {
LOG_WARN("fail to get_new_switchover_epoch_", KR(ret), K(old_switchover_epoch), K(old_status),
K(new_status));
} else if (OB_UNLIKELY(OB_INVALID_VERSION == new_switchover_ts)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new_switchover_ts is invalid", KR(ret), K(new_switchover_ts),
K(old_switchover_epoch), K(old_status), K(new_status));
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"update %s set tenant_role = '%s', switchover_status = '%s', switchover_epoch = %ld "
"where tenant_id = %lu and switchover_epoch = %ld",
"where tenant_id = %lu and switchover_epoch = %ld and switchover_status = '%s'",
OB_ALL_TENANT_INFO_TNAME,
new_role.to_str(), status.to_str(),
new_switchover_ts, tenant_id, old_switchover_epoch))) {
new_role.to_str(), new_status.to_str(),
new_switchover_ts, tenant_id, old_switchover_epoch, old_status.to_str()))) {
LOG_WARN("failed to assign sql", KR(ret), K(tenant_id), K(old_switchover_epoch),
K(new_role), K(sql));
K(new_role), K(old_status), K(sql));
} else if (OB_FAIL(proxy->write(exec_tenant_id, sql.ptr(), affected_rows))) {
LOG_WARN("failed to execute sql", KR(ret), K(exec_tenant_id), K(sql));
} else if (0 == affected_rows) {
ret = OB_NEED_RETRY;
LOG_WARN("switchover may concurrency, need retry", KR(ret), K(old_switchover_epoch));
LOG_WARN("switchover may concurrency, need retry", KR(ret), K(old_switchover_epoch), K(sql));
} else if (!is_single_row(affected_rows)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect updating one row", KR(ret), K(affected_rows), K(sql));
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
ROOTSERVICE_EVENT_ADD("tenant_info", "update_tenant_role", K(ret), K(tenant_id),
K(new_status), K(new_switchover_ts), K(old_status), K(cost));
return ret;
}
@ -457,10 +511,13 @@ int ObAllTenantInfoProxy::update_tenant_switchover_status(
int64_t switchover_epoch,
const ObTenantSwitchoverStatus &old_status, const ObTenantSwitchoverStatus &status)
{
int64_t begin_time = ObTimeUtility::current_time();
int ret = OB_SUCCESS;
const uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_id);
ObSqlString sql;
int64_t affected_rows = 0;
ObTimeoutCtx ctx;
//update switchover epoch while role change
if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id
|| OB_INVALID_VERSION == switchover_epoch
@ -471,6 +528,8 @@ int ObAllTenantInfoProxy::update_tenant_switchover_status(
} else if (OB_ISNULL(proxy)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("proxy is null", KR(ret), KP(proxy));
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"update %s set switchover_status = '%s'"
"where tenant_id = %lu and switchover_epoch = %ld and switchover_status = '%s'",
@ -488,6 +547,225 @@ int ObAllTenantInfoProxy::update_tenant_switchover_status(
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect updating one row", KR(ret), K(affected_rows), K(sql));
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
ROOTSERVICE_EVENT_ADD("tenant_info", "update_tenant_switchover_status", K(ret), K(tenant_id),
K(status), K(switchover_epoch), K(old_status), K(cost));
return ret;
}
int ObAllTenantInfoProxy::update_tenant_recovery_until_scn(
const uint64_t tenant_id,
common::ObMySQLTransaction &trans,
const int64_t switchover_epoch,
const SCN &recovery_until_scn)
{
DEBUG_SYNC(BEFORE_UPDATE_RECOVERY_UNTIL_SCN);
int64_t begin_time = ObTimeUtility::current_time();
int ret = OB_SUCCESS;
const uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_id);
ObSqlString sql;
int64_t affected_rows = 0;
ObTimeoutCtx ctx;
ObLSRecoveryStatOperator ls_recovery_operator;
ObLSRecoveryStat sys_ls_recovery;
if (!is_user_tenant(tenant_id) || OB_INVALID_VERSION == switchover_epoch) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(switchover_epoch));
} else if (OB_UNLIKELY(!recovery_until_scn.is_valid_and_not_min())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("recovery_until_scn invalid", KR(ret), K(recovery_until_scn));
} else if (OB_FAIL(ls_recovery_operator.get_ls_recovery_stat(tenant_id, share::SYS_LS,
true /*for_update*/, sys_ls_recovery, trans))) {
LOG_WARN("failed to get ls recovery stat", KR(ret), K(tenant_id));
} else if (recovery_until_scn < sys_ls_recovery.get_sync_scn()) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("recover before SYS LS sync_scn is not allowed", KR(ret), K(tenant_id), K(recovery_until_scn), K(sys_ls_recovery));
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "recover before SYS LS sync_scn is");
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"update %s set recovery_until_scn = %lu where tenant_id = %lu and sync_scn <= %lu and switchover_epoch = %ld",
OB_ALL_TENANT_INFO_TNAME, recovery_until_scn.get_val_for_inner_table_field(), tenant_id,
recovery_until_scn.get_val_for_inner_table_field(), switchover_epoch))) {
LOG_WARN("failed to assign sql", KR(ret), K(tenant_id), K(recovery_until_scn), K(sql));
} else if (OB_FAIL(trans.write(exec_tenant_id, sql.ptr(), affected_rows))) {
LOG_WARN("failed to execute sql", KR(ret), K(exec_tenant_id), K(sql));
} else if (0 == affected_rows) {
ret = OB_OP_NOT_ALLOW;
LOG_WARN("state changed, check sync_scn and switchover status", KR(ret), K(tenant_id),
K(switchover_epoch), K(recovery_until_scn), K(sql));
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "state changed, check sync_scn and switchover status, recover is");
} else if (!is_single_row(affected_rows)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect updating one row", KR(ret), K(affected_rows), K(sql));
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
LOG_INFO("update_recovery_until_scn finish", KR(ret), K(tenant_id), K(sys_ls_recovery),
K(recovery_until_scn), K(affected_rows), K(switchover_epoch), K(sql), K(cost));
ROOTSERVICE_EVENT_ADD("tenant_info", "update_recovery_until_scn", K(ret), K(tenant_id),
K(recovery_until_scn), K(affected_rows), K(switchover_epoch), K(sys_ls_recovery));
return ret;
}
int ObAllTenantInfoProxy::update_tenant_status(
const uint64_t tenant_id,
ObISQLClient *proxy,
const ObTenantRole new_role,
const ObTenantSwitchoverStatus &old_status,
const ObTenantSwitchoverStatus &new_status,
const share::SCN &sync_scn,
const share::SCN &replayable_scn,
const share::SCN &readable_scn,
const share::SCN &recovery_until_scn,
const int64_t old_switchover_epoch)
{
int64_t begin_time = ObTimeUtility::current_time();
int ret = OB_SUCCESS;
const uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_id);
ObSqlString sql;
int64_t affected_rows = 0;
ObTimeoutCtx ctx;
int64_t new_switchover_epoch = OB_INVALID_VERSION;
if (OB_UNLIKELY(OB_ISNULL(proxy)
|| !is_user_tenant(tenant_id)
|| !new_role.is_valid()
|| !old_status.is_valid()
|| !new_status.is_valid()
|| old_status == new_status
|| !sync_scn.is_valid_and_not_min()
|| !replayable_scn.is_valid_and_not_min()
|| !readable_scn.is_valid_and_not_min()
|| !recovery_until_scn.is_valid_and_not_min()
|| OB_INVALID_VERSION == old_switchover_epoch)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("tenant_info is invalid", KR(ret), KP(proxy), K(tenant_id), K(new_role), K(old_status),
K(new_status), K(sync_scn), K(replayable_scn), K(readable_scn), K(recovery_until_scn),
K(old_switchover_epoch));
} else if (OB_FAIL(get_new_switchover_epoch_(old_switchover_epoch, old_status, new_status,
new_switchover_epoch))) {
LOG_WARN("fail to get_new_switchover_epoch_", KR(ret), K(old_switchover_epoch), K(old_status),
K(new_status));
} else if (OB_UNLIKELY(OB_INVALID_VERSION == new_switchover_epoch)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new_switchover_ts is invalid", KR(ret), K(new_switchover_epoch),
K(old_switchover_epoch), K(old_status), K(new_status));
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"update %s set tenant_role = '%s', switchover_status = '%s', "
"switchover_epoch = %ld, sync_scn = %lu, replayable_scn = %lu, "
"readable_scn = %lu, recovery_until_scn = %lu where tenant_id = %lu "
"and switchover_status = '%s' and switchover_epoch = %ld "
"and readable_scn <= replayable_scn and replayable_scn <= sync_scn and sync_scn <= recovery_until_scn "
"and sync_scn <= %lu and replayable_scn <= %lu and readable_scn <= %lu ",
OB_ALL_TENANT_INFO_TNAME, new_role.to_str(), new_status.to_str(),
new_switchover_epoch,
sync_scn.get_val_for_inner_table_field(),
replayable_scn.get_val_for_inner_table_field(),
readable_scn.get_val_for_inner_table_field(),
recovery_until_scn.get_val_for_inner_table_field(),
tenant_id, old_status.to_str(), old_switchover_epoch,
sync_scn.get_val_for_inner_table_field(),
replayable_scn.get_val_for_inner_table_field(),
readable_scn.get_val_for_inner_table_field()))) {
LOG_WARN("failed to assign sql", KR(ret), K(tenant_id), K(sql));
} else if (OB_FAIL(proxy->write(exec_tenant_id, sql.ptr(), affected_rows))) {
LOG_WARN("failed to execute sql", KR(ret), K(exec_tenant_id), K(sql));
} else if (0 == affected_rows) {
ret = OB_NEED_RETRY;
LOG_WARN("switchover may concurrency, need retry", KR(ret), K(old_switchover_epoch), K(sql));
} else if (!is_single_row(affected_rows)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect updating one row", KR(ret), K(affected_rows), K(sql));
}
ObAllTenantInfo tenant_info;
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = tenant_info.init(tenant_id,
new_role,
new_status,
new_switchover_epoch,
sync_scn,
replayable_scn,
readable_scn,
recovery_until_scn))) {
LOG_WARN("failed to init tenant_info", KR(ret), KR(tmp_ret), K(tenant_id), K(new_role),
K(new_status), K(new_switchover_epoch), K(sync_scn),
K(replayable_scn), K(readable_scn), K(recovery_until_scn));
ret = OB_SUCC(ret) ? tmp_ret : ret;
}
int64_t cost = ObTimeUtility::current_time() - begin_time;
ROOTSERVICE_EVENT_ADD("tenant_info", "update_tenant_role", K(ret), K(tenant_id),
K(tenant_info), K(old_status), K(old_switchover_epoch), K(cost));
return ret;
}
int ObAllTenantInfoProxy::get_new_switchover_epoch_(
const int64_t old_switchover_epoch,
const ObTenantSwitchoverStatus &old_status,
const ObTenantSwitchoverStatus &new_status,
int64_t &new_switchover_epoch)
{
int ret = OB_SUCCESS;
new_switchover_epoch = OB_INVALID_VERSION;
//update switchover epoch when entering and leaving normal switchover status
if (OB_UNLIKELY(OB_INVALID_VERSION == old_switchover_epoch
|| !old_status.is_valid()
|| !new_status.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(old_switchover_epoch), K(old_status), K(new_status));
} else if ((share::NORMAL_SWITCHOVER_STATUS == new_status
|| share::NORMAL_SWITCHOVER_STATUS == old_status) && (old_status != new_status)) {
new_switchover_epoch = max(old_switchover_epoch + 1, ObTimeUtility::current_time());
} else {
new_switchover_epoch = old_switchover_epoch;
}
return ret;
}
int ObAllTenantInfoProxy::update_tenant_log_mode(
const uint64_t tenant_id,
ObISQLClient *proxy,
const ObArchiveMode &old_log_mode,
const ObArchiveMode &new_log_mode)
{
int ret = OB_SUCCESS;
const uint64_t exec_tenant_id = gen_meta_tenant_id(tenant_id);
ObSqlString sql;
int64_t affected_rows = 0;
ObTimeoutCtx ctx;
if (OB_UNLIKELY(!is_user_tenant(tenant_id)
|| !old_log_mode.is_valid()
|| !new_log_mode.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(old_log_mode), K(new_log_mode));
} else if (OB_FAIL(rootserver::ObRootUtils::get_rs_default_timeout_ctx(ctx))) {
LOG_WARN("fail to get timeout ctx", KR(ret), K(ctx));
} else if (OB_FAIL(sql.assign_fmt(
"update %s set log_mode = '%s' where tenant_id = %lu and switchover_status = '%s' "
"and log_mode = '%s' ",
OB_ALL_TENANT_INFO_TNAME, new_log_mode.to_str(), tenant_id,
NORMAL_SWITCHOVER_STATUS.to_str(), old_log_mode.to_str()))) {
LOG_WARN("failed to assign sql", KR(ret), K(tenant_id), K(old_log_mode), K(new_log_mode), K(sql));
} else if (OB_FAIL(proxy->write(exec_tenant_id, sql.ptr(), affected_rows))) {
LOG_WARN("failed to execute sql", KR(ret), K(exec_tenant_id), K(sql));
} else if (0 == affected_rows) {
ret = OB_NEED_RETRY;
LOG_WARN("may concurrency with switchover, need retry", KR(ret), K(tenant_id), K(sql));
} else if (!is_single_row(affected_rows)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect updating one row", KR(ret), K(affected_rows), K(sql));
}
return ret;
}