From 9fac17b4b202daf1cb8ad6492f2f67ee920fa3bd Mon Sep 17 00:00:00 2001 From: ZenoWang Date: Fri, 9 Jun 2023 04:48:09 +0000 Subject: [PATCH] Return recycled scn when tx data is not existed in sstable --- src/storage/tx/ob_trans_service_v4.cpp | 3 ++- src/storage/tx_table/ob_tx_data_table.cpp | 22 ++++++++++++------- src/storage/tx_table/ob_tx_data_table.h | 12 +++++++--- src/storage/tx_table/ob_tx_table.cpp | 11 +++++++--- src/storage/tx_table/ob_tx_table.h | 3 ++- .../tx_table/ob_tx_table_interface.cpp | 7 ++++-- src/storage/tx_table/ob_tx_table_interface.h | 5 ++++- src/storage/tx_table/ob_tx_table_iterator.cpp | 7 +++--- src/storage/tx_table/ob_tx_table_iterator.h | 8 ++++--- .../storage/tx/mock_utils/basic_fake_define.h | 5 ++++- 10 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/storage/tx/ob_trans_service_v4.cpp b/src/storage/tx/ob_trans_service_v4.cpp index 92c94c06d5..1bae2278ca 100644 --- a/src/storage/tx/ob_trans_service_v4.cpp +++ b/src/storage/tx/ob_trans_service_v4.cpp @@ -1818,11 +1818,12 @@ int ObTransService::get_tx_state_from_tx_table_(const share::ObLSID &lsid, int ret = OB_SUCCESS; ObTxTableGuard tx_table_guard; int64_t _state = 0; + SCN recycled_scn; if (OB_FAIL(get_tx_table_guard_(NULL, lsid, tx_table_guard))) { TRANS_LOG(WARN, "get tx table guard failed", KR(ret), K(lsid), KPC(this)); } else if (!tx_table_guard.is_valid()) { TRANS_LOG(WARN, "tx table is null", KR(ret), K(lsid), KPC(this)); - } else if (OB_FAIL(tx_table_guard.try_get_tx_state(tx_id, _state, commit_version))) { + } else if (OB_FAIL(tx_table_guard.try_get_tx_state(tx_id, _state, commit_version, recycled_scn))) { TRANS_LOG(WARN, "get tx state failed", KR(ret), K(lsid), K(tx_id), KPC(this)); } else { state = (int)_state; diff --git a/src/storage/tx_table/ob_tx_data_table.cpp b/src/storage/tx_table/ob_tx_data_table.cpp index c9de65756c..85f64164b7 100644 --- a/src/storage/tx_table/ob_tx_data_table.cpp +++ b/src/storage/tx_table/ob_tx_data_table.cpp @@ -452,7 +452,10 @@ int ObTxDataTable::insert_(ObTxData *&tx_data, ObTxDataMemtableWriteGuard &write return ret; } -int ObTxDataTable::check_with_tx_data(const ObTransID tx_id, ObITxDataCheckFunctor &fn, ObTxDataGuard &tx_data_guard) +int ObTxDataTable::check_with_tx_data(const ObTransID tx_id, + ObITxDataCheckFunctor &fn, + ObTxDataGuard &tx_data_guard, + SCN &recycled_scn) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { @@ -461,7 +464,7 @@ int ObTxDataTable::check_with_tx_data(const ObTransID tx_id, ObITxDataCheckFunct } else if (OB_SUCC(check_tx_data_in_memtable_(tx_id, fn, tx_data_guard))) { // successfully do check function in memtable, check done STORAGE_LOG(DEBUG, "tx data table check with tx memtable data succeed", K(tx_id), K(fn)); - } else if (OB_TRANS_CTX_NOT_EXIST == ret && OB_SUCC(check_tx_data_in_sstable_(tx_id, fn, tx_data_guard))) { + } else if (OB_TRANS_CTX_NOT_EXIST == ret && OB_SUCC(check_tx_data_in_sstable_(tx_id, fn, tx_data_guard, recycled_scn))) { // successfully do check function in sstable STORAGE_LOG(DEBUG, "tx data table check with tx sstable data succeed", K(tx_id), K(fn)); } else { @@ -669,7 +672,8 @@ int ObTxDataTable::get_tx_data_in_memtables_cache_(const ObTransID tx_id, int ObTxDataTable::check_tx_data_in_sstable_(const ObTransID tx_id, ObITxDataCheckFunctor &fn, - ObTxDataGuard &tx_data_guard) + ObTxDataGuard &tx_data_guard, + SCN &recycled_scn) { int ret = OB_SUCCESS; tx_data_guard.reset(); @@ -679,7 +683,7 @@ int ObTxDataTable::check_tx_data_in_sstable_(const ObTransID tx_id, } else if (OB_ISNULL(tx_data_guard.tx_data())) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "tx data is unexpected null", KR(ret), K(tx_data_guard)); - } else if (OB_FAIL(get_tx_data_in_sstable_(tx_id, *tx_data_guard.tx_data()))) { + } else if (OB_FAIL(get_tx_data_in_sstable_(tx_id, *tx_data_guard.tx_data(), recycled_scn))) { STORAGE_LOG(WARN, "get tx data from sstable failed.", KR(ret), K(tx_id)); } else { EVENT_INC(ObStatEventIds::TX_DATA_READ_TX_DATA_SSTABLE_COUNT); @@ -695,7 +699,7 @@ int ObTxDataTable::check_tx_data_in_sstable_(const ObTransID tx_id, return ret; } -int ObTxDataTable::get_tx_data_in_sstable_(const transaction::ObTransID tx_id, ObTxData &tx_data) +int ObTxDataTable::get_tx_data_in_sstable_(const transaction::ObTransID tx_id, ObTxData &tx_data, share::SCN &recycled_scn) { int ret = OB_SUCCESS; ObTableIterParam iter_param = read_schema_.iter_param_; @@ -711,7 +715,7 @@ int ObTxDataTable::get_tx_data_in_sstable_(const transaction::ObTransID tx_id, O ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid tablet handle", KR(ret), K(tablet_handle), K(tablet_id_)); } else { - ObTxDataSingleRowGetter getter(iter_param, slice_allocator_); + ObTxDataSingleRowGetter getter(iter_param, slice_allocator_, recycled_scn); if (OB_FAIL(getter.init(tx_id))) { STORAGE_LOG(WARN, "init ObTxDataSingleRowGetter fail.", KR(ret), KP(this), K(tablet_id_)); } else if (OB_FAIL(getter.get_next_row(tx_data))) { @@ -1269,6 +1273,7 @@ int ObTxDataTable::supplement_undo_actions_if_exist(ObTxData *tx_data) int ret = OB_SUCCESS; ObTxData tx_data_from_sstable; tx_data_from_sstable.reset(); + SCN unused_scn; if (IS_NOT_INIT) { ret = OB_NOT_INIT; @@ -1276,7 +1281,7 @@ int ObTxDataTable::supplement_undo_actions_if_exist(ObTxData *tx_data) } else if (OB_ISNULL(tx_data)) { ret = OB_INVALID_ARGUMENT; STORAGE_LOG(ERROR, "tx data is nullptr", KR(ret), KP(this)); - } else if (OB_FAIL(get_tx_data_in_sstable_(tx_data->tx_id_, tx_data_from_sstable))) { + } else if (OB_FAIL(get_tx_data_in_sstable_(tx_data->tx_id_, tx_data_from_sstable, unused_scn))) { if (ret == OB_TRANS_CTX_NOT_EXIST) { // This transaction does not have undo actions ret = OB_SUCCESS; @@ -1377,8 +1382,9 @@ int ObTxDataTable::dump_tx_data_in_sstable_2_text_(const ObTransID tx_id, FILE * int ret = OB_SUCCESS; ObTxData tx_data; tx_data.reset(); + SCN unused_scn; - if (OB_FAIL(get_tx_data_in_sstable_(tx_id, tx_data))) { + if (OB_FAIL(get_tx_data_in_sstable_(tx_id, tx_data, unused_scn))) { STORAGE_LOG(WARN, "get tx data from sstable failed.", KR(ret), K(tx_id)); } else { fprintf(fd, "********** Tx Data SSTable ***********\n\n"); diff --git a/src/storage/tx_table/ob_tx_data_table.h b/src/storage/tx_table/ob_tx_data_table.h index 52b20ec973..3611bdf61f 100644 --- a/src/storage/tx_table/ob_tx_data_table.h +++ b/src/storage/tx_table/ob_tx_data_table.h @@ -195,7 +195,10 @@ public: // ObTxDataTable * @param[in] tx_id the tx id of the transaction to be checked * @param[in] fn the functor which is dealt with tx data */ - virtual int check_with_tx_data(const transaction::ObTransID tx_id, ObITxDataCheckFunctor &fn, ObTxDataGuard &tx_data_guard); + virtual int check_with_tx_data(const transaction::ObTransID tx_id, + ObITxDataCheckFunctor &fn, + ObTxDataGuard &tx_data_guard, + share::SCN &recycled_scn); /** * @brief See ObTxTable::get_recycle_scn @@ -266,11 +269,14 @@ private: int get_tx_data_from_cache_(const transaction::ObTransID tx_id, ObTxDataGuard &tx_data_guard, bool &find); - int check_tx_data_in_sstable_(const transaction::ObTransID tx_id, ObITxDataCheckFunctor &fn, ObTxDataGuard &tx_data_guard); + int check_tx_data_in_sstable_(const transaction::ObTransID tx_id, + ObITxDataCheckFunctor &fn, + ObTxDataGuard &tx_data_guard, + share::SCN &recycled_scn); int get_tx_data_in_cache_(const transaction::ObTransID tx_id, ObTxData *&tx_data); - int get_tx_data_in_sstable_(const transaction::ObTransID tx_id, ObTxData &tx_data); + int get_tx_data_in_sstable_(const transaction::ObTransID tx_id, ObTxData &tx_data, share::SCN &recycled_scn); int insert_(ObTxData *&tx_data, ObTxDataMemtableWriteGuard &write_guard); diff --git a/src/storage/tx_table/ob_tx_table.cpp b/src/storage/tx_table/ob_tx_table.cpp index 52f52dfe7d..64f899afd7 100644 --- a/src/storage/tx_table/ob_tx_table.cpp +++ b/src/storage/tx_table/ob_tx_table.cpp @@ -826,9 +826,10 @@ int ObTxTable::check_tx_data_in_tables_(ObReadTxDataArg &read_tx_data_arg, ObITx } else if (OB_TRANS_CTX_NOT_EXIST == ret) { ObTxDataGuard tx_data_guard; ObTxData *tx_data = nullptr; + SCN recycled_scn; // read tx data from tx data table and get tx data guard - if (OB_FAIL(tx_data_table_.check_with_tx_data(read_tx_data_arg.tx_id_, fn, tx_data_guard))) { + if (OB_FAIL(tx_data_table_.check_with_tx_data(read_tx_data_arg.tx_id_, fn, tx_data_guard, recycled_scn))) { if (OB_ITER_END == ret) { ret = OB_TRANS_CTX_NOT_EXIST; } @@ -838,6 +839,7 @@ int ObTxTable::check_tx_data_in_tables_(ObReadTxDataArg &read_tx_data_arg, ObITx K(ls_id_), K(read_tx_data_arg), K(tx_data_guard), + K(recycled_scn), "state", get_state_string(state_)); } else if (OB_NOT_NULL(tx_data = tx_data_guard.tx_data())) { // if tx data is not null, put tx data into cache @@ -947,7 +949,10 @@ int ObTxTable::get_tx_state_with_scn(ObReadTxDataArg &read_tx_data_arg, return ret; } -int ObTxTable::try_get_tx_state(ObReadTxDataArg &read_tx_data_arg, int64_t &state, SCN &trans_version) +int ObTxTable::try_get_tx_state(ObReadTxDataArg &read_tx_data_arg, + int64_t &state, + SCN &trans_version, + SCN &recycled_scn) { int ret = OB_SUCCESS; GetTxStateWithSCNFunctor fn(SCN::max_scn(), state, trans_version); @@ -956,7 +961,7 @@ int ObTxTable::try_get_tx_state(ObReadTxDataArg &read_tx_data_arg, int64_t &stat LOG_WARN("tx table is not init.", KR(ret), K(read_tx_data_arg)); } else { ObTxDataGuard tx_data_guard; - ret = tx_data_table_.check_with_tx_data(read_tx_data_arg.tx_id_, fn, tx_data_guard); + ret = tx_data_table_.check_with_tx_data(read_tx_data_arg.tx_id_, fn, tx_data_guard, recycled_scn); if (OB_ITER_END == ret) { ret = OB_TRANS_CTX_NOT_EXIST; } diff --git a/src/storage/tx_table/ob_tx_table.h b/src/storage/tx_table/ob_tx_table.h index 74f2960fef..751b243ec3 100644 --- a/src/storage/tx_table/ob_tx_table.h +++ b/src/storage/tx_table/ob_tx_table.h @@ -162,8 +162,9 @@ public: * @param[in] read_epoch * @param[out] state * @param[out] trans_version + * @param[out] recycled_scn only if tx data is not exist, recycled_scn would be assigned */ - int try_get_tx_state(ObReadTxDataArg &read_tx_data_arg, int64_t &state, share::SCN &trans_version); + int try_get_tx_state(ObReadTxDataArg &read_tx_data_arg, int64_t &state, share::SCN &trans_version, share::SCN &recycled_scn); /** * @brief the txn READ_TRANS_ID use SNAPSHOT_VERSION to read the data, and check whether the data is locked, readable or unreadable by txn DATA_TRANS_ID. READ_LATEST is used to check whether read the data belong to the same txn diff --git a/src/storage/tx_table/ob_tx_table_interface.cpp b/src/storage/tx_table/ob_tx_table_interface.cpp index 5cdaae59c8..0de3b08420 100644 --- a/src/storage/tx_table/ob_tx_table_interface.cpp +++ b/src/storage/tx_table/ob_tx_table_interface.cpp @@ -72,11 +72,14 @@ int ObTxTableGuard::get_tx_state_with_scn(const transaction::ObTransID tx_id, } } -int ObTxTableGuard::try_get_tx_state(const transaction::ObTransID tx_id, int64_t &state, share::SCN &trans_version) +int ObTxTableGuard::try_get_tx_state(const transaction::ObTransID tx_id, + int64_t &state, + share::SCN &trans_version, + share::SCN &recycled_scn) { if (OB_NOT_NULL(tx_table_)) { ObReadTxDataArg arg(tx_id, epoch_, mini_cache_); - return tx_table_->try_get_tx_state(arg, state, trans_version); + return tx_table_->try_get_tx_state(arg, state, trans_version, recycled_scn); } else { return OB_NOT_INIT; } diff --git a/src/storage/tx_table/ob_tx_table_interface.h b/src/storage/tx_table/ob_tx_table_interface.h index df71d8b7bf..26ae95d207 100644 --- a/src/storage/tx_table/ob_tx_table_interface.h +++ b/src/storage/tx_table/ob_tx_table_interface.h @@ -69,7 +69,10 @@ public: // dalegate functions int64_t &state, share::SCN &trans_version); - int try_get_tx_state(const transaction::ObTransID tx_id, int64_t &state, share::SCN &trans_version); + int try_get_tx_state(const transaction::ObTransID tx_id, + int64_t &state, + share::SCN &trans_version, + share::SCN &recycled_scn); int lock_for_read(const transaction::ObLockForReadArg &lock_for_read_arg, bool &can_read, diff --git a/src/storage/tx_table/ob_tx_table_iterator.cpp b/src/storage/tx_table/ob_tx_table_iterator.cpp index 6e4f897333..1b85a24a36 100644 --- a/src/storage/tx_table/ob_tx_table_iterator.cpp +++ b/src/storage/tx_table/ob_tx_table_iterator.cpp @@ -430,9 +430,10 @@ int ObTxDataSingleRowGetter::get_next_row(ObTxData &tx_data) ret = get_next_row_(sstables, tx_data); if (OB_TIMEOUT == ret || OB_DISK_HUNG == ret) { ret = OB_EAGAIN; - STORAGE_LOG(WARN, - "modify ret code from OB_TIMEOUT or OB_DISK_HUNG to OB_EAGAIN", - KR(ret)); + STORAGE_LOG(WARN, "modify ret code from OB_TIMEOUT or OB_DISK_HUNG to OB_EAGAIN", KR(ret)); + } else if (OB_FAIL(ret)) { + recycled_scn_ = static_cast(sstables[0])->get_filled_tx_scn(); + STORAGE_LOG(WARN, "get tx data from sstable failed", K(recycled_scn_)); } } } diff --git a/src/storage/tx_table/ob_tx_table_iterator.h b/src/storage/tx_table/ob_tx_table_iterator.h index b64e3d0f47..75da8564d7 100644 --- a/src/storage/tx_table/ob_tx_table_iterator.h +++ b/src/storage/tx_table/ob_tx_table_iterator.h @@ -172,9 +172,10 @@ class ObTxDataSingleRowGetter { using SliceAllocator = ObSliceAlloc; public: - ObTxDataSingleRowGetter(const ObTableIterParam & iter_param, - SliceAllocator &slice_allocator) - : iter_param_(iter_param), slice_allocator_(slice_allocator), key_datums_() {} + ObTxDataSingleRowGetter(const ObTableIterParam &iter_param, + SliceAllocator &slice_allocator, + share::SCN &recycled_scn) + : iter_param_(iter_param), slice_allocator_(slice_allocator), recycled_scn_(recycled_scn), key_datums_() {} virtual ~ObTxDataSingleRowGetter() {} /** @@ -198,6 +199,7 @@ private: private: const ObTableIterParam &iter_param_; SliceAllocator &slice_allocator_; + share::SCN &recycled_scn_; transaction::ObTransID tx_id_; ObArenaAllocator arena_allocator_; blocksstable::ObStorageDatum key_datums_[2]; diff --git a/unittest/storage/tx/mock_utils/basic_fake_define.h b/unittest/storage/tx/mock_utils/basic_fake_define.h index cef65621c1..122aee970f 100644 --- a/unittest/storage/tx/mock_utils/basic_fake_define.h +++ b/unittest/storage/tx/mock_utils/basic_fake_define.h @@ -100,7 +100,10 @@ public: OZ (map_.insert(tx_data->tx_id_, tx_data)); return ret; } - virtual int check_with_tx_data(const ObTransID tx_id, ObITxDataCheckFunctor &fn, ObTxDataGuard &tx_data_guard) override + virtual int check_with_tx_data(const ObTransID tx_id, + ObITxDataCheckFunctor &fn, + ObTxDataGuard &tx_data_guard, + share::SCN &recycled_scn) override { int ret = OB_SUCCESS; OZ (map_.get(tx_id, tx_data_guard));