fix -4016 error and add TENANT_ID in CDB_OB_DEADLOCK_EVENT_HISTORY

This commit is contained in:
obdev 2023-02-10 10:13:46 +00:00 committed by ob-robot
parent 3648a21c43
commit 8c5ebeee3c
4 changed files with 222 additions and 88 deletions

View File

@ -402,7 +402,8 @@ int LsElectionReferenceInfoRow::get_row_from_table_()
LC_TIME_GUARD(1_s);
#define PRINT_WRAPPER KR(ret), K(*this)
int ret = OB_SUCCESS;
const char *columns[5] = { "tenant_id", "ls_id", "zone_priority", "manual_leader_server", "blacklist" };
constexpr int64_t culumn_size = 5;
const char *columns[culumn_size] = { "tenant_id", "ls_id", "zone_priority", "manual_leader_server", "blacklist" };
char buffer[STACK_BUFFER_SIZE] = {0};
int64_t pos = 0;
if (CLICK_FAIL(databuff_printf(buffer, STACK_BUFFER_SIZE, pos, "where tenant_id=%ld and ls_id=%ld for update", tenant_id_, ls_id_.id()))) {
@ -412,8 +413,10 @@ int LsElectionReferenceInfoRow::get_row_from_table_()
COORDINATOR_LOG_(WARN, "transaction is not started yet");
} else {
HEAP_VAR(ObMySQLProxy::MySQLResult, res) {
common::sqlclient::ObMySQLResult *result = ObTableAccessHelper::get_my_sql_result_(columns, share::OB_ALL_LS_ELECTION_REFERENCE_INFO_TNAME, buffer, trans_, exec_tenant_id_, res);
if (OB_NOT_NULL(result)) {
common::sqlclient::ObMySQLResult *result = nullptr;
if (OB_FAIL(ObTableAccessHelper::get_my_sql_result_(columns, culumn_size, share::OB_ALL_LS_ELECTION_REFERENCE_INFO_TNAME, buffer, trans_, exec_tenant_id_, res, result))) {
COORDINATOR_LOG_(WARN, "fail to get mysql result");
} else if (OB_NOT_NULL(result)) {
int64_t iter_times = 0;
while (OB_SUCC(ret) && OB_SUCC(result->next())) {
if (++iter_times > 1) {

View File

@ -2360,7 +2360,7 @@ int ObInnerTableSchema::cdb_ob_deadlock_event_history_schema(ObTableSchema &tabl
table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT EVENT_ID, SVR_IP, SVR_PORT, DETECTOR_ID, REPORT_TIME, CYCLE_IDX, CYCLE_SIZE, ROLE, PRIORITY_LEVEL, PRIORITY, CREATE_TIME, START_DELAY AS START_DELAY_US, MODULE, VISITOR, OBJECT, EXTRA_NAME1, EXTRA_VALUE1, EXTRA_NAME2, EXTRA_VALUE2, EXTRA_NAME3, EXTRA_VALUE3 FROM OCEANBASE.__ALL_VIRTUAL_DEADLOCK_EVENT_HISTORY )__"))) {
if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID, EVENT_ID, SVR_IP, SVR_PORT, DETECTOR_ID, REPORT_TIME, CYCLE_IDX, CYCLE_SIZE, ROLE, PRIORITY_LEVEL, PRIORITY, CREATE_TIME, START_DELAY AS START_DELAY_US, MODULE, VISITOR, OBJECT, EXTRA_NAME1, EXTRA_VALUE1, EXTRA_NAME2, EXTRA_VALUE2, EXTRA_NAME3, EXTRA_VALUE3 FROM OCEANBASE.__ALL_VIRTUAL_DEADLOCK_EVENT_HISTORY )__"))) {
LOG_ERROR("fail to set view_definition", K(ret));
}
}

View File

@ -23257,7 +23257,8 @@ def_table_schema(
normal_columns = [],
view_definition =
"""
SELECT EVENT_ID,
SELECT TENANT_ID,
EVENT_ID,
SVR_IP,
SVR_PORT,
DETECTOR_ID,

View File

@ -39,6 +39,13 @@
namespace oceanbase
{
namespace logservice
{
namespace coordinator
{
class LsElectionReferenceInfoRow;
}
}
namespace common
{
@ -46,6 +53,7 @@ constexpr int STACK_BUFFER_SIZE = 512;
#define OB_LOG_(args...) OB_LOG(args, PRINT_WRAPPER)
class ObTableAccessHelper
{
friend class logservice::coordinator::LsElectionReferenceInfoRow;
public:
static int split_string_by_char(const ObStringHolder &arg_str, const char character, ObIArray<ObStringHolder> &result)
{
@ -147,36 +155,40 @@ public:
const ObString &where_condition,
T &...values)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(columns), K(table), K(where_condition)
static_assert(N > 0, "columns size must greater than 0");
static_assert(sizeof...(T) == N, "number of value size must equal than N");
int ret = common::OB_SUCCESS;
if (OB_ISNULL(GCTX.sql_proxy_)) {
OB_LOG_(WARN, "GCTX.sql_proxy_ is null");
return read_and_convert_to_values_(tenant_id,
columns,
N,
table,
where_condition,
values...);
}
template <typename ...T>
static int read_single_row(const uint64_t tenant_id,
const std::initializer_list<const char *> &columns,
const ObString &table,
const ObString &where_condition,
T &...values)
{
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(table), K(where_condition)
int ret = OB_SUCCESS;
if (columns.size() != sizeof...(T)) {
ret = OB_SIZE_OVERFLOW;
OB_LOG_(WARN, "sizeof... values should equal to columns size");
} else {
HEAP_VAR(ObMySQLProxy::MySQLResult, res) {
common::sqlclient::ObMySQLResult *result = get_my_sql_result_(columns, table, where_condition, *GCTX.sql_proxy_, tenant_id, res);
if (OB_NOT_NULL(result)) {
int64_t iter_times = 0;
while (OB_SUCC(ret) && OB_SUCC(result->next())) {
if (++iter_times > 1) {
ret = OB_ERR_MORE_THAN_ONE_ROW;
OB_LOG_(WARN, "there are more than one row been selected");
break;
} else if (CLICK_FAIL(get_values_from_row_<0>(result, columns, values...))) {
OB_LOG_(WARN, "failed to get column from row");
}
}
if (OB_ITER_END == ret && 1 == iter_times) {
ret = OB_SUCCESS;
} else {
OB_LOG_(WARN, "iter failed", K(iter_times));
}
} else {
ret = OB_ERR_UNEXPECTED;
OB_LOG_(WARN, "get mysql result failed");
}
const char * columns_array[columns.size()];
auto iter = std::begin(columns);
for (int64_t idx = 0; iter != std::end(columns); ++idx && ++iter) {
columns_array[idx] = *iter;
}
if (OB_FAIL(read_and_convert_to_values_(tenant_id,
columns_array,
columns.size(),
table,
where_condition,
values...))) {
OB_LOG_(WARN, "fail to read and convert to values");
}
}
return ret;
@ -190,36 +202,40 @@ public:
const ObString &condition,
common::ObIArray<ObTuple<T...>> &output_array)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(columns), K(table), K(condition)
static_assert(N > 0, "columns size must greater than 0");
static_assert(sizeof...(T) == N, "number of value size must equal than N");
int ret = common::OB_SUCCESS;
if (OB_ISNULL(GCTX.sql_proxy_)) {
OB_LOG_(WARN, "GCTX.sql_proxy_ is null");
return read_and_convert_to_tuples_(tenant_id,
columns,
N,
table,
condition,
output_array);
}
template <int N, typename ...T>
static int read_multi_row(const uint64_t tenant_id,
const std::initializer_list<const char *> &columns,
const ObString &table,
const ObString &condition,
common::ObIArray<ObTuple<T...>> &output_array)
{
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(table), K(condition)
int ret = OB_SUCCESS;
if (columns.size() != sizeof...(T)) {
ret = OB_SIZE_OVERFLOW;
OB_LOG_(WARN, "sizeof... values should equal to columns size");
} else {
HEAP_VAR(ObMySQLProxy::MySQLResult, res) {
common::sqlclient::ObMySQLResult *result = get_my_sql_result_(columns, table, condition, *GCTX.sql_proxy_, tenant_id, res);
if (OB_NOT_NULL(result)) {
int64_t iter_times = 0;
while (OB_SUCC(ret) && OB_SUCC(result->next())) {
if (CLICK_FAIL(output_array.push_back(ObTuple<T...>()))) {
OB_LOG_(WARN, "push new tuple to array failed", K(iter_times));
} else if (OB_SUCCESS != (ret = AccessHelper<sizeof...(T) - 1, N, T...>::
get_values_to_tuple_from_row(result, columns, output_array.at(iter_times)))) {
OB_LOG_(WARN, "failed to get values from row", K(iter_times));
}
iter_times++;
}
if (OB_ITER_END == ret && iter_times > 0) {
ret = OB_SUCCESS;
} else {
OB_LOG_(WARN, "iter failed", K(iter_times));
}
} else {
ret = OB_ERR_UNEXPECTED;
OB_LOG_(WARN, "get mysql result failed");
}
const char * columns_array[columns.size()];
auto iter = std::begin(columns);
for (int64_t idx = 0; iter != std::end(columns); ++idx && ++iter) {
columns_array[idx] = *iter;
}
if (OB_FAIL(read_and_convert_to_tuples_(tenant_id,
columns_array,
columns.size(),
table,
condition,
output_array))) {
OB_LOG_(WARN, "fail to read and convert to tuples");
}
}
return ret;
@ -295,24 +311,110 @@ public:
return ret;
#undef PRINT_WRAPPER
}
public:
template <int N>
static common::sqlclient::ObMySQLResult *get_my_sql_result_(const char* (&columns)[N],
const ObString &table,
const ObString &condition,
ObISQLClient &proxy,
const uint64_t tenant_id,
ObMySQLProxy::MySQLResult &res)
private:
template <typename ...T>
static int read_and_convert_to_values_(const uint64_t tenant_id,
const char **columns,
const int64_t culumn_size,
const ObString &table,
const ObString &condition,
T &...values)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(table), K(condition)
int ret = common::OB_SUCCESS;
if (OB_ISNULL(GCTX.sql_proxy_)) {
OB_LOG_(WARN, "GCTX.sql_proxy_ is null");
} else {
HEAP_VAR(ObMySQLProxy::MySQLResult, res) {
common::sqlclient::ObMySQLResult *result = nullptr;
if (OB_FAIL(get_my_sql_result_(columns, culumn_size, table, condition, *GCTX.sql_proxy_, tenant_id, res, result))) {
OB_LOG_(WARN, "fail to get ObMySQLResult");
} else if (OB_NOT_NULL(result)) {
int64_t iter_times = 0;
while (OB_SUCC(ret) && OB_SUCC(result->next())) {
if (++iter_times > 1) {
ret = OB_ERR_MORE_THAN_ONE_ROW;
OB_LOG_(WARN, "there are more than one row been selected");
break;
} else if (CLICK_FAIL(get_values_from_row_<0>(result, columns, values...))) {
OB_LOG_(WARN, "failed to get column from row");
}
}
if (OB_ITER_END == ret && 1 == iter_times) {
ret = OB_SUCCESS;
} else {
OB_LOG_(WARN, "iter failed", K(iter_times));
}
} else {
ret = OB_ERR_UNEXPECTED;
OB_LOG_(WARN, "get mysql result failed");
}
}
}
return ret;
#undef PRINT_WRAPPER
}
template <typename ...T>
static int read_and_convert_to_tuples_(const uint64_t tenant_id,
const char **columns,
const int64_t culumn_size,
const ObString &table,
const ObString &condition,
common::ObIArray<ObTuple<T...>> &output_array)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(table), K(condition)
int ret = common::OB_SUCCESS;
if (OB_ISNULL(GCTX.sql_proxy_)) {
OB_LOG_(WARN, "GCTX.sql_proxy_ is null");
} else {
HEAP_VAR(ObMySQLProxy::MySQLResult, res) {
common::sqlclient::ObMySQLResult *result = nullptr;
if (OB_FAIL(get_my_sql_result_(columns, culumn_size, table, condition, *GCTX.sql_proxy_, tenant_id, res, result))) {
OB_LOG_(WARN, "fail to get ObMySQLResult");
} else if (OB_NOT_NULL(result)) {
int64_t iter_times = 0;
while (OB_SUCC(ret) && OB_SUCC(result->next())) {
if (CLICK_FAIL(output_array.push_back(ObTuple<T...>()))) {
OB_LOG_(WARN, "push new tuple to array failed", K(iter_times));
} else if (OB_SUCCESS != (ret = AccessHelper<sizeof...(T) - 1, T...>::
get_values_to_tuple_from_row(result, columns, output_array.at(iter_times)))) {
OB_LOG_(WARN, "failed to get values from row", K(iter_times));
}
iter_times++;
}
if (OB_ITER_END == ret && iter_times > 0) {
ret = OB_SUCCESS;
} else {
OB_LOG_(WARN, "iter failed", K(iter_times));
}
} else {
ret = OB_ERR_UNEXPECTED;
OB_LOG_(WARN, "get mysql result failed");
}
}
}
return ret;
#undef PRINT_WRAPPER
}
static int get_my_sql_result_(const char **columns,
const int64_t column_size,
const ObString &table,
const ObString &condition,
ObISQLClient &proxy,
const uint64_t tenant_id,
ObMySQLProxy::MySQLResult &res,
common::sqlclient::ObMySQLResult *&result)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
#define PRINT_WRAPPER KR(ret), K(MTL_ID()), K(tenant_id), K(columns), K(table), K(condition), K(sql), K(columns_str)
int ret = OB_SUCCESS;
common::sqlclient::ObMySQLResult *result = NULL;
ObSqlString sql;
char columns_str[STACK_BUFFER_SIZE] = {0};
int64_t pos = 0;
for (int i = 0; i < N; ++i) {
if (i != N - 1) {
for (int i = 0; i < column_size; ++i) {
if (i != column_size - 1) {
if (CLICK_FAIL(databuff_printf(&columns_str[0], STACK_BUFFER_SIZE, pos, "%s,", columns[i]))) {
OB_LOG_(WARN, "failed to format column string");
}
@ -332,7 +434,7 @@ public:
OB_LOG_(WARN, "failed to get result");
}
}
return result;
return ret;
#undef PRINT_WRAPPER
}
template <typename T>
@ -411,6 +513,36 @@ public:
return ret;
#undef PRINT_WRAPPER
}
static int get_signle_column_from_signle_row_(common::sqlclient::ObMySQLResult *row,
const char *column,
share::ObLSID &ls_id)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
int ret = common::OB_SUCCESS;
int64_t value = 0;
if (CLICK_FAIL(row->get_int(column, value))) {
OB_LOG(WARN, "get_column_from_signle_row failed", KR(ret), K(MTL_ID()), K(column));
} else {
ls_id = share::ObLSID(value);
OB_LOG(TRACE, "get_column_from_signle_row success", KR(ret), K(MTL_ID()), K(column), K(value));
}
return ret;
}
static int get_signle_column_from_signle_row_(common::sqlclient::ObMySQLResult *row,
const char *column,
common::ObTabletID &tablet_id)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
int ret = common::OB_SUCCESS;
int64_t value = 0;
if (CLICK_FAIL(row->get_int(column, value))) {
OB_LOG(WARN, "get_column_from_signle_row failed", KR(ret), K(MTL_ID()), K(column));
} else {
tablet_id = common::ObTabletID(value);
OB_LOG(TRACE, "get_column_from_signle_row success", KR(ret), K(MTL_ID()), K(column), K(value));
}
return ret;
}
static int get_signle_column_from_signle_row_(common::sqlclient::ObMySQLResult *row,
const char *column,
int64_t &value)
@ -452,17 +584,17 @@ public:
return ret;
}
// 可变参数模版展开的递归基
template <int FLOOR, int N>
static int get_values_from_row_(common::sqlclient::ObMySQLResult *row, const char* (&columns)[N])
template <int FLOOR>
static int get_values_from_row_(common::sqlclient::ObMySQLResult *row, const char **columns)
{
UNUSED(row);
UNUSED(columns);
return OB_SUCCESS;
}
// 可变参数模版展开,从行中获取每一个入参
template <int FLOOR, int N, typename V, typename ...T>
template <int FLOOR, typename V, typename ...T>
static int get_values_from_row_(common::sqlclient::ObMySQLResult *row,
const char* (&columns)[N],
const char **columns,
V &value,
T &...others)
{
@ -477,37 +609,35 @@ public:
}
return ret;
}
template <int FLOOR, int N, typename ...T>
template <int FLOOR, typename ...T>
friend class AccessHelper;
// 便特化必须靠类定义来协助
template <int FLOOR, int N, typename ...T>
template <int FLOOR, typename ...T>
struct AccessHelper
{
// 从行中获取元组中的每一个元素
static int get_values_to_tuple_from_row(common::sqlclient::ObMySQLResult *row,
const char* (&columns)[N],
const char **columns,
ObTuple<T...> &tuple)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);
static_assert(FLOOR > 0 && FLOOR <= N, "unexpected compile error");
static_assert(FLOOR > 0 && FLOOR <= sizeof...(T), "unexpected compile error");
int ret = common::OB_SUCCESS;
if (FLOOR != N) {
if (CLICK_FAIL(get_signle_column_from_signle_row_(row, columns[FLOOR], std::get<FLOOR>(tuple.tuple())))) {
OB_LOG(WARN, "get value failed", KR(ret), K(MTL_ID()), K(columns[FLOOR]));
} else {
ret = AccessHelper<FLOOR - 1, N, T...>::get_values_to_tuple_from_row(row, columns, tuple);
}
if (CLICK_FAIL(get_signle_column_from_signle_row_(row, columns[FLOOR], std::get<FLOOR>(tuple.tuple())))) {
OB_LOG(WARN, "get value failed", KR(ret), K(MTL_ID()), K(columns[FLOOR]));
} else {
ret = AccessHelper<FLOOR - 1, T...>::get_values_to_tuple_from_row(row, columns, tuple);
}
return ret;
}
};
// 模版偏特化递归基
template <int N, typename ...T>
struct AccessHelper<0, N, T...>
template <typename ...T>
struct AccessHelper<0, T...>
{
// 从行中获取元组中的每一个元素的递归基
static int get_values_to_tuple_from_row(common::sqlclient::ObMySQLResult *row,
const char* (&columns)[N],
const char **columns,
ObTuple<T...> &tuple)
{
TIMEGUARD_INIT(OCCAM, 1_s, 60_s);