fix tablet status cache for weak read scenario

This commit is contained in:
hiddenbomb 2023-06-30 04:12:23 +00:00 committed by ob-robot
parent cd8fb2e17e
commit 2776120751
5 changed files with 145 additions and 22 deletions

View File

@ -179,14 +179,19 @@ TEST_F(TestTabletStatusCache, weak_read)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 20/*snapshot*/);
ASSERT_EQ(OB_SNAPSHOT_DISCARDED, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, but snapshot is not max scn, not supported
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, 20/*snapshot*/);
ASSERT_EQ(OB_NOT_SUPPORTED, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_READABLE_COMMITED, snapshot version is bigger than create commit version, return OB_SUCCESS
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 60/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(tablet->tablet_status_cache_.is_valid());
}
TEST_F(TestTabletStatusCache, get_transfer_out_tablet)
@ -231,20 +236,26 @@ TEST_F(TestTabletStatusCache, get_transfer_out_tablet)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SCHEMA_EAGAIN, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, allow to get TRANSFER_OUT status tablet
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
tablet_handle.reset();
// read snapshot: 80. not max scn, return OB_NOT_SUPPORTED
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, 80/*snapshot*/);
ASSERT_EQ(OB_NOT_SUPPORTED, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// read snapshot: 80. less than transfer scn
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// check tablet status cache
{
@ -266,24 +277,32 @@ TEST_F(TestTabletStatusCache, get_transfer_out_tablet)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_TABLET_NOT_EXIST, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, allow to get tablet
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
tablet_handle.reset();
// mode is READ_READABLE_COMMITED, read snapshot 80 less than transfer scn 100, allow to get tablet
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 80/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, snapshot is not max scn, return OB_NOT_SUPPORTED
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, 80/*snapshot*/);
ASSERT_EQ(OB_NOT_SUPPORTED, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, allow to get tablet
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// begin transfer out deleted transaction
user_data.tablet_status_ = ObTabletStatus::TRANSFER_OUT_DELETED;
@ -309,10 +328,13 @@ TEST_F(TestTabletStatusCache, get_transfer_out_tablet)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_TABLET_NOT_EXIST, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, allow to get tablet whose snapshot status is transfer out
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// transaction commit
commit_scn = share::SCN::plus(min_scn, 220);
@ -322,10 +344,13 @@ TEST_F(TestTabletStatusCache, get_transfer_out_tablet)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_TABLET_NOT_EXIST, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// mode is READ_ALL_COMMITED, snapshot status is transfer out deleted, not allow to get
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_ALL_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
// begin transfer out deleted transaction
user_data.tablet_status_ = ObTabletStatus::DELETED;
@ -349,6 +374,7 @@ TEST_F(TestTabletStatusCache, get_transfer_out_tablet)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 100/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
ObLSHandle ls_handle;
ret = MTL(ObLSService*)->get_ls(LS_ID, ls_handle, ObLSGetMod::STORAGE_MOD);
@ -416,6 +442,7 @@ TEST_F(TestTabletStatusCache, get_transfer_deleted)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 100/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
ret = ls->get_tablet_svr()->update_tablet_to_empty_shell(tablet_id);
ASSERT_EQ(OB_SUCCESS, ret);
@ -423,6 +450,78 @@ TEST_F(TestTabletStatusCache, get_transfer_deleted)
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 100/*snapshot*/);
ASSERT_EQ(OB_TABLET_NOT_EXIST, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
}
TEST_F(TestTabletStatusCache, get_transfer_out_deleted)
{
int ret = OB_SUCCESS;
// create tablet
const common::ObTabletID tablet_id(ObTimeUtility::fast_current_time() % 10000000000000);
ObTabletHandle tablet_handle;
ret = create_tablet(tablet_id, tablet_handle);
ASSERT_EQ(OB_SUCCESS, ret);
ObTablet *tablet = tablet_handle.get_obj();
ASSERT_NE(nullptr, tablet);
ObLSHandle ls_handle;
ret = MTL(ObLSService*)->get_ls(LS_ID, ls_handle, ObLSGetMod::STORAGE_MOD);
ASSERT_EQ(OB_SUCCESS, ret);
ObLS *ls = ls_handle.get_ls();
ASSERT_NE(nullptr, ls);
const ObTabletMapKey key(LS_ID, tablet_id);
tablet_handle.reset();
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, ObTransVersion::MAX_TRANS_VERSION/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(tablet->tablet_status_cache_.is_valid());
ObTabletCreateDeleteMdsUserData user_data;
share::SCN min_scn;
min_scn.set_min();
// set transfer scn
// create commit scn: 50
// transfer scn: 100
// delete commit scn: 200
// begin transfer out deleted transaction
user_data.tablet_status_ = ObTabletStatus::TRANSFER_OUT_DELETED;
user_data.transfer_scn_ = share::SCN::plus(min_scn, 100);
user_data.transfer_ls_id_ = share::ObLSID(1010);
user_data.data_type_ = ObTabletMdsUserDataType::FINISH_TRANSFER_OUT;
user_data.create_commit_scn_ = share::SCN::plus(min_scn, 50);
user_data.create_commit_version_ = 50;
user_data.delete_commit_scn_ = share::SCN::plus(min_scn, 200);
user_data.delete_commit_version_ = 200;
mds::MdsCtx ctx(mds::MdsWriter(transaction::ObTransID(789)));
ret = tablet->set(user_data, ctx);
ASSERT_EQ(OB_SUCCESS, ret);
share::SCN commit_scn = share::SCN::plus(min_scn, 120);
ctx.single_log_commit(commit_scn, commit_scn);
// disable cache
{
SpinWLockGuard guard(tablet->mds_cache_lock_);
tablet->tablet_status_cache_.reset();
}
// mock weak read
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 210/*snapshot*/);
ASSERT_EQ(OB_TABLET_NOT_EXIST, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, 100/*snapshot*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
ret = ObTabletCreateDeleteHelper::check_and_get_tablet(key, tablet_handle, 1 * 1000 * 1000/*timeout_us*/,
ObMDSGetTabletMode::READ_READABLE_COMMITED, INT64_MAX/*snapshot*/);
ASSERT_EQ(OB_TABLET_NOT_EXIST, ret);
ASSERT_TRUE(!tablet->tablet_status_cache_.is_valid());
}
TEST_F(TestTabletStatusCache, get_read_all_committed_tablet)
@ -559,6 +658,29 @@ TEST_F(TestTabletStatusCache, get_read_all_committed_tablet)
ASSERT_EQ(OB_SUCCESS, ret);
}
// TODO(@bowen.gbw): refactor test cases to cover all scene
/*
TEST_F(TestTabletStatusCache, transfer_src_ls_read_all_committed)
{
}
TEST_F(TestTabletStatusCache, transfer_dst_ls_read_all_committed)
{
}
TEST_F(TestTabletStatusCache, transfer_src_ls_read_readable_committed)
{
}
TEST_F(TestTabletStatusCache, transfer_dst_ls_read_readable_committed)
{
}
*/
} // namespace storage
} // namespace oceanbase

View File

@ -188,7 +188,11 @@ int ObTabletCreateDeleteHelper::check_status_for_new_mds(
LOG_WARN("failed to check read snapshot by commit version", K(ret), K(ls_id), K(tablet_id), K(snapshot_version), K(user_data));
}
if (OB_SUCC(ret) && ObTabletStatus::TRANSFER_OUT != tablet_status && user_data.is_valid()) {
if (OB_FAIL(ret)) {
} else if (ObTabletStatus::NORMAL == tablet_status
&& user_data.is_valid()
&& ObTabletStatus::NORMAL == user_data.tablet_status_) {
// we only set tablet status cache when current status NORMAL and create transaction is COMIITTED
tablet_status_cache.set_value(user_data);
}

View File

@ -262,7 +262,6 @@ int ObTabletFinishTransferOutReplayExecutor::check_src_transfer_tablet_(
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tablet tx data is unexpected",
K(ret),
K(ObTabletStatus::get_str(user_data.tablet_status_)),
K(transfer_seq),
K(user_data),
KPC(tablet));
@ -384,7 +383,6 @@ int ObTabletFinishTransferOutHelper::inner_check_transfer_out_tablet_validity_(
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tablet tx data is unexpected",
K(ret),
K(ObTabletStatus::get_str(user_data.tablet_status_)),
K(transfer_seq),
K(user_data),
KPC(tablet));
@ -711,10 +709,7 @@ int ObTabletFinishTransferInReplayExecutor::check_dest_transfer_tablet_(
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("tablet tx data is unexpected",
K(ret),
K(user_data),
K(scn_),
K(tablet->get_tablet_meta()),
K(ObTabletStatus::get_str(user_data.tablet_status_)),
K(transfer_seq),
K(user_data),
KPC(tablet));
@ -997,7 +992,6 @@ int ObTabletFinishTransferInHelper::inner_check_transfer_in_tablet_validity_(
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("tablet tx data is unexpected",
K(ret),
K(ObTabletStatus::get_str(data.tablet_status_)),
K(transfer_seq),
K(data),
KPC(tablet));

View File

@ -24,6 +24,8 @@ namespace storage
ObTabletStatus::ObTabletStatus()
: status_(Status::MAX)
{
static_assert(sizeof(status_str_array_) / sizeof(const char *) == static_cast<uint8_t>(ObTabletStatus::MAX) + 1,
"status str array size does not equal to enum value count");
}
ObTabletStatus::ObTabletStatus(const Status &status)
@ -31,24 +33,13 @@ ObTabletStatus::ObTabletStatus(const Status &status)
{
}
static const char *TABLET_STATUS_STRS[] = {
"CREATING",
"NORMAL",
"DELETING",
"DELETED",
"TRANSFER_OUT",
"TRANSFER_IN",
"TRANSFER_OUT_DELETED",
};
const char *ObTabletStatus::get_str(const ObTabletStatus &status)
{
const char *str = NULL;
if (status.status_ < 0 || status.status_ >= ObTabletStatus::MAX) {
const char *str = nullptr;
if (status.status_ > ObTabletStatus::MAX) {
str = "UNKNOWN";
} else {
str = TABLET_STATUS_STRS[status.status_];
str = status_str_array_[status.status_];
}
return str;
}

View File

@ -53,8 +53,20 @@ public:
int deserialize(const char *buf, const int64_t len, int64_t &pos);
int64_t get_serialize_size() const;
TO_STRING_KV(K_(status));
TO_STRING_KV("val", static_cast<uint8_t>(status_),
"str", get_str(*this));
private:
static constexpr const char *status_str_array_[] = {
"CREATING",
"NORMAL",
"DELETING",
"DELETED",
"TRANSFER_OUT",
"TRANSFER_IN",
"TRANSFER_OUT_DELETED",
"MAX"
};
Status status_;
};