From c9e4c535fcbacae24523845d4789548166d39612 Mon Sep 17 00:00:00 2001 From: obdev Date: Fri, 11 Nov 2022 11:39:56 +0000 Subject: [PATCH] split tablet_freeze for replacing tablet_meta --- src/storage/ls/ob_freezer.cpp | 92 ++++++++++++++++++++ src/storage/ls/ob_freezer.h | 2 + src/storage/ls/ob_ls_tablet_service.cpp | 108 +++++++++++++----------- 3 files changed, 154 insertions(+), 48 deletions(-) diff --git a/src/storage/ls/ob_freezer.cpp b/src/storage/ls/ob_freezer.cpp index c2c886d6f..e93ce5f28 100644 --- a/src/storage/ls/ob_freezer.cpp +++ b/src/storage/ls/ob_freezer.cpp @@ -526,6 +526,98 @@ int ObFreezer::force_tablet_freeze(const ObTabletID &tablet_id) return ret; } +int ObFreezer::tablet_freeze_for_replace_tablet_meta(const ObTabletID &tablet_id, memtable::ObIMemtable *&imemtable) +{ + int ret = OB_SUCCESS; + ObTabletHandle handle; + ObTablet *tablet = nullptr; + ObTabletMemtableMgr *memtable_mgr = nullptr; + imemtable = nullptr; + int64_t freeze_snapshot_version = OB_INVALID_TIMESTAMP; + FLOG_INFO("[Freezer] tablet_freeze_for_replace_tablet_meta start", K(ret), K_(ls_id), K(tablet_id)); + stat_.reset(); + stat_.start_time_ = ObTimeUtility::current_time(); + stat_.state_ = ObFreezeState::NOT_SET_FREEZE_FLAG; + stat_.tablet_id_ = tablet_id; + + ObTabletFreezeGuard guard(*this, true /* try guard */); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K_(ls_id), K(tablet_id)); + } else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) { + // no need freeze now, a ls freeze is running or will be running + ret = OB_SUCCESS; + FLOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K_(ls_id), K(tablet_id)); + } else if (OB_FAIL(set_freeze_flag_without_inc_freeze_clock())) { + ret = OB_SUCCESS; + FLOG_INFO("[Freezer] freeze is running", K(ret), K_(ls_id), K(tablet_id)); + } else if (FALSE_IT(stat_.state_ = ObFreezeState::NOT_SUBMIT_LOG)) { + } else { + // succeed to set freeze flag + if (OB_FAIL(get_ls_weak_read_ts(freeze_snapshot_version))) { + TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K_(ls_id)); + } else if (ObVersionRange::MAX_VERSION == freeze_snapshot_version + || ObVersionRange::MIN_VERSION >= freeze_snapshot_version) { + ret = OB_NOT_INIT; + LOG_WARN("[Freezer] weak read service not inited", K(ret), K_(ls_id)); + } else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) { + } else if (FALSE_IT(set_need_resubmit_log(false))) { + } else if (OB_FAIL(ls_tablet_svr_->get_tablet(tablet_id, + handle, + ObTabletCommon::NO_CHECK_GET_TABLET_TIMEOUT_US))) { + TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K_(ls_id), K(tablet_id)); + stat_.add_diagnose_info("fail to get tablet"); + } else if (FALSE_IT(tablet = handle.get_obj())) { + } else if (OB_ISNULL(memtable_mgr = static_cast(tablet->get_memtable_mgr()))) { + TRANS_LOG(WARN, "[Freezer] tablet_memtable_mgr is null", K(ret), K_(ls_id), K(tablet_id)); + } else if (OB_FAIL(memtable_mgr->set_is_tablet_freeze_for_active_memtable(imemtable))) { + if (ret == OB_ENTRY_NOT_EXIST) { + ret = OB_SUCCESS; + TRANS_LOG(INFO, "[Freezer] no need to freeze since there is no active memtable", K(ret), + K_(ls_id), K(tablet_id)); + stat_.add_diagnose_info("no need to freeze since there is no active memtable"); + } else { + TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K_(ls_id), K(tablet_id)); + stat_.add_diagnose_info("fail to set is_tablet_freeze"); + } + } + if (OB_FAIL(ret) || OB_ISNULL(imemtable)) { + stat_.state_ = ObFreezeState::FINISH; + stat_.end_time_ = ObTimeUtility::current_time(); + stat_.ret_code_ = ret; + print_freezer_statistics(); + unset_freeze_(); + } + } + + return ret; +} + +// must ensure that call tablet_freeze_for_replace_tablet_meta() successfully before calling the func +int ObFreezer::handle_frozen_memtable_for_replace_tablet_meta(const ObTabletID &tablet_id, memtable::ObIMemtable *imemtable) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(imemtable)) { + ret = OB_SUCCESS; + FLOG_INFO("[Freezer] no need to tablet_freeze_for_replace_tablet_meta", K(ret), K_(ls_id), K(tablet_id)); + } else { + if (OB_FAIL(handle_memtable_for_tablet_freeze(imemtable))) { + TRANS_LOG(WARN, "[Freezer] fail to handle memtable", K(ret), K_(ls_id), K(tablet_id)); + } else { + stat_.add_diagnose_info("tablet_freeze_for_replace_tablet_meta success"); + FLOG_INFO("[Freezer] tablet_freeze_for_replace_tablet_meta success", K(ret), K_(ls_id), K(tablet_id)); + } + stat_.state_ = ObFreezeState::FINISH; + stat_.end_time_ = ObTimeUtility::current_time(); + stat_.ret_code_ = ret; + print_freezer_statistics(); + unset_freeze_(); + } + + return ret; +} + /* private subfunctions for freeze process */ int ObFreezer::handle_memtable_for_tablet_freeze(memtable::ObIMemtable *imemtable) { diff --git a/src/storage/ls/ob_freezer.h b/src/storage/ls/ob_freezer.h index 96ef044b8..fb0329996 100644 --- a/src/storage/ls/ob_freezer.h +++ b/src/storage/ls/ob_freezer.h @@ -211,6 +211,8 @@ public: int logstream_freeze(); int tablet_freeze(const ObTabletID &tablet_id); int force_tablet_freeze(const ObTabletID &tablet_id); + int tablet_freeze_for_replace_tablet_meta(const ObTabletID &tablet_id, memtable::ObIMemtable *&imemtable); + int handle_frozen_memtable_for_replace_tablet_meta(const ObTabletID &tablet_id, memtable::ObIMemtable *imemtable); /* freeze_flag */ bool is_freeze(uint32_t is_freeze=UINT32_MAX) const; diff --git a/src/storage/ls/ob_ls_tablet_service.cpp b/src/storage/ls/ob_ls_tablet_service.cpp index f6672c687..dfb916c93 100644 --- a/src/storage/ls/ob_ls_tablet_service.cpp +++ b/src/storage/ls/ob_ls_tablet_service.cpp @@ -2845,73 +2845,85 @@ int ObLSTabletService::build_ha_tablet_new_table_store( const ObBatchUpdateTableStoreParam ¶m) { int ret = OB_SUCCESS; - ObTabletHandle old_tablet_handle; - ObTablet *old_tablet = nullptr; - ObTabletHandle new_tablet_handle; - ObTablet *new_tablet = nullptr; - ObTenantMetaMemMgr *t3m = nullptr; + ObTenantMetaMemMgr *t3m = MTL(ObTenantMetaMemMgr*); ObMetaDiskAddr disk_addr; ObFreezer *freezer = nullptr; + memtable::ObIMemtable *imemtable = nullptr; + bool is_tablet_freeze = false; - ObBucketHashWLockGuard lock_guard(bucket_lock_, tablet_id.hash()); if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("not inited", K(ret), K_(is_inited)); } else if (OB_UNLIKELY(!tablet_id.is_valid() || !param.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", K(ret), K(tablet_id), K(param)); - } else if (OB_ISNULL(t3m = MTL(ObTenantMetaMemMgr*))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("t3m is null", K(ret)); - } else if (OB_FAIL(direct_get_tablet(tablet_id, old_tablet_handle))) { - LOG_WARN("failed to get tablet", K(ret), K(tablet_id)); } else if (OB_ISNULL(freezer = ls_->get_freezer())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("freezer should not be NULL", K(ret), KP(freezer), KPC(ls_)); } else { - old_tablet = old_tablet_handle.get_obj(); - const share::ObLSID &ls_id = ls_->get_ls_id(); - const ObTabletMapKey key(ls_id, tablet_id); - ObTabletTxMultiSourceDataUnit tx_data; - ObTabletBindingInfo ddl_data; - ObTabletAutoincSeq autoinc_seq; - //In order to merge tablet meta - //it is necessary to make the left side of the newly created memtable start from clog_checkpinoit_ts - //the new memtable can be stuck during the creation of the tablet, it is safe here + ObTabletHandle old_tablet_handle; + ObTabletHandle new_tablet_handle; + ObBucketHashWLockGuard lock_guard(bucket_lock_, tablet_id.hash()); + if (OB_FAIL(direct_get_tablet(tablet_id, old_tablet_handle))) { + LOG_WARN("failed to get tablet", K(ret), K(tablet_id)); + } else { + ObTablet *old_tablet = old_tablet_handle.get_obj(); + ObTablet *new_tablet = nullptr; + const share::ObLSID &ls_id = ls_->get_ls_id(); + const ObTabletMapKey key(ls_id, tablet_id); + ObTabletTxMultiSourceDataUnit tx_data; + ObTabletBindingInfo ddl_data; + ObTabletAutoincSeq autoinc_seq; + //In order to merge tablet meta + //it is necessary to make the left side of the newly created memtable start from clog_checkpinoit_ts + //the new memtable can be stuck during the creation of the tablet, it is safe here - if (OB_FAIL(old_tablet->get_tx_data(tx_data))) { - LOG_WARN("failed to get tx data from old tablet", K(ret), K(tablet_id)); - } else if (OB_FAIL(old_tablet->get_ddl_data(ddl_data))) { - LOG_WARN("failed to get tx data from old tablet", K(ret), K(tablet_id)); - } else if (OB_FAIL(old_tablet->get_latest_autoinc_seq(autoinc_seq))) { - LOG_WARN("failed to get autoinc seq from old tablet", K(ret)); - } else if (OB_FAIL(ObTabletCreateDeleteHelper::acquire_tablet(key, new_tablet_handle, true/*only acquire*/))) { - LOG_WARN("failed to acquire tablet", K(ret), K(key)); - } else if (FALSE_IT(new_tablet = new_tablet_handle.get_obj())) { - } else if (OB_FAIL(new_tablet->init(param, *old_tablet, tx_data, ddl_data, autoinc_seq))) { - LOG_WARN("failed to init tablet", K(ret), KPC(old_tablet)); - } else if (old_tablet->get_tablet_meta().clog_checkpoint_ts_ < new_tablet->get_tablet_meta().clog_checkpoint_ts_ - && OB_FAIL(freezer->tablet_freeze(tablet_id))) { - if (OB_ENTRY_EXIST == ret) { - ret = OB_SUCCESS; + if (OB_FAIL(old_tablet->get_tx_data(tx_data))) { + LOG_WARN("failed to get tx data from old tablet", K(ret), K(tablet_id)); + } else if (OB_FAIL(old_tablet->get_ddl_data(ddl_data))) { + LOG_WARN("failed to get tx data from old tablet", K(ret), K(tablet_id)); + } else if (OB_FAIL(old_tablet->get_latest_autoinc_seq(autoinc_seq))) { + LOG_WARN("failed to get autoinc seq from old tablet", K(ret)); + } else if (OB_FAIL(ObTabletCreateDeleteHelper::acquire_tablet(key, new_tablet_handle, true/*only acquire*/))) { + LOG_WARN("failed to acquire tablet", K(ret), K(key)); + } else if (FALSE_IT(new_tablet = new_tablet_handle.get_obj())) { + } else if (OB_FAIL(new_tablet->init(param, *old_tablet, tx_data, ddl_data, autoinc_seq))) { + LOG_WARN("failed to init tablet", K(ret), KPC(old_tablet)); + } else if (old_tablet->get_tablet_meta().clog_checkpoint_ts_ < new_tablet->get_tablet_meta().clog_checkpoint_ts_) { + if (OB_FAIL(freezer->tablet_freeze_for_replace_tablet_meta(tablet_id, imemtable))) { + if (OB_ENTRY_EXIST == ret) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to freeze tablet", K(ret), K(tablet_id), KPC(old_tablet), KPC(new_tablet)); + } + } else { + is_tablet_freeze = true; + } + } + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(new_tablet->set_memtable_clog_checkpoint_ts(param.tablet_meta_))) { + LOG_WARN("failed to set memtable clog checkpoint ts", K(ret), KPC(old_tablet), KPC(new_tablet), K(param)); + } else if (OB_FAIL(ObTabletSlogHelper::write_create_tablet_slog(new_tablet_handle, disk_addr))) { + LOG_WARN("fail to write update tablet slog", K(ret), K(new_tablet_handle), K(disk_addr)); + } else if (OB_FAIL(t3m->compare_and_swap_tablet(key, disk_addr, old_tablet_handle, new_tablet_handle))) { + LOG_ERROR("failed to compare and swap tablet", K(ret), K(key), K(disk_addr)); + ob_usleep(1000 * 1000); + ob_abort(); } else { - LOG_WARN("failed to freeze tablet", K(ret), K(tablet_id), KPC(old_tablet), KPC(new_tablet)); + LOG_INFO("succeed to build ha tablet new table store", K(ret), K(tablet_id), K(param)); } } + } - if (OB_FAIL(ret)) { - } else if (OB_FAIL(new_tablet->set_memtable_clog_checkpoint_ts(param.tablet_meta_))) { - LOG_WARN("failed to set memtable clog checkpoint ts", K(ret), KPC(old_tablet), KPC(new_tablet), K(param)); - } else if (OB_FAIL(ObTabletSlogHelper::write_create_tablet_slog(new_tablet_handle, disk_addr))) { - LOG_WARN("fail to write update tablet slog", K(ret), K(new_tablet_handle), K(disk_addr)); - } else if (OB_FAIL(t3m->compare_and_swap_tablet(key, disk_addr, old_tablet_handle, new_tablet_handle))) { - LOG_ERROR("failed to compare and swap tablet", K(ret), K(key), K(disk_addr)); - ob_usleep(1000 * 1000); - ob_abort(); - } else { - LOG_INFO("succeed to build ha tablet new table store", K(ret), K(tablet_id), K(param)); + if (is_tablet_freeze) { + int tmp_ret = OB_SUCCESS; + if (OB_TMP_FAIL(freezer->handle_frozen_memtable_for_replace_tablet_meta(tablet_id, imemtable))) { + LOG_WARN("failed to handle_frozen_memtable_for_replace_tablet_meta", K(tmp_ret), K(tablet_id), K(param)); + ret = OB_SUCC(ret) ? tmp_ret : ret; } } + return ret; } @@ -3393,7 +3405,7 @@ int ObLSTabletService::insert_lob_tablet_row( const ObColDesc &column = run_ctx.col_descs_->at(i); ObObj &obj = row.row_val_.get_cell(i); if (!column.col_type_.is_lob_v2() || obj.is_null() || obj.is_nop_value()) { - // do nothing + // do nothing } else { if (!check_lob) { if (OB_FAIL(check_lob_tablet_valid(data_tablet))) {