refine dup table new gc code in leader_switch

This commit is contained in:
KyrielightWei 2024-04-16 20:51:19 +00:00 committed by ob-robot
parent 6cbab0038f
commit 78578299f4
11 changed files with 1005 additions and 417 deletions

View File

@ -34,5 +34,6 @@ ob_unittest_multi_replica(test_ob_dup_table_basic)
ob_unittest_multi_replica(test_ob_dup_table_restart)
ob_unittest_multi_replica(test_ob_dup_table_leader_switch)
ob_unittest_multi_replica(test_ob_dup_table_tablet_gc)
ob_unittest_multi_replica(test_ob_dup_table_new_gc)
ob_unittest_multi_replica(test_mds_replay_from_ctx_table)
ob_unittest_multi_replica_longer_timeout(test_multi_transfer_tx)

View File

@ -259,38 +259,40 @@ namespace unittest
WRITE_SQL_BY_CONN(connection, "set ob_query_timeout = 3000000000"); \
WRITE_SQL_BY_CONN(connection, "set autocommit=0");
#define RETRY_UNTIL_TIMEOUT(condition, timeout_us, retry_interval_us) \
{ \
int64_t start_time = ObTimeUtility::fast_current_time(); \
while (OB_SUCC(ret) && !(condition)) { \
if (ObTimeUtility::fast_current_time() - start_time > timeout_us) { \
ret = OB_TIMEOUT; \
break; \
} \
SERVER_LOG(INFO, "retry one time until timeout", K(condition), K(start_time), \
K(timeout_us)); \
ob_usleep(retry_interval_us); \
} \
SERVER_LOG(INFO, "retry to wait one condition successfully", K(condition), K(start_time), \
K(timeout_us), K(ObTimeUtility::fast_current_time() - start_time)); \
#define RETRY_UNTIL_TIMEOUT(condition, timeout_us, retry_interval_us) \
{ \
ret = OB_SUCCESS; \
int64_t start_time = ObTimeUtility::fast_current_time(); \
while (OB_SUCC(ret) && !(condition)) { \
if (ObTimeUtility::fast_current_time() - start_time > timeout_us) { \
ret = OB_TIMEOUT; \
break; \
} \
SERVER_LOG(INFO, "retry one time until timeout", K(condition), K(start_time), \
K(timeout_us)); \
ob_usleep(retry_interval_us); \
} \
SERVER_LOG(INFO, "retry to wait one condition successfully", K(ret), K(condition), \
K(start_time), K(timeout_us), K(ObTimeUtility::fast_current_time() - start_time)); \
}
#define RETRY_OP_UNTIL_TIMEOUT(op, condition, timeout_us, retry_interval_us) \
{ \
int64_t start_time = ObTimeUtility::fast_current_time(); \
op; \
while (OB_SUCC(ret) && !(condition)) { \
if (ObTimeUtility::fast_current_time() - start_time > timeout_us) { \
ret = OB_TIMEOUT; \
break; \
} \
SERVER_LOG(INFO, "retry opertion until timeout", K(condition), K(start_time), \
K(timeout_us)); \
ob_usleep(retry_interval_us); \
op; \
} \
SERVER_LOG(INFO, "retry to opertion successfully", K(condition), K(start_time), K(timeout_us), \
K(ObTimeUtility::fast_current_time() - start_time)); \
#define RETRY_OP_UNTIL_TIMEOUT(op, condition, timeout_us, retry_interval_us) \
{ \
ret = OB_SUCCESS; \
int64_t start_time = ObTimeUtility::fast_current_time(); \
op; \
while (OB_SUCC(ret) && !(condition)) { \
if (ObTimeUtility::fast_current_time() - start_time > timeout_us) { \
ret = OB_TIMEOUT; \
break; \
} \
SERVER_LOG(INFO, "retry opertion until timeout", K(condition), K(start_time), \
K(timeout_us)); \
ob_usleep(retry_interval_us); \
op; \
} \
SERVER_LOG(INFO, "retry to opertion successfully", K(ret), K(condition), K(start_time), \
K(timeout_us), K(ObTimeUtility::fast_current_time() - start_time)); \
}
#define WAIT_START_SERVICE_SUCCC(timeout_us, retry_interval_us) \

View File

@ -0,0 +1,450 @@
/*
* 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.
*/
#include <gtest/gtest.h>
#define USING_LOG_PREFIX SERVER
#define protected public
#define private public
#include "env/ob_fast_bootstrap.h"
#include "env/ob_multi_replica_util.h"
#include "lib/mysqlclient/ob_mysql_result.h"
#include "storage/tx/ob_dup_table_lease.h"
#include "storage/tx/ob_dup_table_util.h"
using namespace oceanbase::transaction;
using namespace oceanbase::storage;
#define CUR_TEST_CASE_NAME ObDupTableNewGCTest
DEFINE_MULTI_ZONE_TEST_CASE_CLASS
MULTI_REPLICA_TEST_MAIN_FUNCTION(test_dup_table_new_gc_);
static const int64_t MAX_DUP_TABLE_COUNT = 10;
static bool STOP_PREPARE_SERIALIZE_DUP_TABLET = false;
namespace oceanbase
{
namespace transaction
{
OB_NOINLINE int ObLSDupTabletsMgr::process_prepare_ser_err_test_()
{
int ret = OB_SUCCESS;
if (STOP_PREPARE_SERIALIZE_DUP_TABLET) {
ret = OB_EAGAIN;
}
if (OB_FAIL(ret)) {
DUP_TABLE_LOG(INFO, "errsim prepare serialize err test in mittest", K(ret), K(ls_id_));
}
return ret;
}
} // namespace transaction
namespace unittest
{
struct DupTableBasicArg
{
uint64_t tenant_id_;
int64_t ls_id_num_;
ObSEArray<int64_t, 10> table_id_;
int64_t tablet_count_;
ObSEArray<int64_t, 100> tablet_id_array_;
DupTableBasicArg() { reset(); }
void reset()
{
tenant_id_ = 0;
ls_id_num_ = 0;
table_id_.reset();
tablet_count_ = 0;
tablet_id_array_.reset();
}
TO_STRING_KV(K(tenant_id_), K(ls_id_num_), K(table_id_), K(tablet_count_), K(tablet_id_array_));
OB_UNIS_VERSION(1);
};
OB_SERIALIZE_MEMBER(DupTableBasicArg,
tenant_id_,
ls_id_num_,
table_id_,
tablet_count_,
tablet_id_array_);
static DupTableBasicArg dup_basic_arg_;
static const int64_t CUR_GC_INTERVAL = 2 * 1000 * 1000;
void reduce_dup_table_gc_interval(int64_t tenant_id, int64_t cur_gc_interval)
{
share::ObTenantSwitchGuard tenant_guard;
ASSERT_EQ(OB_SUCCESS, tenant_guard.switch_to(tenant_id));
MTL(transaction::ObTransService *)->dup_tablet_scan_task_.scan_task_execute_interval_ =
cur_gc_interval;
MTL(transaction::ObTransService *)->dup_tablet_scan_task_.max_execute_interval_ = cur_gc_interval;
oceanbase::transaction::ObLSDupTabletsMgr::MAX_READABLE_SET_SER_INTERVAL = CUR_GC_INTERVAL;
}
TEST_F(GET_ZONE_TEST_CLASS_NAME(1), create_dup_table)
{
int ret = OB_SUCCESS;
CREATE_TEST_TENANT(test_tenant_id);
SERVER_LOG(INFO, "[ObMultiReplicaTestBase] create test tenant success", K(test_tenant_id));
reduce_dup_table_gc_interval(test_tenant_id, CUR_GC_INTERVAL);
common::ObMySQLProxy &test_tenant_sql_proxy = get_curr_simple_server().get_sql_proxy2();
ACQUIRE_CONN_FROM_SQL_PROXY(test_conn, test_tenant_sql_proxy);
ACQUIRE_CONN_FROM_SQL_PROXY(sys_conn, get_curr_simple_server().get_sql_proxy());
std::string primary_zone_sql = "ALTER TENANT " + std::string(DEFAULT_TEST_TENANT_NAME)
+ " set primary_zone='zone1; zone3; zone2';";
WRITE_SQL_BY_CONN(test_conn, primary_zone_sql.c_str());
for (int i = 0; i < MAX_DUP_TABLE_COUNT; i++) {
std::string tname = "test_t" + std::to_string(i);
std::string create_table_sql =
"CREATE TABLE " + tname
+ "( "
"id_x int, "
"id_y int, "
"id_z int, "
"PRIMARY KEY(id_x)"
") duplicate_scope='cluster' PARTITION BY hash(id_x) partitions 10;";
std::string get_table_id_sql = "select table_id, duplicate_scope from "
"oceanbase.__all_table where table_name = '"
+ tname + "' ";
WRITE_SQL_BY_CONN(test_conn, create_table_sql.c_str());
READ_SQL_BY_CONN(test_conn, table_info_result, get_table_id_sql.c_str());
ASSERT_EQ(OB_SUCCESS, table_info_result->next());
int64_t table_id = 0;
int64_t dup_scope = 0;
ASSERT_EQ(OB_SUCCESS, table_info_result->get_int("table_id", table_id));
ASSERT_EQ(OB_SUCCESS, table_info_result->get_int("duplicate_scope", dup_scope));
ASSERT_EQ(true, table_id > 0);
ASSERT_EQ(true, dup_scope != 0);
ASSERT_EQ(OB_SUCCESS, dup_basic_arg_.table_id_.push_back(table_id));
std::string tablet_count_sql =
"select count(*), ls_id from oceanbase.__all_tablet_to_ls where table_id = "
+ std::to_string(table_id) + " group by ls_id order by count(*)";
READ_SQL_BY_CONN(test_conn, tablet_count_result, tablet_count_sql.c_str());
int64_t tablet_count = 0;
int64_t ls_id_num = 0;
ASSERT_EQ(OB_SUCCESS, tablet_count_result->next());
ASSERT_EQ(OB_SUCCESS, tablet_count_result->get_int("count(*)", tablet_count));
ASSERT_EQ(OB_SUCCESS, tablet_count_result->get_int("ls_id", ls_id_num));
ASSERT_EQ(10, tablet_count);
ASSERT_EQ(true, share::ObLSID(ls_id_num).is_valid());
if (dup_basic_arg_.ls_id_num_ <= 0) {
dup_basic_arg_.ls_id_num_ = ls_id_num;
} else {
ASSERT_EQ(dup_basic_arg_.ls_id_num_, ls_id_num);
}
dup_basic_arg_.tablet_count_ += tablet_count;
std::string tablet_id_sql =
"select tablet_id from oceanbase.__all_tablet_to_ls where table_id = "
+ std::to_string(table_id) + " and ls_id = " + std::to_string(ls_id_num);
READ_SQL_BY_CONN(test_conn, tablet_id_reult, tablet_id_sql.c_str());
while (OB_SUCC(tablet_id_reult->next())) {
int64_t id = 0;
ASSERT_EQ(OB_SUCCESS, tablet_id_reult->get_int("tablet_id", id));
ASSERT_EQ(true, ObTabletID(id).is_valid());
ASSERT_EQ(OB_SUCCESS, dup_basic_arg_.tablet_id_array_.push_back(id));
}
}
dup_basic_arg_.tenant_id_ = test_tenant_id;
std::string tmp_str;
ASSERT_EQ(OB_SUCCESS, EventArgSerTool<DupTableBasicArg>::serialize_arg(dup_basic_arg_, tmp_str));
ASSERT_EQ(OB_SUCCESS, finish_event("CREATE_DUP_TABLE", tmp_str));
}
TEST_F(GET_ZONE_TEST_CLASS_NAME(2), leader_switch_without_gc)
{
int ret = OB_SUCCESS;
std::string tmp_event_val;
ASSERT_EQ(OB_SUCCESS, wait_event_finish("CREATE_DUP_TABLE", tmp_event_val, 30 * 60 * 1000));
ASSERT_EQ(OB_SUCCESS,
EventArgSerTool<DupTableBasicArg>::deserialize_arg(dup_basic_arg_, tmp_event_val));
reduce_dup_table_gc_interval(dup_basic_arg_.tenant_id_, CUR_GC_INTERVAL);
ASSERT_EQ(OB_SUCCESS, get_curr_simple_server().init_sql_proxy2());
common::ObMySQLProxy &sys_sql_proxy = get_curr_simple_server().get_sql_proxy();
ACQUIRE_CONN_FROM_SQL_PROXY(sys_conn, sys_sql_proxy);
GET_LS(dup_basic_arg_.tenant_id_, dup_basic_arg_.ls_id_num_, ls_handle);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.is_inited()
&& ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_,
30 * 1000 * 1000, 1 * 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(!ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000,
100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
usleep(ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL + 4 * CUR_GC_INTERVAL);
std::string ls_id_str = std::to_string(dup_basic_arg_.ls_id_num_);
std::string zone2_ip = local_ip_ + ":" + std::to_string(rpc_ports_[1]);
std::string switch_leader_sql = "alter system switch replica leader ls=" + ls_id_str + " server='"
+ zone2_ip + "' tenant='tt1';";
WRITE_SQL_BY_CONN(sys_conn, switch_leader_sql.c_str());
RETRY_OP_UNTIL_TIMEOUT(
ASSERT_EQ(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count(),
dup_basic_arg_.tablet_count_),
ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000, 50 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
< dup_basic_arg_.tablet_count_,
10 * 1000 * 1000, 50 * 1000);
EXPECT_EQ(ret, OB_TIMEOUT);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_,
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
std::string zone1_ip = local_ip_ + ":" + std::to_string(rpc_ports_[0]);
std::string switch_leader_to_zone1_sql = "alter system switch replica leader ls=" + ls_id_str
+ " server='" + zone1_ip + "' tenant='tt1';";
WRITE_SQL_BY_CONN(sys_conn, switch_leader_to_zone1_sql.c_str());
RETRY_UNTIL_TIMEOUT(!ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000,
100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, finish_event("SWITCH_LEADER_TO_ZONE2_WITHOUT_GC", ""));
}
TEST_F(GET_ZONE_TEST_CLASS_NAME(1), leader_revoke_in_gc)
{
int ret = OB_SUCCESS;
std::string tmp_event_val;
ASSERT_EQ(OB_SUCCESS,
wait_event_finish("SWITCH_LEADER_TO_ZONE2_WITHOUT_GC", tmp_event_val, 30 * 60 * 1000));
common::ObMySQLProxy &test_tenant_sql_proxy = get_curr_simple_server().get_sql_proxy2();
ACQUIRE_CONN_FROM_SQL_PROXY(test_conn, test_tenant_sql_proxy);
GET_LS(dup_basic_arg_.tenant_id_, dup_basic_arg_.ls_id_num_, ls_handle);
RETRY_UNTIL_TIMEOUT(ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000,
100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_,
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
TRANS_LOG(INFO, "[ObMultiReplicaTestBase] print dup tablet stat info 1", K(ret),
KPC(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_));
{
std::string tname = "test_t" + std::to_string(1);
std::string delete_table_sql = "DROP TABLE " + tname;
WRITE_SQL_BY_CONN(test_conn, delete_table_sql.c_str());
std::string get_table_id_sql = "select table_id, duplicate_scope from "
"oceanbase.__all_table where table_name = '"
+ tname + "' ";
READ_SQL_BY_CONN(test_conn, table_info_result, get_table_id_sql.c_str());
ASSERT_EQ(OB_ITER_END, table_info_result->next());
}
// gc t1 successfully
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_ - 10,
20 * 1000 * 1000, 100 * 1000);
TRANS_LOG(INFO, "[ObMultiReplicaTestBase] print dup tablet stat info 1.1", K(ret),
KPC(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_));
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->print_tablet_diag_info_log(true);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(
(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->removing_old_set_->size() == 0),
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
STOP_PREPARE_SERIALIZE_DUP_TABLET = true;
{
std::string tname = "test_t" + std::to_string(2);
std::string delete_table_sql = "DROP TABLE " + tname;
WRITE_SQL_BY_CONN(test_conn, delete_table_sql.c_str());
std::string get_table_id_sql = "select table_id, duplicate_scope from "
"oceanbase.__all_table where table_name = '"
+ tname + "' ";
READ_SQL_BY_CONN(test_conn, table_info_result, get_table_id_sql.c_str());
ASSERT_EQ(OB_ITER_END, table_info_result->next());
}
TRANS_LOG(INFO, "[ObMultiReplicaTestBase] print dup tablet stat info 2", K(ret),
KPC(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_));
RETRY_UNTIL_TIMEOUT(
(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->removing_old_set_->size() > 0),
20 * 1000 * 1000, 100 * 1000);
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->print_tablet_diag_info_log(true);
ASSERT_EQ(ret, OB_SUCCESS);
TRANS_LOG(INFO, "[ObMultiReplicaTestBase] print dup tablet stat info 3", K(ret),
KPC(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_));
ASSERT_EQ(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count(),
dup_basic_arg_.tablet_count_ - 10 /*readable 90 + removing 10*/);
ASSERT_EQ(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->removing_old_set_->size(),
10);
ASSERT_EQ(OB_SUCCESS, finish_event("DROP_TABLE_WITHOUT_LOG", ""));
}
TEST_F(GET_ZONE_TEST_CLASS_NAME(2), continue_gc_in_new_leader)
{
int ret = OB_SUCCESS;
std::string tmp_event_val;
ASSERT_EQ(OB_SUCCESS, wait_event_finish("DROP_TABLE_WITHOUT_LOG", tmp_event_val, 30 * 60 * 1000));
STOP_PREPARE_SERIALIZE_DUP_TABLET = true;
common::ObMySQLProxy &test_tenant_sql_proxy = get_curr_simple_server().get_sql_proxy2();
ACQUIRE_CONN_FROM_SQL_PROXY(test_conn, test_tenant_sql_proxy);
ACQUIRE_CONN_FROM_SQL_PROXY(sys_conn, get_curr_simple_server().get_sql_proxy());
GET_LS(dup_basic_arg_.tenant_id_, dup_basic_arg_.ls_id_num_, ls_handle);
std::string ls_id_str = std::to_string(dup_basic_arg_.ls_id_num_);
std::string zone2_ip = local_ip_ + ":" + std::to_string(rpc_ports_[1]);
std::string switch_leader_sql = "alter system switch replica leader ls=" + ls_id_str + " server='"
+ zone2_ip + "' tenant='tt1';";
WRITE_SQL_BY_CONN(sys_conn, switch_leader_sql.c_str());
RETRY_UNTIL_TIMEOUT(ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000,
100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
< dup_basic_arg_.tablet_count_ - 10,
20 * 1000 * 1000, 100 * 1000);
TRANS_LOG(INFO, "[ObMultiReplicaTestBase] print dup tablet stat info 4", K(ret),
KPC(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_));
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->print_tablet_diag_info_log(true);
ASSERT_EQ(ret, OB_TIMEOUT);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_ - 10 /*readable 90 + removing 10*/,
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->removing_old_set_->size(),
10);
STOP_PREPARE_SERIALIZE_DUP_TABLET = false;
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_ - 10 * 2,
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(OB_SUCCESS, finish_event("CONTINUE_GC_IN_ZONE2", ""));
}
TEST_F(GET_ZONE_TEST_CLASS_NAME(1), check_gc_result_in_old_leader)
{
int ret = OB_SUCCESS;
std::string tmp_event_val;
ASSERT_EQ(OB_SUCCESS, wait_event_finish("CONTINUE_GC_IN_ZONE2", tmp_event_val, 30 * 60 * 1000));
common::ObMySQLProxy &test_tenant_sql_proxy = get_curr_simple_server().get_sql_proxy2();
ACQUIRE_CONN_FROM_SQL_PROXY(test_conn, test_tenant_sql_proxy);
ACQUIRE_CONN_FROM_SQL_PROXY(sys_conn, get_curr_simple_server().get_sql_proxy());
GET_LS(dup_basic_arg_.tenant_id_, dup_basic_arg_.ls_id_num_, ls_handle);
RETRY_UNTIL_TIMEOUT(!ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000,
100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_ - 10 * 2,
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
std::string ls_id_str = std::to_string(dup_basic_arg_.ls_id_num_);
std::string zone1_ip = local_ip_ + ":" + std::to_string(rpc_ports_[0]);
std::string switch_leader_to_zone1_sql = "alter system switch replica leader ls=" + ls_id_str
+ " server='" + zone1_ip + "' tenant='tt1';";
WRITE_SQL_BY_CONN(sys_conn, switch_leader_to_zone1_sql.c_str());
RETRY_UNTIL_TIMEOUT(ls_handle.get_ls()->dup_table_ls_handler_.is_master(), 20 * 1000 * 1000,
100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
RETRY_UNTIL_TIMEOUT(
ls_handle.get_ls()->dup_table_ls_handler_.tablets_mgr_ptr_->get_readable_tablet_count()
== dup_basic_arg_.tablet_count_ - 10 * 2,
20 * 1000 * 1000, 100 * 1000);
ASSERT_EQ(ret, OB_SUCCESS);
}
// TEST_F(GET_ZONE_TEST_CLASS_NAME(1), random_error)
// {
// ASSERT_EQ(ObTimeUtility::current_time() % 4 != 1, true);
// }
//
// TEST_F(GET_ZONE_TEST_CLASS_NAME(2), random_error)
// {
// ASSERT_EQ(ObTimeUtility::current_time() % 4 != 2, true);
// }
//
// TEST_F(GET_ZONE_TEST_CLASS_NAME(3), random_error)
// {
// ASSERT_EQ(ObTimeUtility::current_time() % 4 != 3, true);
// }
} // namespace unittest
} // namespace oceanbase

View File

@ -560,10 +560,8 @@ int ObDupTableLogOperator::submit_log_entry()
int64_t max_ser_size = 0;
bool submit_result = false;
DupLogTypeArray type_array;
if (OB_SUCC(ret)) {
if (OB_TMP_FAIL(tablet_mgr_ptr_->scan_readable_set_for_gc())) {
DUP_TABLE_LOG(WARN, "scan readable set failed", K(tmp_ret));
}
if (OB_FAIL(prepare_serialize_log_entry_(max_ser_size, type_array))) {
DUP_TABLE_LOG(WARN, "prepare serialize log entry failed", K(ret));
} else if (!type_array.empty()) {

View File

@ -82,6 +82,8 @@ struct DupTableInterfaceStat
int64_t dup_table_lease_log_sync_total_time_;
int64_t dup_table_tablet_log_sync_total_time_;
int64_t dup_table_ls_leader_takeover_ts_;
void reset()
{
dup_table_follower_read_succ_cnt_ = 0;
@ -101,6 +103,8 @@ struct DupTableInterfaceStat
dup_table_log_deser_total_time_ = 0;
dup_table_lease_log_sync_total_time_ = 0;
dup_table_tablet_log_sync_total_time_ = 0;
dup_table_ls_leader_takeover_ts_ = 0;
}
TO_STRING_KV(K(dup_table_follower_read_succ_cnt_),
@ -115,7 +119,8 @@ struct DupTableInterfaceStat
K(dup_table_log_replay_total_time_),
K(dup_table_log_deser_total_time_),
K(dup_table_lease_log_sync_total_time_),
K(dup_table_tablet_log_sync_total_time_));
K(dup_table_tablet_log_sync_total_time_),
K(dup_table_ls_leader_takeover_ts_));
};
#define DUP_LEASE_LIFE_PREFIX "[DupLeaseLife] "

View File

@ -9,6 +9,7 @@
// See the Mulan PubL v2 for more details.
#include "lib/utility/ob_tracepoint.h"
#include "storage/tx/ob_trans_service.h"
#include "ob_dup_table_base.h"
#include "ob_dup_table_tablets.h"
#include "ob_dup_table_util.h"
@ -28,6 +29,9 @@ namespace transaction
int64_t ObLSDupTabletsMgr::GC_DUP_TABLETS_TIME_INTERVAL = 5 * 60 * 1000 * 1000L; // 5 min
int64_t ObLSDupTabletsMgr::GC_DUP_TABLETS_FAILED_TIMEOUT =
5 * GC_DUP_TABLETS_TIME_INTERVAL; // 25 min
int64_t ObLSDupTabletsMgr::MAX_READABLE_SET_SER_INTERVAL = 30 * 1000 * 1000L; //30s
const int64_t ObLSDupTabletsMgr::GC_TIMEOUT = 1 * 1000 * 1000L; // 1s
const int64_t ObLSDupTabletsMgr::RESERVED_FREE_SET_COUNT = 64;
@ -444,10 +448,8 @@ void ObLSDupTabletsMgr::reset()
ls_id_.reset();
ATOMIC_STORE(&is_stopped_, true);
ATOMIC_STORE(&is_master_, false);
last_gc_succ_time_ = 0;
last_no_free_set_time_ = 0;
extra_free_set_alloc_count_ = 0;
tablet_gc_window_ = 2 * ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL;
gc_start_time_ = 0;
readable_set_in_gc_ = nullptr;
@ -699,166 +701,177 @@ ERRSIM_POINT_DEF(ERRSIM_DUP_TABLE_GC_RIGHT_NOW);
int ObLSDupTabletsMgr::gc_tmporary_dup_tablets(const int64_t gc_ts, const int64_t max_task_interval)
{
int ret = OB_SUCCESS;
SpinWLockGuard guard(dup_tablets_lock_);
int gc_tablet_cnt = 0;
ObTabletID tmp_id;
// run gc now
if (OB_FAIL(ERRSIM_DUP_TABLE_GC_RIGHT_NOW)) {
ret = OB_SUCCESS;
last_gc_succ_time_ = gc_ts - GC_DUP_TABLETS_TIME_INTERVAL;
DUP_TABLE_LOG(WARN, "use errsim to invoke gc", KR(ret), K(last_gc_succ_time_), K(gc_ts),
K(max_task_interval));
}
if (0 > (gc_ts - last_gc_succ_time_) || 0 > last_gc_succ_time_ || 0 > gc_ts) {
ret = OB_INVALID_ARGUMENT;
DUP_TABLE_LOG(WARN, "Invalid gc_ts or last_gc_time_", KR(ret), K(last_gc_succ_time_), K(gc_ts));
} else if ((gc_ts - last_gc_succ_time_) < GC_DUP_TABLETS_TIME_INTERVAL) {
DUP_TABLE_LOG(DEBUG, "not need gc now", K(last_gc_succ_time_));
} else {
tablet_gc_window_ = 2
* (max_task_interval > ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL
? max_task_interval
: ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL);
int64_t gc_timeout = 0;
if ((gc_ts - last_gc_succ_time_) > GC_DUP_TABLETS_FAILED_TIMEOUT && last_gc_succ_time_ != 0) {
gc_timeout = INT64_MAX;
DUP_TABLE_LOG(WARN,
"gc failed too much times, this time should not break",
K(ret),
K(gc_timeout),
K(GC_DUP_TABLETS_FAILED_TIMEOUT),
K(gc_ts),
K(last_gc_succ_time_));
} else {
gc_timeout = GC_TIMEOUT;
}
int64_t gc_start_time = ObTimeUtility::fast_current_time();
/**
* Gc readable tablet set
* */
DupTabletChangeMap *old_tablet_set = nullptr;
DupTabletSetCommonHeader old_tablet_common_header;
old_tablet_common_header.set_old();
old_tablet_common_header.set_invalid_unique_id();
if (OB_FAIL(ret)) {
} else if (OB_FAIL(get_target_tablet_set_(old_tablet_common_header, old_tablet_set))) {
DUP_TABLE_LOG(WARN, "get old tablet set failed, need skip gc readable tablets", K(ret),
KPC(old_tablet_set));
ret = OB_SUCCESS;
} else if (!old_tablet_set->get_change_status()->is_modifiable()) {
ret = OB_EAGAIN; // should not update gc succ time to increase gc freq
DUP_TABLE_LOG(INFO, "old tablet set can not be modified, skip gc readable tablets", K(ret),
KPC(old_tablet_set));
} else if (old_tablet_set->get_related_set_op_type() == DupTableRelatedSetOpType::OLD_GC) {
DLIST_FOREACH(readable_tablets_ptr, readable_tablets_list_)
{
if (readable_tablets_ptr->is_logging()) {
// do nothing
} else {
GcDiscardedDupTabletHandler readable_gc_handler(
gc_ts, tablet_gc_window_, readable_tablets_ptr->get_common_header(), *old_tablet_set);
if (OB_FAIL(hash_for_each_remove_with_timeout(tmp_id, *readable_tablets_ptr,
readable_gc_handler, gc_timeout))) {
DUP_TABLE_LOG(WARN, "remove readable tablets failed", KR(ret),
K(readable_gc_handler.get_gc_tablet_cnt()));
} else if (OB_FAIL(readable_gc_handler.get_ret())) {
// if fail, not update last gc succ time to increase gc freqency
DUP_TABLE_LOG(WARN, "remove readable tablets failed, may need retry", KR(ret),
K(readable_gc_handler.get_gc_tablet_cnt()));
}
gc_tablet_cnt += readable_gc_handler.get_gc_tablet_cnt();
}
}
} else {
DUP_TABLE_LOG(WARN, "related set type not match", K(ret), KPC(removing_old_set_));
}
/**
* Gc new tablet set
* */
DupTabletChangeMap *changing_new_set = nullptr;
DupTabletSetCommonHeader new_tablet_common_header;
new_tablet_common_header.set_new();
new_tablet_common_header.set_invalid_unique_id();
if (OB_FAIL(ret)) {
// do nothing
} else if (OB_FAIL(get_target_tablet_set_(new_tablet_common_header, changing_new_set))) {
DUP_TABLE_LOG(WARN, "get changing new set failed", K(ret), KPC(changing_new_set));
} else if (OB_NOT_NULL(changing_new_set)) {
if (changing_new_set->empty()) {
// do nothing
DUP_TABLE_LOG(DEBUG, "changing_new_set is empty, not need gc", K(ret));
} else {
GcDiscardedDupTabletHandler new_gc_handler(
gc_ts, tablet_gc_window_, changing_new_set->get_common_header(), *old_tablet_set);
if (OB_FAIL(hash_for_each_remove_with_timeout(tmp_id, *changing_new_set, new_gc_handler,
gc_timeout))) {
DUP_TABLE_LOG(WARN, "remove new tablets failed", KR(ret));
}
// collect gc in new tablets count
gc_tablet_cnt += new_gc_handler.get_gc_tablet_cnt();
}
}
// collect gc readable tablet
if (OB_SUCC(ret)) {
last_gc_succ_time_ = gc_ts;
} else if (OB_TIMEOUT == ret) {
DUP_TABLE_LOG(WARN, "gc tablets failed, scan all tablets set cost too much time", K(ret),
K(gc_start_time), K(gc_timeout), K(gc_tablet_cnt));
} else if (OB_EAGAIN == ret) {
ret = OB_SUCCESS;
}
if (0 != gc_tablet_cnt) {
DUP_TABLE_LOG(INFO, "finish gc dup tablet on time", K(ret), KPC(changing_new_set_),
KPC(removing_old_set_), K(readable_tablets_list_.get_size()), K(gc_tablet_cnt));
}
}
// SpinWLockGuard guard(dup_tablets_lock_);
// int gc_tablet_cnt = 0;
// ObTabletID tmp_id;
//
// // run gc now
// if (OB_FAIL(ERRSIM_DUP_TABLE_GC_RIGHT_NOW)) {
// ret = OB_SUCCESS;
// last_gc_succ_time_ = gc_ts - GC_DUP_TABLETS_TIME_INTERVAL;
// DUP_TABLE_LOG(WARN, "use errsim to invoke gc", KR(ret), K(last_gc_succ_time_), K(gc_ts),
// K(max_task_interval));
// }
//
// if (0 >= (gc_ts - last_gc_succ_time_) || 0 >= last_gc_succ_time_ || 0 >= gc_ts) {
// ret = OB_INVALID_ARGUMENT;
// DUP_TABLE_LOG(WARN, "Invalid gc_ts or last_gc_time_", KR(ret), K(last_gc_succ_time_), K(gc_ts));
// } else if ((gc_ts - last_gc_succ_time_) < GC_DUP_TABLETS_TIME_INTERVAL) {
// DUP_TABLE_LOG(DEBUG, "not need gc now", K(last_gc_succ_time_));
// } else {
// tablet_gc_window_ = 2
// * (max_task_interval > ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL
// ? max_task_interval
// : ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL);
//
// int64_t gc_timeout = 0;
// if ((gc_ts - last_gc_succ_time_) > GC_DUP_TABLETS_FAILED_TIMEOUT && last_gc_succ_time_ != 0) {
// gc_timeout = INT64_MAX;
// DUP_TABLE_LOG(WARN,
// "gc failed too much times, this time should not break",
// K(ret),
// K(gc_timeout),
// K(GC_DUP_TABLETS_FAILED_TIMEOUT),
// K(gc_ts),
// K(last_gc_succ_time_));
// } else {
// gc_timeout = GC_TIMEOUT;
// }
//
// int64_t gc_start_time = ObTimeUtility::fast_current_time();
//
// /**
// * Gc readable tablet set
// * */
// DupTabletChangeMap *old_tablet_set = nullptr;
// DupTabletSetCommonHeader old_tablet_common_header;
// old_tablet_common_header.set_old();
// old_tablet_common_header.set_invalid_unique_id();
//
// if (OB_FAIL(ret)) {
// } else if (OB_FAIL(get_target_tablet_set_(old_tablet_common_header, old_tablet_set))) {
// DUP_TABLE_LOG(WARN, "get old tablet set failed, need skip gc readable tablets", K(ret),
// KPC(old_tablet_set));
// ret = OB_SUCCESS;
// } else if (!old_tablet_set->get_change_status()->is_modifiable()) {
// ret = OB_EAGAIN; // should not update gc succ time to increase gc freq
// DUP_TABLE_LOG(INFO, "old tablet set can not be modified, skip gc readable tablets", K(ret),
// KPC(old_tablet_set));
// } else if (old_tablet_set->get_related_set_op_type() == DupTableRelatedSetOpType::OLD_GC) {
// DLIST_FOREACH(readable_tablets_ptr, readable_tablets_list_)
// {
// if (readable_tablets_ptr->is_logging()) {
// // do nothing
// } else {
// GcDiscardedDupTabletHandler readable_gc_handler(
// gc_ts, tablet_gc_window_, readable_tablets_ptr->get_common_header(), *old_tablet_set);
// if (OB_FAIL(hash_for_each_remove_with_timeout(tmp_id, *readable_tablets_ptr,
// readable_gc_handler, gc_timeout))) {
// DUP_TABLE_LOG(WARN, "remove readable tablets failed", KR(ret),
// K(readable_gc_handler.get_gc_tablet_cnt()));
// } else if (OB_FAIL(readable_gc_handler.get_ret())) {
// // if fail, not update last gc succ time to increase gc freqency
// DUP_TABLE_LOG(WARN, "remove readable tablets failed, may need retry", KR(ret),
// K(readable_gc_handler.get_gc_tablet_cnt()));
// }
// gc_tablet_cnt += readable_gc_handler.get_gc_tablet_cnt();
// }
// }
// } else {
// DUP_TABLE_LOG(WARN, "related set type not match", K(ret), KPC(removing_old_set_));
// }
//
// /**
// * Gc new tablet set
// * */
// DupTabletChangeMap *changing_new_set = nullptr;
// DupTabletSetCommonHeader new_tablet_common_header;
// new_tablet_common_header.set_new();
// new_tablet_common_header.set_invalid_unique_id();
// if (OB_FAIL(ret)) {
// // do nothing
// } else if (OB_FAIL(get_target_tablet_set_(new_tablet_common_header, changing_new_set))) {
// DUP_TABLE_LOG(WARN, "get changing new set failed", K(ret), KPC(changing_new_set));
// } else if (OB_NOT_NULL(changing_new_set)) {
// if (changing_new_set->empty()) {
// // do nothing
// DUP_TABLE_LOG(DEBUG, "changing_new_set is empty, not need gc", K(ret));
// } else {
// GcDiscardedDupTabletHandler new_gc_handler(
// gc_ts, tablet_gc_window_, changing_new_set->get_common_header(), *old_tablet_set);
//
// if (OB_FAIL(hash_for_each_remove_with_timeout(tmp_id, *changing_new_set, new_gc_handler,
// gc_timeout))) {
// DUP_TABLE_LOG(WARN, "remove new tablets failed", KR(ret));
// }
// // collect gc in new tablets count
// gc_tablet_cnt += new_gc_handler.get_gc_tablet_cnt();
// }
// }
// // collect gc readable tablet
// if (OB_SUCC(ret)) {
// last_gc_succ_time_ = gc_ts;
// } else if (OB_TIMEOUT == ret) {
// DUP_TABLE_LOG(WARN, "gc tablets failed, scan all tablets set cost too much time", K(ret),
// K(gc_start_time), K(gc_timeout), K(gc_tablet_cnt));
// } else if (OB_EAGAIN == ret) {
// ret = OB_SUCCESS;
// }
//
// if (0 != gc_tablet_cnt) {
// DUP_TABLE_LOG(INFO, "finish gc dup tablet on time", K(ret), KPC(changing_new_set_),
// KPC(removing_old_set_), K(readable_tablets_list_.get_size()), K(gc_tablet_cnt));
// }
// }
return ret;
}
DupTabletChangeMap *ObLSDupTabletsMgr::get_need_gc_set_(bool &new_round)
DupTabletChangeMap *ObLSDupTabletsMgr::get_need_gc_set_()
{
if (OB_ISNULL(readable_set_in_gc_) || gc_start_time_ <= 0) {
gc_start_time_ = ObTimeUtility::fast_current_time();
if (!readable_tablets_list_.is_empty()) {
readable_set_in_gc_ = readable_tablets_list_.get_first();
}
}
if (OB_NOT_NULL(readable_set_in_gc_)) {
if (!readable_set_in_gc_->get_common_header().is_readable_set()) {
DUP_TABLE_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "this ptr not in readable list",
KPC(removing_old_set_), KPC(readable_set_in_gc_));
readable_set_in_gc_ = nullptr;
} else if (readable_set_in_gc_->need_gc_scan(gc_start_time_)) {
// retry gc scan for OB_SIZE_OVERFLOW
} else {
READABLE_DLIST_FOREACH_X(readable_set_in_gc_, readable_tablets_list_,
!readable_set_in_gc_->need_gc_scan(gc_start_time_));
}
}
if (OB_ISNULL(readable_set_in_gc_)) {
if (!readable_tablets_list_.is_empty()) {
readable_set_in_gc_ = readable_tablets_list_.get_first();
new_round = true;
}
}
if (readable_set_in_gc_ == readable_tablets_list_.get_header()) {
if (readable_set_in_gc_ == readable_tablets_list_.get_header()
|| OB_ISNULL(readable_set_in_gc_)) {
readable_set_in_gc_ = nullptr;
DUP_TABLE_LOG(INFO, "readable_set_in_gc_ is null ptr, no need start gc", K(readable_tablets_list_.get_size()),
KP(removing_old_set_), KP(readable_set_in_gc_), KP(readable_tablets_list_.get_header()));
gc_start_time_ = ObTimeUtility::fast_current_time();
DUP_TABLE_LOG(INFO, "readable_set_in_gc_ is null ptr, no need start gc",
K(readable_tablets_list_.get_size()), KP(removing_old_set_),
KP(readable_set_in_gc_), KP(readable_tablets_list_.get_header()),
KP(readable_tablets_list_.get_first()));
}
return readable_set_in_gc_;
}
int ObLSDupTabletsMgr::scan_readable_set_for_gc()
int ObLSDupTabletsMgr::scan_readable_set_for_gc(const int64_t leader_takeover_ts)
{
int ret = OB_SUCCESS;
DupTabletChangeMap *tmp_readable_gc_set_ptr = nullptr;
bool new_round = false;
const int64_t last_scan_task_succ_ts =
MTL(ObTransService *)->get_dup_table_scan_task().get_last_scan_task_succ_ts();
SpinWLockGuard guard(dup_tablets_lock_);
if (OB_ISNULL(removing_old_set_)) {
@ -867,23 +880,27 @@ int ObLSDupTabletsMgr::scan_readable_set_for_gc()
} else if (removing_old_set_->get_related_set_op_type() <= DupTableRelatedSetOpType::INVALID) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(WARN, "invalid related set type", K(ret), KPC(removing_old_set_));
} else if (leader_takeover_ts >= last_scan_task_succ_ts) {
ret = OB_EAGAIN;
DUP_TABLE_LOG(
WARN, "Since taking over, we have not yet scanned the schema of the dup table even once",
K(ret), K(leader_takeover_ts), K(last_scan_task_succ_ts),
K(MTL(ObTransService *)->get_dup_table_scan_task()));
} else if (removing_old_set_->get_related_set_op_type() == DupTableRelatedSetOpType::NEW_GC) {
if ((!removing_old_set_->empty())
|| removing_old_set_->get_related_common_header().is_valid()) {
if (is_busy_in_readable_change_()) {
// old set not confimed and clear, not need scan this time
} else if (OB_ISNULL(tmp_readable_gc_set_ptr = get_need_gc_set_(new_round))) {
} else if (OB_ISNULL(tmp_readable_gc_set_ptr = get_need_gc_set_())) {
// get null set
} else {
int64_t cur_time = ObTimeUtility::fast_current_time();
if (new_round || gc_start_time_ <= 0) {
gc_start_time_ = cur_time;
}
int64_t dup_schema_expired_time_interval =
3 * (MTL(ObTransService *)->get_dup_table_scan_task().get_max_exec_interval());
GcOneReadableSetHandler gc_handler(cur_time, tablet_gc_window_, *removing_old_set_,
MAX_GC_TABLET_COUNT);
GcOneReadableSetHandler gc_handler(gc_start_time_, dup_schema_expired_time_interval,
*removing_old_set_, MAX_GC_TABLET_COUNT);
if (OB_FAIL(hash_for_each_update(*tmp_readable_gc_set_ptr, gc_handler))) {
DUP_TABLE_LOG(WARN, "scan readable for gc failed", K(ret), KPC(removing_old_set_),
KPC(tmp_readable_gc_set_ptr), K(cur_time), K(gc_start_time_));
KPC(tmp_readable_gc_set_ptr), K(dup_schema_expired_time_interval),
K(gc_start_time_));
if (OB_SIZE_OVERFLOW == ret) {
ret = OB_SUCCESS;
}
@ -905,7 +922,7 @@ int ObLSDupTabletsMgr::scan_readable_set_for_gc()
DUP_TABLE_LOG(INFO, DUP_TABLET_LIFE_PREFIX "scan a readable set for GC", K(ret),
K(gc_handler.get_gc_tablet_cnt()), KPC(removing_old_set_),
KPC(tmp_readable_gc_set_ptr), K(new_round), K(gc_start_time_),
K(tablet_gc_window_));
K(dup_schema_expired_time_interval));
}
}
}
@ -913,6 +930,15 @@ int ObLSDupTabletsMgr::scan_readable_set_for_gc()
return ret;
}
bool ObLSDupTabletsMgr::is_busy_in_readable_change_()
{
bool is_busy =
// in gc
(!removing_old_set_->empty())
|| removing_old_set_->get_related_common_header().is_valid();
return is_busy;
}
// leader and follower remove tablet from readable set after first log synced
// lock outside this func
int ObLSDupTabletsMgr::remove_tablet_from_readable_set_()
@ -989,15 +1015,9 @@ int ObLSDupTabletsMgr::refresh_dup_tablet(const common::ObTabletID &tablet_id,
if (OB_FAIL(discover_dup_tablet_(tablet_id, refresh_time))) {
DUP_TABLE_LOG(WARN, "discover a dup tablet failed", K(tablet_id), K(refresh_time));
}
} else {
if (OB_NOT_NULL(removing_old_set_)
&& removing_old_set_->get_related_set_op_type() == DupTableRelatedSetOpType::OLD_GC) {
if (OB_FAIL(lose_dup_tablet_(tablet_id))) {
DUP_TABLE_LOG(WARN, "a dup tablet lose dup attr failed", K(tablet_id));
}
} else {
DUP_TABLE_LOG(WARN, "related set type not match", K(ret), KPC(removing_old_set_));
if (OB_FAIL(lose_dup_tablet_(tablet_id))) {
DUP_TABLE_LOG(WARN, "a dup tablet lose dup attr failed", K(tablet_id));
}
}
@ -1114,7 +1134,9 @@ OB_NOINLINE int ObLSDupTabletsMgr::process_prepare_ser_err_test_()
ret = EN_DUP_TABLE_LOG_PREPARE_SERIALIZE;
#endif
DUP_TABLE_LOG(INFO, "errsim prepare serialize err test", K(ret),K(ls_id_));
if (OB_FAIL(ret)) {
DUP_TABLE_LOG(INFO, "errsim for prepare serialize", K(ret), K(ls_id_));
}
return ret;
}
@ -1130,12 +1152,85 @@ int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size,
unique_id_array.reuse();
if (OB_FAIL(process_prepare_ser_err_test_())) {
DUP_TABLE_LOG(WARN, "errsim for dup tablet log prepare serialize", K(ret));
}
if (OB_SUCC(ret)) {
if (OB_FAIL(process_prepare_ser_err_test_())) {
DUP_TABLE_LOG(WARN, "errsim for dup tablet log prepare serialize", K(ret));
if (OB_FAIL(prepare_serialize_confirming_tablet_set_(max_ser_size, unique_id_array,
max_log_buf_len))) {
DUP_TABLE_LOG(WARN, "prepare serialize confirming tablet set failed", K(ret), K(max_ser_size),
K(max_log_buf_len));
}
}
if (OB_SUCC(ret)) {
if (ObTimeUtility::fast_current_time() - ATOMIC_LOAD(&last_readable_sync_succ_time_)
<= MAX_READABLE_SET_SER_INTERVAL) {
DUP_TABLE_LOG(DEBUG,
"Too many readable tablets log entry. Stop serializing readable tablet log",
K(ret), K(unique_id_array), K(max_ser_size), K(last_readable_sync_succ_time_));
} else if (OB_FAIL(prepare_serialize_readable_tablet_set_(max_ser_size, unique_id_array,
max_log_buf_len))) {
DUP_TABLE_LOG(WARN, "prepare serialize readable tablet set failed", K(ret),
K(unique_id_array), K(max_ser_size), K(last_readable_sync_succ_time_));
}
}
if (OB_LOG_TOO_LARGE == ret) {
DUP_TABLE_LOG(DEBUG, "Too many dup tablets, we can not submit all", K(ret), K(max_ser_size),
K(max_log_buf_len), K(unique_id_array), K(unique_id_array.count()),
K(readable_tablets_list_.get_size()));
ret = OB_SUCCESS;
}
return ret;
}
int ObLSDupTabletsMgr::prepare_serialize_readable_tablet_set_(int64_t &max_ser_size,
DupTabletSetIDArray &unique_id_array,
const int64_t max_log_buf_len)
{
int ret = OB_SUCCESS;
// TODO serialize readable tablets
if (OB_SUCC(ret)) {
if (readable_tablets_list_.get_size() > 200) {
ret = OB_LOG_TOO_LARGE;
} else {
DLIST_FOREACH(readable_ptr, readable_tablets_list_)
{
if (readable_ptr->is_logging()) {
// set logging by old perpare serialize
DUP_TABLE_LOG(INFO, "this readable set is prepare serialized", K(ret),
K(readable_ptr->get_RO_common_header()));
} else if (OB_FAIL(cal_single_set_max_ser_size_(readable_ptr, max_ser_size, max_log_buf_len,
unique_id_array))) {
DUP_TABLE_LOG(WARN, "cal readable set max ser_size failed", K(ret));
if (OB_SIZE_OVERFLOW == ret) {
ret = OB_LOG_TOO_LARGE;
}
} else {
readable_ptr->set_logging();
}
}
DUP_TABLE_LOG(INFO, "serialize readable tablets in log for recovery", K(ret),
K(unique_id_array), K(max_ser_size), K(last_readable_sync_succ_time_),
K(last_readable_log_entry_scn_.atomic_load()));
}
}
return ret;
}
int ObLSDupTabletsMgr::prepare_serialize_confirming_tablet_set_(int64_t &max_ser_size,
DupTabletSetIDArray &unique_id_array,
const int64_t max_log_buf_len)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
//need_confirm_queue
if (OB_SUCC(ret)) {
bool can_be_confirmed = true;
DLIST_FOREACH(cur_map, need_confirm_new_queue_)
@ -1164,6 +1259,7 @@ int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size,
}
}
//changing new set
if (OB_SUCC(ret)) {
if (OB_ISNULL(changing_new_set_)) {
// do nothing
@ -1230,52 +1326,10 @@ int ObLSDupTabletsMgr::prepare_serialize(int64_t &max_ser_size,
}
}
}
if (OB_SUCC(ret)
&& ObTimeUtility::fast_current_time() - ATOMIC_LOAD(&last_readable_sync_succ_time_)
<= 30 * 1000 * 1000) {
ret = OB_LOG_TOO_LARGE;
DUP_TABLE_LOG(DEBUG,
"Too many readable tablets log entry. Stop serializing readable tablet log",
K(ret), K(unique_id_array), K(max_ser_size), K(last_readable_sync_succ_time_));
}
// TODO serialize readable tablets
if (OB_SUCC(ret)) {
if (readable_tablets_list_.get_size() > 200) {
ret = OB_LOG_TOO_LARGE;
} else {
DLIST_FOREACH(readable_ptr, readable_tablets_list_)
{
if (readable_ptr->is_logging()) {
// set logging by old perpare serialize
DUP_TABLE_LOG(INFO, "this readable set is prepare serialized", K(ret),
K(readable_ptr->get_RO_common_header()));
} else if (OB_FAIL(cal_single_set_max_ser_size_(readable_ptr, max_ser_size, max_log_buf_len,
unique_id_array))) {
DUP_TABLE_LOG(WARN, "cal readable set max ser_size failed", K(ret));
if (OB_SIZE_OVERFLOW == ret) {
ret = OB_LOG_TOO_LARGE;
}
} else {
readable_ptr->set_logging();
}
}
DUP_TABLE_LOG(INFO, "serialize readable tablets in log for recovery", K(ret),
K(unique_id_array), K(max_ser_size), K(last_readable_sync_succ_time_),
K(last_readable_log_entry_scn_.atomic_load()));
}
}
if (OB_LOG_TOO_LARGE == ret) {
DUP_TABLE_LOG(DEBUG, "Too many dup tablets, we can not submit all", K(ret), K(max_ser_size),
K(max_log_buf_len), K(unique_id_array), K(unique_id_array.count()),
K(readable_tablets_list_.get_size()));
ret = OB_SUCCESS;
}
return ret;
}
int ObLSDupTabletsMgr::serialize_tablet_log(const DupTabletSetIDArray &unique_id_array,
char *buf,
const int64_t buf_len,
@ -1589,7 +1643,7 @@ int ObLSDupTabletsMgr::tablet_log_synced(const bool sync_result,
}
if (unique_id_array.count() > 0) {
DUP_TABLE_LOG(DEBUG, "tablet log sync", K(ret), K(sync_result), K(for_replay), K(is_master()),
DUP_TABLE_LOG(INFO, "tablet log sync", K(ret), K(sync_result), K(for_replay), K(is_master()),
K(unique_id_array), K(scn), K(modify_readable_set));
}
@ -1771,6 +1825,19 @@ int64_t ObLSDupTabletsMgr::get_dup_tablet_count()
return total_size;
}
int64_t ObLSDupTabletsMgr::get_readable_tablet_count()
{
SpinRLockGuard guard(dup_tablets_lock_);
int64_t total_size = 0;
DLIST_FOREACH_X(readable_set_ptr, readable_tablets_list_, true)
{
total_size += readable_set_ptr->size();
}
return total_size;
}
bool ObLSDupTabletsMgr::has_dup_tablet() { return 0 < get_dup_tablet_count(); }
int64_t ObLSDupTabletsMgr::get_readable_tablet_set_count()
@ -2139,6 +2206,7 @@ int ObLSDupTabletsMgr::lose_dup_tablet_(const common::ObTabletID &tablet_id)
* In changing_new: remove from new set
* */
DupTabletInfo tmp_info;
bool remove_from_temporary = false;
DupTabletSetCommonHeader changing_new_header;
changing_new_header.set_invalid_unique_id();
@ -2155,6 +2223,8 @@ int ObLSDupTabletsMgr::lose_dup_tablet_(const common::ObTabletID &tablet_id)
} else if (OB_SUCC(changing_new_map->get_refactored(tablet_id, tmp_info))) {
if (OB_FAIL(changing_new_map->erase_refactored(tablet_id))) {
DUP_TABLE_LOG(WARN, "remove from changing_new_set_ failed", K(ret), K(tablet_id));
} else {
remove_from_temporary = true;
}
} else if (ret != OB_HASH_NOT_EXIST) {
DUP_TABLE_LOG(WARN, "get dup table status from new_tablets_ failed", K(ret));
@ -2162,40 +2232,30 @@ int ObLSDupTabletsMgr::lose_dup_tablet_(const common::ObTabletID &tablet_id)
ret = OB_SUCCESS;
}
DupTabletSetCommonHeader old_set_header;
old_set_header.set_invalid_unique_id();
old_set_header.set_old();
DupTabletChangeMap *old_tablet_set = nullptr;
if (OB_FAIL(ret)) {
// do nothing
} else if (OB_FAIL(get_target_tablet_set_(old_set_header, old_tablet_set))) {
DUP_TABLE_LOG(WARN, "get old tablets set failed", K(ret));
} else if (!old_tablet_set->get_change_status()->is_modifiable()) {
ret = OB_SUCCESS;
DUP_TABLE_LOG(DEBUG, "old tablet set can not be modified", K(ret), K(tablet_id),
KPC(old_tablet_set));
} else {
DLIST_FOREACH(readable_set_ptr, readable_tablets_list_)
if (OB_SUCC(ret) && remove_from_temporary) {
DUP_TABLE_LOG(INFO, DUP_TABLET_LIFE_PREFIX "lose a temporary dup tablet", K(ret), K(tablet_id),
KPC(changing_new_set_));
}
#ifdef ENABLE_DEBUG_LOG
if (OB_SUCC(ret) && !remove_from_temporary) {
ret = OB_HASH_NOT_EXIST;
DLIST_FOREACH_X(readable_set_ptr, readable_tablets_list_, OB_HASH_NOT_EXIST == ret)
{
if (readable_set_ptr->is_logging()) {
// do nothing
} else if (OB_SUCC(readable_set_ptr->get_refactored(tablet_id, tmp_info))) {
if (OB_FAIL(old_tablet_set->set_refactored(tablet_id, tmp_info))) {
DUP_TABLE_LOG(WARN, "insert into old tablet set failed", K(ret));
} else if (OB_FAIL(readable_set_ptr->erase_refactored(tablet_id))) {
DUP_TABLE_LOG(WARN, "remove from readable tablet set failed", K(ret));
}
if (OB_SUCC(readable_set_ptr->get_refactored(tablet_id, tmp_info))) {
DUP_TABLE_LOG(INFO, "lose a dup tablet in readable tabelt set which need be gc", K(ret),
K(tablet_id), K(tmp_info), KPC(readable_set_ptr));
} else if (ret != OB_HASH_NOT_EXIST) {
DUP_TABLE_LOG(WARN, "get dup table status from readable_tablets_ failed", K(ret));
} else if (ret == OB_HASH_NOT_EXIST) {
ret = OB_SUCCESS;
DUP_TABLE_LOG(WARN, "get dup table status from readable_tablets_ failed", K(ret),
KPC(readable_set_ptr));
}
}
if (ret == OB_HASH_NOT_EXIST) {
ret = OB_SUCCESS;
}
}
if (OB_FAIL(ret)) {
DUP_TABLE_LOG(WARN, "lose dup tablet failed", K(ret), K(tablet_id), KPC(changing_new_set_),
KPC(removing_old_set_), K(readable_tablets_list_.get_size()));
}
#endif
return ret;
}
@ -3185,6 +3245,8 @@ int ObTenantDupTabletSchemaHelper::refresh_and_get_tablet_set(TabletIDSet &tenan
{
int ret = OB_SUCCESS;
tenant_dup_tablet_set.reuse();
if (OB_FAIL(get_all_dup_tablet_set_(tenant_dup_tablet_set))) {
DUP_TABLE_LOG(WARN, "get tenant dup tablet set faild", K(ret));
}

View File

@ -419,10 +419,6 @@ public:
DUP_TABLE_LOG(INFO, "this readable set used for other operation, should skip gc", KPC(this));
bool_ret = false;
} else {
bool_ret = true;
}
if (bool_ret) {
if (last_gc_scan_ts_ <= 0
|| gc_start_time > last_gc_scan_ts_) {
bool_ret = true;
@ -431,6 +427,8 @@ public:
}
}
DUP_TABLE_LOG(INFO, "check need gc scan", K(bool_ret),K(last_gc_scan_ts_),K(gc_start_time),KPC(this));
return bool_ret;
}
void set_last_gc_scan_ts(const int64_t gc_start_time) {
@ -440,6 +438,8 @@ public:
} else {
last_gc_scan_ts_ = gc_start_time;
}
DUP_TABLE_LOG(INFO, "set last gc scn ts", K(last_gc_scan_ts_),K(gc_start_time),KPC(this));
}
int64_t get_last_gc_scan_ts() { return last_gc_scan_ts_; }
@ -629,7 +629,7 @@ public:
const share::SCN &to_scn);
int gc_tmporary_dup_tablets(const int64_t gc_ts, const int64_t max_task_interval);
// new gc methods
int scan_readable_set_for_gc();
int scan_readable_set_for_gc(const int64_t leader_takeover_ts);
int refresh_dup_tablet(const common::ObTabletID &tablet_id,
bool is_dup_table,
@ -662,6 +662,7 @@ public:
int try_to_confirm_tablets(const share::SCN &confirm_scn);
// bool need_log_tablets();
int64_t get_dup_tablet_count();
int64_t get_readable_tablet_count();
bool has_dup_tablet();
int64_t get_readable_tablet_set_count();
int64_t get_need_confirm_tablet_set_count();
@ -835,6 +836,13 @@ private:
const bool for_replay);
bool need_seralize_readable_set() { return true; }
int prepare_serialize_readable_tablet_set_(int64_t &max_ser_size,
DupTabletSetIDArray &unique_id_array,
const int64_t max_log_buf_len);
int prepare_serialize_confirming_tablet_set_(int64_t &max_ser_size,
DupTabletSetIDArray &unique_id_array,
const int64_t max_log_buf_len);
int cal_single_set_max_ser_size_(DupTabletChangeMap *hash_map,
int64_t &max_ser_size,
const int64_t ser_size_limit,
@ -854,8 +862,9 @@ private:
int remove_src_and_related_set_header_from_array_(DupTabletChangeMap *src_set,
DupTabletChangeMap *related_set,
DupTabletSetIDArray &unique_id_array);
DupTabletChangeMap *get_need_gc_set_(bool &new_round);
DupTabletChangeMap *get_need_gc_set_();
int remove_tablet_from_readable_set_();
bool is_busy_in_readable_change_();
private:
//
static int64_t GC_DUP_TABLETS_TIME_INTERVAL; // 5 min
@ -866,6 +875,7 @@ private:
const static int64_t MAX_FREE_SET_COUNT;
const static int64_t MAX_GC_TABLET_COUNT;
static int64_t MAX_READABLE_SET_SER_INTERVAL;
public:
TO_STRING_KV(K(free_set_pool_.get_size()),
@ -873,7 +883,6 @@ public:
K(need_confirm_new_queue_.get_size()),
K(readable_tablets_list_.get_size()),
KPC(removing_old_set_),
K(last_gc_succ_time_),
K(last_no_free_set_time_),
K(extra_free_set_alloc_count_));
@ -885,16 +894,12 @@ private:
bool is_master_;
bool is_stopped_;
// used for gc_handler
int64_t tablet_gc_window_; // default is 2 * ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL;
common::ObDList<DupTabletChangeMap> free_set_pool_;
DupTabletChangeMap *changing_new_set_;
common::ObDList<DupTabletChangeMap> need_confirm_new_queue_;
common::ObDList<DupTabletChangeMap> readable_tablets_list_;
DupTabletChangeMap *removing_old_set_;
// gc_dup_table
int64_t last_gc_succ_time_;
/* 1. gc one round means iter all readable set
* 2. use readable_set_in_gc_ point to readable set not finish gc in one round
* 3. use gc_start_time_ mark gc one round start time one round

View File

@ -355,13 +355,23 @@ int ObDupTableLSTsSyncMgr::get_local_ts_info(DupTableTsInfo &ts_info)
int ObDupTableLSTsSyncMgr::get_cache_ts_info(const common::ObAddr &addr, DupTableTsInfo &ts_info)
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
SpinRLockGuard guard(ts_sync_lock_);
{
SpinRLockGuard guard(ts_sync_lock_);
if (OB_FAIL(get_ts_info_cache_(addr, ts_info))) {
DUP_TABLE_LOG(WARN, "get ts info cache failed", K(ret));
if (OB_FAIL(get_ts_info_cache_(addr, ts_info))) {
DUP_TABLE_LOG(WARN, "get ts info cache failed", K(ret));
}
DUP_TABLE_LOG(DEBUG, "get ts info cache", K(ret), K(ret), K(ts_info));
}
if (OB_HASH_NOT_EXIST == ret) {
if (OB_TMP_FAIL(request_ts_info(addr))) {
DUP_TABLE_LOG(WARN, "request ts info failed", K(tmp_ret), K(ts_info));
}
}
DUP_TABLE_LOG(DEBUG, "get ts info cache", K(ret), K(ret), K(ts_info));
return ret;
}

View File

@ -38,8 +38,13 @@ void ObDupTabletScanTask::reset()
tenant_id_ = 0;
dup_table_scan_timer_ = nullptr;
dup_loop_worker_ = nullptr;
last_execute_time_ = 0;
max_execute_interval_ = 0;
min_dup_ls_status_info_.reset();
tenant_schema_dup_tablet_set_.destroy();
scan_task_execute_interval_ = ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL;
last_dup_ls_refresh_time_ = 0;
last_dup_schema_refresh_time_ = 0;
last_scan_task_succ_time_ = 0;
max_execute_interval_ = ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL;
}
int ObDupTabletScanTask::make(const int64_t tenant_id,
@ -54,6 +59,9 @@ int ObDupTabletScanTask::make(const int64_t tenant_id,
tenant_id_ = tenant_id;
dup_table_scan_timer_ = scan_timer;
dup_loop_worker_ = loop_worker;
min_dup_ls_status_info_.reset();
tenant_schema_dup_tablet_set_.reuse();
scan_task_execute_interval_ = ObDupTabletScanTask::DUP_TABLET_SCAN_INTERVAL;
// ObTransTask::make(ObTransRetryTaskType::DUP_TABLET_SCAN_TASK);
// set_retry_interval_us(DUP_TABLET_SCAN_INTERVAL, DUP_TABLET_SCAN_INTERVAL);
}
@ -74,83 +82,143 @@ void ObDupTabletScanTask::runTimerTask()
}
dup_table_scan_timer_->unregister_timeout_task(*this);
dup_table_scan_timer_->register_timeout_task(*this, DUP_TABLET_SCAN_INTERVAL);
dup_table_scan_timer_->register_timeout_task(*this, scan_task_execute_interval_);
}
}
int ObDupTabletScanTask::refresh_dup_tablet_schema_(
bool need_refresh,
ObTenantDupTabletSchemaHelper::TabletIDSet &tenant_dup_tablet_set,
share::ObLSStatusInfo &dup_ls_status_info)
int ObDupTabletScanTask::refresh_dup_ls_(const int64_t cur_time)
{
int ret = OB_SUCCESS;
bool has_dup_ls = false;
if (need_refresh) {
bool need_refresh = true;
if (min_dup_ls_status_info_.is_valid() && min_dup_ls_status_info_.is_duplicate_ls()) {
if (cur_time - last_dup_ls_refresh_time_ < MAX_DUP_LS_REFRESH_INTERVAL) {
need_refresh = false;
} else {
need_refresh = true;
}
} else {
need_refresh = true;
}
if (need_refresh && OB_SUCC(ret)) {
share::ObLSStatusInfo tmp_dup_ls_status_info;
share::ObLSStatusOperator ls_status_op;
if (OB_FAIL(ls_status_op.get_duplicate_ls_status_info(MTL_ID(), *GCTX.sql_proxy_,
dup_ls_status_info, share::OBCG_STORAGE))) {
tmp_dup_ls_status_info, share::OBCG_STORAGE))) {
if (OB_ENTRY_NOT_EXIST == ret) {
DUP_TABLE_LOG(DEBUG, "no duplicate ls", K(dup_ls_status_info));
DUP_TABLE_LOG(DEBUG, "no duplicate ls", K(tmp_dup_ls_status_info));
ret = OB_SUCCESS;
} else {
DUP_TABLE_LOG(WARN, "get duplicate ls status info failed", K(ret), K(dup_ls_status_info));
DUP_TABLE_LOG(WARN, "get duplicate ls status info failed", K(ret),
K(tmp_dup_ls_status_info));
}
} else {
DUP_TABLE_LOG(INFO, "find a duplicate ls", K(ret), K(dup_ls_status_info));
}
DUP_TABLE_LOG(DEBUG, "find a duplicate ls", K(ret), K(tmp_dup_ls_status_info));
if (OB_SUCC(ret) && dup_ls_status_info.is_duplicate_ls()) {
if (OB_FAIL(ret)) {
// do nothing
} else if (!tenant_dup_tablet_set.created()) {
if (OB_FAIL(tenant_dup_tablet_set.create(512))) {
DUP_TABLE_LOG(WARN, "init dup tablet cache failed", K(ret));
if (!tmp_dup_ls_status_info.is_valid() || !tmp_dup_ls_status_info.is_duplicate_ls()) {
ret = OB_ERR_UNEXPECTED;
DUP_TABLE_LOG(ERROR, "invalid tmp_dup_ls_status_info", K(ret), K(tmp_dup_ls_status_info));
} else {
if (min_dup_ls_status_info_.is_valid() && min_dup_ls_status_info_.is_duplicate_ls()
&& tmp_dup_ls_status_info.get_ls_id() != min_dup_ls_status_info_.get_ls_id()) {
DUP_TABLE_LOG(ERROR, "The min_dup_ls has already changed", K(ret),
K(tmp_dup_ls_status_info), K(min_dup_ls_status_info_));
}
if (OB_FAIL(min_dup_ls_status_info_.assign(tmp_dup_ls_status_info))) {
DUP_TABLE_LOG(WARN, "rewrite min_dup_ls_status_info_ failed", K(ret),
K(tmp_dup_ls_status_info), K(min_dup_ls_status_info_));
} else {
last_dup_ls_refresh_time_ = cur_time;
}
}
if (OB_FAIL(ret)) {
// do nothing
} else if (OB_FAIL(dup_schema_helper_.refresh_and_get_tablet_set(tenant_dup_tablet_set))) {
DUP_TABLE_LOG(WARN, "refresh dup tablet set failed", K(ret));
}
}
}
return ret;
}
int ObDupTabletScanTask::refresh_dup_tablet_schema_(const int64_t cur_time)
{
int ret = OB_SUCCESS;
if (OB_SUCC(ret) && min_dup_ls_status_info_.is_valid()
&& min_dup_ls_status_info_.is_duplicate_ls()) {
if (OB_FAIL(ret)) {
// do nothing
} else if (!tenant_schema_dup_tablet_set_.created()) {
if (OB_FAIL(tenant_schema_dup_tablet_set_.create(512))) {
DUP_TABLE_LOG(WARN, "init dup tablet cache failed", K(ret));
}
}
if (OB_FAIL(ret)) {
// do nothing
} else if (cur_time <= last_dup_schema_refresh_time_) {
// do nothing
} else if (OB_FAIL(
dup_schema_helper_.refresh_and_get_tablet_set(tenant_schema_dup_tablet_set_))) {
DUP_TABLE_LOG(WARN, "refresh dup tablet set failed", K(ret));
tenant_schema_dup_tablet_set_.clear();
} else {
last_dup_schema_refresh_time_ = cur_time;
}
}
return ret;
}
bool ObDupTabletScanTask::has_valid_dup_schema_() const
{
bool dup_schema_is_valid = false;
dup_schema_is_valid = min_dup_ls_status_info_.is_valid()
&& min_dup_ls_status_info_.is_duplicate_ls()
&& !tenant_schema_dup_tablet_set_.empty();
return dup_schema_is_valid;
}
int ObDupTabletScanTask::execute_for_dup_ls_()
{
int ret = OB_SUCCESS;
int tmp_ret = OB_SUCCESS;
TabletIDArray tablet_id_array;
ObTenantDupTabletSchemaHelper::TabletIDSet tenant_dup_tablet_set;
bool need_refreh_dup_schema = true;
ObLSHandle ls_handle;
share::ObLSStatusInfo dup_ls_status_info;
// compute scan task max execute interval
const int64_t cur_time = ObTimeUtility::fast_current_time();
if (cur_time - last_execute_time_ > 0) {
if (0 != last_execute_time_) {
max_execute_interval_ = max(max_execute_interval_, cur_time - last_execute_time_);
last_execute_time_ = cur_time;
if (cur_time - last_scan_task_succ_time_ > 0) {
if (0 != last_scan_task_succ_time_) {
if (max_execute_interval_ / 2 >= (cur_time - last_scan_task_succ_time_)) {
// Avoid residual excessive execution intervals in exceptional circumstances
ATOMIC_STORE(&max_execute_interval_, cur_time - last_scan_task_succ_time_);
} else {
ATOMIC_STORE(&max_execute_interval_,
max(max_execute_interval_, cur_time - last_scan_task_succ_time_));
}
} else {
last_execute_time_ = ObTimeUtility::fast_current_time();
}
}
if (OB_TMP_FAIL(refresh_dup_ls_(cur_time))) {
DUP_TABLE_LOG(WARN, "refresh dup ls failed", K(tmp_ret), KPC(this));
} else if (OB_TMP_FAIL(refresh_dup_tablet_schema_(cur_time))) {
DUP_TABLE_LOG(WARN, "refresh dup schema failed", K(tmp_ret), KPC(this));
}
if (OB_ISNULL(MTL(ObLSService *)) || OB_ISNULL(dup_loop_worker_)) {
ret = OB_INVALID_ARGUMENT;
DUP_TABLE_LOG(WARN, "invalid arguments", K(ret));
} else if (OB_FAIL(refresh_dup_tablet_schema_(need_refreh_dup_schema, tenant_dup_tablet_set,
dup_ls_status_info))) {
DUP_TABLE_LOG(WARN, "refresh dup table schema failed", K(ret));
} else if (!dup_ls_status_info.is_duplicate_ls()) {
} else if (!has_valid_dup_schema_()) {
DUP_TABLE_LOG(DEBUG, "refresh dup table schema failed", K(ret), KPC(this));
// do nothing
} else if (OB_FAIL(MTL(ObLSService *)
->get_ls(dup_ls_status_info.ls_id_, ls_handle, ObLSGetMod::TRANS_MOD))) {
DUP_TABLE_LOG(WARN, "get dup ls failed", K(ret), K(dup_ls_status_info));
} else if (OB_FAIL(
MTL(ObLSService *)
->get_ls(min_dup_ls_status_info_.ls_id_, ls_handle, ObLSGetMod::TRANS_MOD))) {
DUP_TABLE_LOG(WARN, "get dup ls failed", K(ret), KPC(this));
} else {
ObLS *cur_ls_ptr = ls_handle.get_ls();
@ -158,16 +226,9 @@ int ObDupTabletScanTask::execute_for_dup_ls_()
ret = OB_INVALID_ARGUMENT;
DUP_TABLE_LOG(WARN, "invalid ls ptr", K(ret), KP(cur_ls_ptr));
} else if (!cur_ls_ptr->get_dup_table_ls_handler()->is_master()) {
// #ifndef NDEBUG
DUP_TABLE_LOG(INFO,
"ls not leader",
K(cur_ls_ptr->get_ls_id()));
// #endif
} else if (OB_FAIL(refresh_dup_tablet_schema_(need_refreh_dup_schema, tenant_dup_tablet_set,
dup_ls_status_info))) {
DUP_TABLE_LOG(INFO, "refresh dup table schema failed", K(ret));
} else if (OB_FALSE_IT(need_refreh_dup_schema = false)) {
// do nothing
#ifndef NDEBUG
DUP_TABLE_LOG(INFO, "ls not leader", K(cur_ls_ptr->get_ls_id()));
#endif
} else {
storage::ObHALSTabletIDIterator ls_tablet_id_iter(cur_ls_ptr->get_ls_id(), true);
if (OB_FAIL(cur_ls_ptr->build_tablet_iter(ls_tablet_id_iter))) {
@ -180,7 +241,7 @@ int ObDupTabletScanTask::execute_for_dup_ls_()
int64_t refresh_time = ObTimeUtility::fast_current_time();
while (OB_SUCC(ls_tablet_id_iter.get_next_tablet_id(tmp_tablet_id))) {
is_dup_tablet = false;
ret = tenant_dup_tablet_set.exist_refactored(tmp_tablet_id);
ret = tenant_schema_dup_tablet_set_.exist_refactored(tmp_tablet_id);
if (OB_HASH_EXIST == ret) {
is_dup_tablet = true;
ret = OB_SUCCESS;
@ -193,7 +254,9 @@ int ObDupTabletScanTask::execute_for_dup_ls_()
K(ret), K(cur_ls_ptr->get_ls_id()), K(tmp_tablet_id));
}
if (!cur_ls_ptr->get_dup_table_ls_handler()->is_inited() && !is_dup_tablet) {
if (OB_FAIL(ret)) {
// do nothing
} else if (!cur_ls_ptr->get_dup_table_ls_handler()->is_inited() && !is_dup_tablet) {
// do nothing
} else if (OB_FAIL(cur_ls_ptr->get_dup_table_ls_handler()->init(is_dup_tablet))
&& OB_INIT_TWICE != ret) {
@ -210,31 +273,31 @@ int ObDupTabletScanTask::execute_for_dup_ls_()
}
if (OB_ITER_END == ret) {
// ret = OB_SUCCESS;
if (OB_FAIL(cur_ls_ptr->get_dup_table_ls_handler()->gc_temporary_dup_tablets(
refresh_time, max_execute_interval_))) {
DUP_TABLE_LOG(WARN, "ls gc dup_tablet failed", KR(ret), K(refresh_time),
K(max_execute_interval_));
}
ret = OB_SUCCESS;
}
}
}
// refresh dup_table_ls on leader and follower
if (!cur_ls_ptr->get_dup_table_ls_handler()->check_tablet_set_exist()) {
// refresh dup_table_ls on leader and follower
if (!cur_ls_ptr->get_dup_table_ls_handler()->is_inited()
|| !cur_ls_ptr->get_dup_table_ls_handler()->check_tablet_set_exist()) {
// do nothing
} else if (OB_FAIL(dup_loop_worker_->append_dup_table_ls(cur_ls_ptr->get_ls_id()))) {
} else if (OB_TMP_FAIL(dup_loop_worker_->append_dup_table_ls(cur_ls_ptr->get_ls_id()))) {
DUP_TABLE_LOG(WARN, "refresh dup_table ls failed", K(ret));
}
}
if (tenant_dup_tablet_set.created()) {
tenant_dup_tablet_set.destroy();
}
if (OB_FAIL(ret)) {
DUP_TABLE_LOG(WARN, "scan dup ls to find dup_tablet failed", KR(ret));
} else {
ATOMIC_STORE(&last_scan_task_succ_time_, cur_time);
}
#ifndef NDEBUG
DUP_TABLE_LOG(INFO, "execute dup table scan task", KPC(this));
#else
#endif
return ret;
}
@ -453,15 +516,6 @@ int ObDupTableLSHandler::safe_to_destroy(bool &is_dup_table_handler_safe)
void ObDupTableLSHandler::destroy() { reset(); }
// int ObDupTableLSHandler::offline()
// {
// int ret = OB_SUCCESS;
// }
// return ret;
// }
//
// int ObDupTableLSHandler::online() {}
void ObDupTableLSHandler::reset()
{
// ATOMIC_STORE(&is_inited_, false);
@ -502,38 +556,6 @@ void ObDupTableLSHandler::reset()
}
}
// bool ObDupTableLSHandler::is_master()
// {
// bool sub_master = true;
// if (OB_NOT_NULL(ts_sync_mgr_ptr_)) {
// sub_master = sub_master && ts_sync_mgr_ptr_->is_master();
// }
// if (OB_NOT_NULL(lease_mgr_ptr_)) {
// sub_master = sub_master && lease_mgr_ptr_->is_master();
// }
// if (OB_NOT_NULL(tablets_mgr_ptr_)) {
// sub_master = sub_master && tablets_mgr_ptr_->is_master();
// }
//
// return (ATOMIC_LOAD(&is_master_)) && sub_master;
// }
// bool ObDupTableLSHandler::is_follower()
// {
// bool sub_not_master = true;
// if (OB_NOT_NULL(ts_sync_mgr_ptr_)) {
// sub_not_master = sub_not_master && !ts_sync_mgr_ptr_->is_master();
// }
// if (OB_NOT_NULL(lease_mgr_ptr_)) {
// sub_not_master = sub_not_master && !lease_mgr_ptr_->is_master();
// }
// if (OB_NOT_NULL(tablets_mgr_ptr_)) {
// sub_not_master = sub_not_master && !tablets_mgr_ptr_->is_master();
// }
//
// return (!ATOMIC_LOAD(&is_master_)) && sub_not_master;
// }
bool ObDupTableLSHandler::is_inited()
{
SpinRLockGuard r_init_guard(init_rw_lock_);
@ -542,21 +564,6 @@ bool ObDupTableLSHandler::is_inited()
bool ObDupTableLSHandler::is_master() { return ls_state_helper_.is_leader_serving(); }
// bool ObDupTableLSHandler::is_online()
// {
// bool sub_online = true;
// if (OB_NOT_NULL(ts_sync_mgr_ptr_)) {
// sub_online = sub_online && !ts_sync_mgr_ptr_->is_master();
// }
// if (OB_NOT_NULL(lease_mgr_ptr_)) {
// sub_online = sub_online && !lease_mgr_ptr_->is_master();
// }
// if (OB_NOT_NULL(tablets_mgr_ptr_)) {
// sub_online = sub_online && !tablets_mgr_ptr_->is_master();
// }
//
// }
int ObDupTableLSHandler::ls_loop_handle()
{
int ret = OB_SUCCESS;
@ -581,19 +588,27 @@ int ObDupTableLSHandler::ls_loop_handle()
if (OB_ISNULL(log_operator_) || !log_operator_->is_busy()) {
// handle lease request and collect follower info
DupTableTsInfo min_lease_ts_info;
if (OB_FAIL(get_min_lease_ts_info_(min_lease_ts_info))) {
DUP_TABLE_LOG(WARN, "get min lease ts info failed", K(ret), K(min_lease_ts_info));
if (OB_TMP_FAIL(get_min_lease_ts_info_(min_lease_ts_info))) {
DUP_TABLE_LOG(WARN, "get min lease ts info failed", K(tmp_ret), K(min_lease_ts_info));
// try confirm tablets and check tablet need log
} else if (OB_FAIL(try_to_confirm_tablets_(min_lease_ts_info.max_replayed_scn_))) {
DUP_TABLE_LOG(WARN, "try confirm tablets failed", K(ret), K(min_lease_ts_info));
} else {
// submit lease log
} else if (OB_TMP_FAIL(try_to_confirm_tablets_(min_lease_ts_info.max_replayed_scn_))) {
DUP_TABLE_LOG(WARN, "try confirm tablets failed", K(tmp_ret), K(min_lease_ts_info));
}
if (OB_TMP_FAIL(tablets_mgr_ptr_->scan_readable_set_for_gc(
ATOMIC_LOAD(&interface_stat_.dup_table_ls_leader_takeover_ts_)))) {
DUP_TABLE_LOG(WARN, "scan readable set failed", K(tmp_ret));
}
// submit lease log
if(OB_FAIL(ret))
{
} else
if (OB_ISNULL(log_operator_)) {
ret = OB_INVALID_ARGUMENT;
DUP_TABLE_LOG(WARN, "invalid log operator ptr", K(ret), KP(log_operator_));
} else if (OB_FAIL(log_operator_->submit_log_entry())) {
DUP_TABLE_LOG(WARN, "submit dup table log entry failed", K(ret));
}
} else if (OB_FAIL(log_operator_->submit_log_entry())) {
DUP_TABLE_LOG(WARN, "submit dup table log entry failed", K(ret));
}
}
@ -1359,6 +1374,9 @@ int ObDupTableLSHandler::switch_to_leader()
if (OB_FAIL(ls_state_helper_.state_change_succ(ObDupTableLSRoleState::LS_TAKEOVER_SUCC,
restore_state_container))) {
DUP_TABLE_LOG(ERROR, "change ls role state error", K(ret), KPC(this));
} else {
ATOMIC_STORE(&interface_stat_.dup_table_ls_leader_takeover_ts_,
ObTimeUtility::fast_current_time());
}
} else {
tmp_ret = OB_SUCCESS;
@ -1580,6 +1598,8 @@ int ObDupTableLSHandler::get_min_lease_ts_info_(DupTableTsInfo &min_ts_info)
{
int ret = OB_SUCCESS;
int ts_info_err_ret = OB_SUCCESS;
LeaseAddrArray lease_valid_array;
min_ts_info.reset();
@ -1599,6 +1619,10 @@ int ObDupTableLSHandler::get_min_lease_ts_info_(DupTableTsInfo &min_ts_info)
for (int64_t i = 0; OB_SUCC(ret) && i < lease_valid_array.count(); i++) {
if (OB_FAIL(ts_sync_mgr_ptr_->get_cache_ts_info(lease_valid_array[i], tmp_ts_info))) {
DUP_TABLE_LOG(WARN, "get cache ts info failed", K(ret), K(lease_valid_array[i]));
if (OB_HASH_NOT_EXIST == ret) {
ts_info_err_ret = ret;
ret = OB_SUCCESS;
}
} else {
min_ts_info.max_replayed_scn_ =
share::SCN::min(min_ts_info.max_replayed_scn_, tmp_ts_info.max_replayed_scn_);
@ -1610,8 +1634,12 @@ int ObDupTableLSHandler::get_min_lease_ts_info_(DupTableTsInfo &min_ts_info)
}
}
if (OB_SUCC(ret) && ts_info_err_ret != OB_SUCCESS) {
ret = ts_info_err_ret;
}
if (OB_FAIL(ret)) {
DUP_TABLE_LOG(INFO, "get min lease ts info failed", K(ret), K(min_ts_info),
DUP_TABLE_LOG(WARN, "get min lease ts info failed", K(ret), K(ts_info_err_ret), K(min_ts_info),
K(lease_valid_array));
}
return ret;

View File

@ -17,6 +17,7 @@
#include "storage/tx/ob_dup_table_lease.h"
#include "storage/tx/ob_trans_define.h"
#include "storage/tx/ob_dup_table_stat.h"
#include "share/ls/ob_ls_status_operator.h"
namespace oceanbase
{
@ -57,7 +58,8 @@ public:
class ObDupTabletScanTask : public ObITimeoutTask
{
public:
static const int64_t DUP_TABLET_SCAN_INTERVAL = 10 * 1000 * 1000; // 10s
static const int64_t DUP_TABLET_SCAN_INTERVAL = 10 * 1000 * 1000; // 10s
static const int64_t MAX_DUP_LS_REFRESH_INTERVAL = 60 * 60 * 1000 * 1000L; // 60min
public:
ObDupTabletScanTask() { reset(); }
~ObDupTabletScanTask() { destroy(); }
@ -70,11 +72,26 @@ public:
void runTimerTask();
uint64_t hash() const { return tenant_id_; }
int64_t get_max_exec_interval() const { return ATOMIC_LOAD(&max_execute_interval_); }
int64_t get_last_scan_task_succ_ts() const { return ATOMIC_LOAD(&last_scan_task_succ_time_); }
TO_STRING_KV(K(tenant_id_),
KP(dup_table_scan_timer_),
KP(dup_loop_worker_),
K(min_dup_ls_status_info_),
K(tenant_schema_dup_tablet_set_.size()),
K(scan_task_execute_interval_),
K(last_dup_ls_refresh_time_),
K(last_dup_schema_refresh_time_),
K(last_scan_task_succ_time_),
K(max_execute_interval_));
private:
int execute_for_dup_ls_();
int refresh_dup_tablet_schema_(bool need_refresh,
ObTenantDupTabletSchemaHelper::TabletIDSet &tenant_dup_tablet_set,
share::ObLSStatusInfo &dup_ls_status_info);
int refresh_dup_ls_(const int64_t cur_time);
int refresh_dup_tablet_schema_(const int64_t cur_time);
bool has_valid_dup_schema_() const;
private:
ObTenantDupTabletSchemaHelper dup_schema_helper_;
@ -82,7 +99,16 @@ private:
int64_t tenant_id_;
ObDupTableLeaseTimer *dup_table_scan_timer_;
ObDupTableLoopWorker *dup_loop_worker_;
int64_t last_execute_time_;
share::ObLSStatusInfo min_dup_ls_status_info_; // min_ls_id
ObTenantDupTabletSchemaHelper::TabletIDSet tenant_schema_dup_tablet_set_;
int64_t scan_task_execute_interval_;
int64_t last_dup_ls_refresh_time_;
int64_t last_dup_schema_refresh_time_;
int64_t last_scan_task_succ_time_;
int64_t max_execute_interval_;
};

View File

@ -230,6 +230,7 @@ public:
ObIDupTableRpc *get_dup_table_rpc() { return dup_table_rpc_; }
ObDupTableRpc &get_dup_table_rpc_impl() { return dup_table_rpc_impl_; }
ObDupTableLoopWorker &get_dup_table_loop_worker() { return dup_table_loop_worker_; }
const ObDupTabletScanTask &get_dup_table_scan_task() { return dup_tablet_scan_task_; }
ObILocationAdapter *get_location_adapter() { return location_adapter_; }
common::ObMySQLProxy *get_mysql_proxy() { return GCTX.sql_proxy_; }
bool is_running() const { return is_running_; }