Revert [MDS] optimize tablet mds truncate lock behavior and add it when replay

This commit is contained in:
fengdeyiji
2025-02-19 03:46:03 +00:00
committed by ob-robot
parent 6afa63d29b
commit 2ff302df92
8 changed files with 69 additions and 179 deletions

View File

@ -65,7 +65,6 @@ int ObTabletReplayExecutor::execute(const share::SCN &scn, const share::ObLSID &
ObTablet *tablet = nullptr;
ObLSHandle ls_handle;
ObLSService *ls_service = nullptr;
ObTabletMdsExclusiveLockGuard mds_lock_guard;
if (OB_UNLIKELY(!is_inited_)) {
ret = OB_NOT_INIT;
CLOG_LOG(WARN, "replay executor not init", KR(ret), K_(is_inited));
@ -98,7 +97,7 @@ int ObTabletReplayExecutor::execute(const share::SCN &scn, const share::ObLSID &
} else {
CLOG_LOG(WARN, "failed to check restore status", K(ret), K(ls_id), K(scn));
}
} else if (CLICK_FAIL(check_can_skip_replay_to_mds_(scn, tablet_handle, can_skip_replay, mds_lock_guard))) {
} else if (CLICK_FAIL(check_can_skip_replay_to_mds_(scn, tablet_handle, can_skip_replay))) {
CLOG_LOG(WARN, "failed to check can skip reply to mds", K(ret), K(ls_id), K(scn), K(tablet_handle));
} else if (can_skip_replay) {
//do nothing
@ -187,8 +186,7 @@ int ObTabletReplayExecutor::replay_check_restore_status_(storage::ObTabletHandle
int ObTabletReplayExecutor::check_can_skip_replay_to_mds_(
const share::SCN &scn,
storage::ObTabletHandle &tablet_handle,
bool &can_skip,
ObTabletMdsExclusiveLockGuard &mds_lock_guard)
bool &can_skip)
{
int ret = OB_SUCCESS;
ObTablet *tablet = nullptr;
@ -202,17 +200,11 @@ int ObTabletReplayExecutor::check_can_skip_replay_to_mds_(
} else if (OB_ISNULL(tablet = tablet_handle.get_obj())) {
ret = OB_ERR_UNEXPECTED;
CLOG_LOG(WARN, "tablet should not be NULL", K(ret), KP(tablet));
} else if (OB_ISNULL(tablet->get_tablet_pointer_())) {
ret = OB_ERR_UNEXPECTED;
CLOG_LOG(WARN, "tablet pointer should not be NULL", K(ret), KP(tablet));
} else if (tablet->get_tablet_meta().mds_checkpoint_scn_ >= scn) {
can_skip = true;
CLOG_LOG(INFO, "skip replay to mds", KPC(tablet), K(scn));
} else {
mds_lock_guard.set(tablet->get_tablet_pointer_()->get_mds_truncate_lock());
if (tablet->get_tablet_meta().mds_checkpoint_scn_ >= scn) {
can_skip = true;
CLOG_LOG(INFO, "skip replay to mds", KPC(tablet), K(scn));
} else {
can_skip = false;
}
can_skip = false;
}
return ret;
}

View File

@ -139,8 +139,7 @@ private:
int check_can_skip_replay_to_mds_(
const share::SCN &scn,
storage::ObTabletHandle &tablet_handle,
bool &can_skip,
ObTabletMdsExclusiveLockGuard &mds_lock_guard);
bool &can_skip);
// The replay of multi-source log modified by ObTabletCreateDeleteMdsUserData needs to be filtered by tablet_change_checkpoint_scn
int check_can_skip_replay_(
const storage::ObLSHandle &ls_handle,

View File

@ -3938,13 +3938,13 @@ int ObLSTabletService::build_tablet_with_batch_tables(
if (param.release_mds_scn_.is_min()) {
//do nothing
} else {
pointer->get_mds_truncate_lock().exclusive_lock(); // need use try lock, and expand critical area
TabletMdsLockGuard<storage::LockMode::EXCLUSIVE> guard;
pointer->get_mds_truncate_lock_guard(guard);
if (OB_FAIL(pointer->release_mds_nodes_redo_scn_below(tablet_id, param.release_mds_scn_))) {
//overwrite ret
LOG_WARN("failed to relase mds node redo scn below", K(ret), K(tablet_id), "release mds scn", param.release_mds_scn_);
ret = OB_RELEASE_MDS_NODE_ERROR;
}
pointer->get_mds_truncate_lock().exclusive_unlock();
}
time_guard.click("ReleaseMDS");

View File

@ -1,104 +0,0 @@
/**
* 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.
*/
#ifndef OCEANBASE_STORAGE_OB_TABLET_MDS_TRUNCATE_LOCK_H
#define OCEANBASE_STORAGE_OB_TABLET_MDS_TRUNCATE_LOCK_H
#include "deps/oblib/src/lib/lock/ob_spin_rwlock.h"
namespace oceanbase
{
namespace storage
{
struct ObTabletMDSTruncateLock : public common::SpinRWLock
{
ObTabletMDSTruncateLock() : lock_times_(0), lock_owner_(0) {}
bool try_exclusive_lock() {
bool ret = false;
if (ATOMIC_LOAD(&lock_owner_) == ob_gettid()) {
ret = true;
} else if (OB_LIKELY(ret = common::SpinRWLock::try_wrlock())) {
ATOMIC_STORE(&lock_owner_, ob_gettid());
}
if (OB_LIKELY(ret)) {
ATOMIC_AAF(&lock_times_, 1);
}
return ret;
}
void exclusive_lock() {
if (!is_exclusive_locked_by_self()) {
common::SpinRWLock::wrlock();
ATOMIC_STORE(&lock_owner_, ob_gettid());
}
ATOMIC_AAF(&lock_times_, 1);
}
void exclusive_unlock() {
uint32_t lock_times = ATOMIC_LOAD(&lock_times_);
if (OB_UNLIKELY(ATOMIC_LOAD(&lock_owner_) != ob_gettid()) || lock_times <= 0) {
ob_abort();
} else if (ATOMIC_AAF(&lock_times_, -1) == 0) {
common::SpinRWLock::wrunlock();
ATOMIC_STORE(&lock_owner_, 0);
}
}
bool is_exclusive_locked_by_self() {
return ATOMIC_LOAD(&lock_owner_) == ob_gettid();
}
private:
uint32_t lock_times_;
int64_t lock_owner_;
};
struct ObTabletMdsSharedLockGuard
{
ObTabletMdsSharedLockGuard() : lock_(nullptr) {}
ObTabletMdsSharedLockGuard(ObTabletMDSTruncateLock &lock) : lock_(nullptr) {
if (lock.is_exclusive_locked_by_self()) {
// do nothing
} else {
lock.rdlock();
lock_ = &lock;
}
}
~ObTabletMdsSharedLockGuard() {
if (lock_) {
lock_->rdunlock();
}
}
ObTabletMDSTruncateLock *lock_;
};
struct ObTabletMdsExclusiveLockGuard
{
ObTabletMdsExclusiveLockGuard() : lock_(nullptr) {}
ObTabletMdsExclusiveLockGuard(ObTabletMDSTruncateLock &lock) : lock_(nullptr) { set(lock); }
void set(ObTabletMDSTruncateLock &lock) {
if (OB_UNLIKELY(lock_)) {
ob_abort();
} else {
lock.exclusive_lock();
lock_ = &lock;
}
}
~ObTabletMdsExclusiveLockGuard() {
if (lock_) {
lock_->exclusive_unlock();
}
}
ObTabletMDSTruncateLock *lock_;
};
}
}
#endif

View File

@ -43,7 +43,7 @@ ObTabletPointer::ObTabletPointer()
auto_part_size_(OB_INVALID_SIZE)
{
#if defined(__x86_64__) && !defined(ENABLE_OBJ_LEAK_CHECK)
static_assert(sizeof(ObTabletPointer) == 376, "The size of ObTabletPointer will affect the meta memory manager, and the necessity of adding new fields needs to be considered.");
static_assert(sizeof(ObTabletPointer) == 360, "The size of ObTabletPointer will affect the meta memory manager, and the necessity of adding new fields needs to be considered.");
#endif
}

View File

@ -21,7 +21,6 @@
#include "storage/multi_data_source/mds_table_handler.h"
#include "storage/ob_i_memtable_mgr.h"
#include "storage/ob_protected_memtable_mgr_handle.h"
#include "ob_tablet_mds_truncate_lock.h"
namespace oceanbase
{
@ -88,6 +87,30 @@ public:
int64_t backup_bytes_;
};
enum class LockMode { SHARE, EXCLUSIVE };
template <LockMode mode>
struct TabletMdsLockGuard
{
TabletMdsLockGuard() : lock_(nullptr) {}
TabletMdsLockGuard(mds::MdsLock &lock) : lock_(&lock) {
if (mode == LockMode::SHARE) {
lock_->rdlock();
} else if (mode == LockMode::EXCLUSIVE) {
lock_->wrlock();
}
}
~TabletMdsLockGuard() {
if (lock_) {
if (mode == LockMode::SHARE) {
lock_->rdunlock();
} else if (mode == LockMode::EXCLUSIVE) {
lock_->wrunlock();
}
}
}
mds::MdsLock *lock_;
};
class ObTabletPointer final
{
friend class ObTablet;
@ -96,6 +119,15 @@ class ObTabletPointer final
friend class ObTabletResidentInfo;
friend class ObTabletPointerMap;
friend class ObFlyingTabletPointerMap;
public:
template <LockMode MODE>
void get_mds_truncate_lock_guard(TabletMdsLockGuard<MODE> &lock_guard) const {
if (OB_ISNULL(lock_guard.lock_)) {
new (&lock_guard) TabletMdsLockGuard<MODE>(mds_lock_);
} else {
ob_abort();// just for defence
}
}
public:
ObTabletPointer();
ObTabletPointer(const ObLSHandle &ls_handle,
@ -141,7 +173,6 @@ public:
public:
bool get_initial_state() const;
ObTabletResidentInfo get_tablet_resident_info(const ObTabletMapKey &key) const;
ObTabletMDSTruncateLock &get_mds_truncate_lock() const { return mds_lock_; }
void set_initial_state(const bool initial_state);
int create_ddl_kv_mgr(const share::ObLSID &ls_id, const ObTabletID &tablet_id, ObDDLKvMgrHandle &ddl_kv_mgr_handle);
void get_ddl_kv_mgr(ObDDLKvMgrHandle &ddl_kv_mgr_handle);
@ -159,8 +190,8 @@ public:
// NOTICE1: input arg mds_ckpt_scn must be very carefully picked,
// this scn should be calculated by mds table when flush,
// and dumped to mds sstable, recorded on tablet
// otherwise mds data will lost
// NOTICE2: this call must be protected by ObTabletMdsSharedLockGuard EXCLUSIVE mode
// ohterwise mds data will lost
// NOTICE2: this call must be protected by TabletMdsLockGuard<LockMode::EXCLUSIVE>
int release_mds_nodes_redo_scn_below(const ObTabletID &tablet_id, const share::SCN &mds_ckpt_scn);
ObLS *get_ls() const;
// the RW operations of tablet_attr are protected by lock guard of tablet_map_
@ -188,12 +219,12 @@ private:
bool initial_state_; // 1B
bool flying_; // 1B
ObByteLock ddl_kv_mgr_lock_; // 1B
mutable ObTabletMDSTruncateLock mds_lock_;// 24B
mutable mds::MdsLock mds_lock_;// 12B
mds::ObMdsTableHandler mds_table_handler_;// 48B
ObTablet *old_version_chain_; // 8B
ObTabletAttr attr_; // 32B // protected by rw lock of tablet_map_
int64_t auto_part_size_; // 8B
DISALLOW_COPY_AND_ASSIGN(ObTabletPointer); // 376B
DISALLOW_COPY_AND_ASSIGN(ObTabletPointer); // 360B
};
struct ObTabletResidentInfo final

View File

@ -179,11 +179,12 @@ int ObITabletMdsInterface::set(T &&data, mds::MdsCtx &ctx, const int64_t lock_ti
MDS_TG(10_ms);
int ret = OB_SUCCESS;
mds::MdsTableHandle handle;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
if (MDS_FAIL(get_mds_table_handle_(handle, true))) {
MDS_LOG_SET(WARN, "failed to get_mds_table");
} else if (!handle.is_valid()) {
@ -205,11 +206,12 @@ int ObITabletMdsInterface::replay(T &&data, mds::MdsCtx &ctx, const share::SCN &
#define PRINT_WRAPPER KR(ret), K(*this), K(data), K(ctx), K(scn)
MDS_TG(10_ms);
int ret = OB_SUCCESS;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
if (scn < get_tablet_meta_().mds_checkpoint_scn_) {
MDS_LOG_SET(TRACE, "no need do replay");
} else {
@ -237,11 +239,12 @@ int ObITabletMdsInterface::set(const Key &key, Value &&data, mds::MdsCtx &ctx, c
MDS_TG(10_ms);
int ret = OB_SUCCESS;
mds::MdsTableHandle handle;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
if (CLICK_FAIL(get_mds_table_handle_(handle, true))) {
MDS_LOG_SET(WARN, "failed to get_mds_table");
} else if (!handle.is_valid()) {
@ -267,11 +270,12 @@ int ObITabletMdsInterface::replay(const Key &key,
#define PRINT_WRAPPER KR(ret), K(*this), K(key), K(mds), K(ctx), K(scn)
MDS_TG(10_ms);
int ret = OB_SUCCESS;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
if (scn < get_tablet_meta_().mds_checkpoint_scn_) {
MDS_LOG_SET(TRACE, "no need do replay");
} else {
@ -300,11 +304,12 @@ int ObITabletMdsInterface::remove(const Key &key, mds::MdsCtx &ctx, const int64_
MDS_TG(10_ms);
int ret = OB_SUCCESS;
mds::MdsTableHandle handle;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
if (CLICK_FAIL(get_mds_table_handle_(handle, true))) {
MDS_LOG_SET(WARN, "failed to get_mds_table");
} else if (!handle.is_valid()) {
@ -328,11 +333,12 @@ int ObITabletMdsInterface::replay_remove(const Key &key, mds::MdsCtx &ctx, const
MDS_TG(10_ms);
int ret = OB_SUCCESS;
mds::MdsTableHandle handle;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
if (CLICK_FAIL(get_mds_table_handle_(handle, true))) {
MDS_LOG_SET(WARN, "failed to get_mds_table");
} else if (!handle.is_valid()) {
@ -356,11 +362,12 @@ int ObITabletMdsInterface::is_locked_by_others(bool &is_locked, const mds::MdsWr
MDS_TG(10_ms);
int ret = OB_SUCCESS;
bool is_online = false;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
do {
mds::MdsTableHandle handle;
ObLSSwitchChecker ls_switch_checker;
@ -414,6 +421,7 @@ int ObITabletMdsInterface::get_latest(OP &&read_op,
int ret = OB_SUCCESS;
bool is_online = false;
bool is_data_complete = false;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_FAIL(check_mds_data_complete_<T>(is_data_complete))) {
MDS_LOG(WARN, "failed to check data completion");
} else if (!is_data_complete) {
@ -423,7 +431,7 @@ int ObITabletMdsInterface::get_latest(OP &&read_op,
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
do {
mds::MdsTableHandle handle;
ObLSSwitchChecker ls_switch_checker;
@ -493,6 +501,7 @@ int ObITabletMdsInterface::get_latest_committed(OP &&read_op) const
ObLSSwitchChecker ls_switch_checker;
bool is_online = false;
bool is_data_complete = false;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_FAIL(check_mds_data_complete_<T>(is_data_complete))) {
MDS_LOG(WARN, "failed to check data completion");
} else if (!is_data_complete) {
@ -502,7 +511,7 @@ int ObITabletMdsInterface::get_latest_committed(OP &&read_op) const
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
do {
if (CLICK_FAIL(get_mds_table_handle_(handle, false))) {
if (OB_ENTRY_NOT_EXIST != ret) {
@ -575,6 +584,7 @@ int ObITabletMdsInterface::get_snapshot(const Key &key,
MDS_TG(10_ms);
int ret = OB_SUCCESS;
bool is_online = false;
TabletMdsLockGuard<LockMode::SHARE> guard;
bool is_data_complete = false;
if (OB_FAIL(check_mds_data_complete_<Value>(is_data_complete))) {
MDS_LOG(WARN, "failed to check data completion");
@ -585,7 +595,7 @@ int ObITabletMdsInterface::get_snapshot(const Key &key,
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
do {
mds::MdsTableHandle handle;
ObLSSwitchChecker ls_switch_checker;
@ -906,11 +916,12 @@ inline int ObITabletMdsInterface::check_transfer_in_redo_written(bool &written)
bool is_online = false;
ObTabletCreateDeleteMdsUserData tablet_status;
share::SCN redo_scn;
TabletMdsLockGuard<LockMode::SHARE> guard;
if (OB_ISNULL(get_tablet_pointer_())) {
ret = OB_BAD_NULL_ERROR;
MDS_LOG(ERROR, "pointer on tablet should not be null");
} else {
ObTabletMdsSharedLockGuard guard(get_tablet_pointer_()->get_mds_truncate_lock());
get_tablet_pointer_()->get_mds_truncate_lock_guard(guard);
do {
mds::MdsTableHandle handle;
ObLSSwitchChecker ls_switch_checker;

View File

@ -10,7 +10,6 @@
* See the Mulan PubL v2 for more details.
*/
#include "storage/multi_data_source/runtime_utility/common_define.h"
#include <ratio>
#define UNITTEST_DEBUG
#include <gtest/gtest.h>
#define private public
@ -18,7 +17,6 @@
#include "storage/multi_data_source/mds_table_handler.h"
#include "src/storage/multi_data_source/mds_table_iterator.ipp"
#include "storage/tablet/ob_mds_schema_helper.h"
#include "storage/meta_mem/ob_tablet_pointer.h"
namespace oceanbase {
namespace storage {
namespace mds {
@ -735,43 +733,6 @@ TEST_F(TestMdsTable, test_rvalue_set) {
}, writer, trans_stat, trans_version));
}
TEST_F(TestMdsTable, test_tablet_mds_lock) {
ObTabletMDSTruncateLock lock;
{
{
// 同线程可以多次加互斥锁
ObTabletMdsExclusiveLockGuard lg1(lock);
ObTabletMdsExclusiveLockGuard lg2(lock);
// 持有互斥锁的同时也可以加共享锁
ObTabletMdsSharedLockGuard lg3(lock);
ObTabletMdsSharedLockGuard lg4(lock);
ASSERT_EQ(true, lock.try_exclusive_lock());
lock.exclusive_unlock();
}
}
{
ObTabletMdsSharedLockGuard lg1(lock);
// 持有共享锁时无法加互斥锁
ASSERT_EQ(false, lock.try_exclusive_lock());
}
// 跨线程exclusive锁互斥
std::thread t1([&lock]() {
ObTabletMdsExclusiveLockGuard lg(lock);
ob_usleep(1_s);
});
std::thread t2([&lock]() {
std::chrono::system_clock::time_point start = std::chrono::high_resolution_clock::now();
ob_usleep(0.5_s);
ObTabletMdsExclusiveLockGuard lg(lock);
std::chrono::system_clock::time_point end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> duration = end - start;
MDS_LOG(INFO, "add lock use time", K(duration.count()));
ASSERT_EQ(true, duration.count() > 1_s);
});
t1.join();
t2.join();
}
}
}