From 6fa43cf8a0386e373093b901013c7e940ccda346 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 27 Jan 2025 13:02:41 +0800 Subject: [PATCH 01/46] initial Signed-off-by: Calvin Neo --- .../Storages/KVStore/Decode/RegionTable.cpp | 25 +++++++++++++++---- .../src/Storages/KVStore/Decode/RegionTable.h | 12 ++++++--- .../Storages/KVStore/Decode/RegionTable_fwd.h | 23 +++++++++++++++++ .../KVStore/MultiRaft/ApplySnapshot.cpp | 2 +- .../KVStore/MultiRaft/RaftCommands.cpp | 2 +- .../KVStore/MultiRaft/RegionCFDataBase.h | 4 +++ .../Storages/KVStore/MultiRaft/RegionData.cpp | 7 +++++- .../Storages/KVStore/MultiRaft/RegionData.h | 6 +++-- dbms/src/Storages/KVStore/Region.cpp | 11 +++++++- dbms/src/Storages/KVStore/Region.h | 6 +++++ .../KVStore/tests/gtest_new_kvstore.cpp | 24 ++++++++++++------ 11 files changed, 101 insertions(+), 21 deletions(-) create mode 100644 dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index a209d9b7f38..a4a94e15ec0 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -67,14 +67,16 @@ RegionTable::Table & RegionTable::getOrCreateTable(const KeyspaceID keyspace_id, RegionTable::InternalRegion & RegionTable::insertRegion(Table & table, const Region & region) { const auto range = region.getRange(); - return insertRegion(table, *range, region.id()); + return insertRegion(table, *range, region); } RegionTable::InternalRegion & RegionTable::insertRegion( Table & table, const RegionRangeKeys & region_range_keys, - const RegionID region_id) + const Region & region) { + auto region_id = region.id(); + region.setRegionTableSize(table.size); auto keyspace_id = region_range_keys.getKeyspaceID(); auto & table_regions = table.regions; // Insert table mapping. @@ -164,6 +166,19 @@ void RegionTable::updateRegion(const Region & region) internal_region.updateRegionCacheBytes(region.dataSize()); } +size_t RegionTable::getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const +{ + std::scoped_lock lock(mutex); + + auto it = tables.find(KeyspaceTableID{keyspace_id, table_id}); + if (it == tables.end()) + return 0; + const auto & table = it->second; + if (table.size) + return *(table.size); + return 0; +} + namespace { /// Remove obsolete data for table after data of `handle_range` is removed from this TiFlash node. @@ -386,10 +401,10 @@ void RegionTable::shrinkRegionRange(const Region & region) internal_region.updateRegionCacheBytes(region.dataSize()); } -void RegionTable::extendRegionRange(const RegionID region_id, const RegionRangeKeys & region_range_keys) +void RegionTable::extendRegionRange(const Region & region, const RegionRangeKeys & region_range_keys) { std::lock_guard lock(mutex); - + const RegionID region_id = region.id(); auto keyspace_id = region_range_keys.getKeyspaceID(); auto table_id = region_range_keys.getMappedTableID(); auto new_handle_range = region_range_keys.rawKeys(); @@ -433,7 +448,7 @@ void RegionTable::extendRegionRange(const RegionID region_id, const RegionRangeK else { auto & table = getOrCreateTable(keyspace_id, table_id); - insertRegion(table, region_range_keys, region_id); + insertRegion(table, region_range_keys, region); LOG_INFO(log, "insert internal region, keyspace={} table_id={} region_id={}", keyspace_id, table_id, region_id); } } diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 1c15c18624d..51d2fdec4e8 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -94,9 +95,12 @@ class RegionTable : private boost::noncopyable { explicit Table(const TableID table_id_) : table_id(table_id_) - {} + { + size = std::make_shared(0); + } TableID table_id; InternalRegions regions; + RegionTableSize size; }; explicit RegionTable(Context & context_); @@ -108,7 +112,7 @@ class RegionTable : private boost::noncopyable void shrinkRegionRange(const Region & region); /// extend range for possible InternalRegion or add one. - void extendRegionRange(RegionID region_id, const RegionRangeKeys & region_range_keys); + void extendRegionRange(const Region & region, const RegionRangeKeys & region_range_keys); void removeRegion(RegionID region_id, bool remove_data, const RegionTaskLock &); @@ -151,6 +155,8 @@ class RegionTable : private boost::noncopyable void clear(); + size_t getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const; + public: // safe ts is maintained by check_leader RPC (https://github.com/tikv/tikv/blob/1ea26a2ac8761af356cc5c0825eb89a0b8fc9749/components/resolved_ts/src/advance.rs#L262), // leader_safe_ts is the safe_ts in leader, leader will send to learner to advance safe_ts of learner, and TiFlash will record the safe_ts into safe_ts_map in check_leader RPC. @@ -182,7 +188,7 @@ class RegionTable : private boost::noncopyable Table & getOrCreateTable(KeyspaceID keyspace_id, TableID table_id); void removeTable(KeyspaceID keyspace_id, TableID table_id); InternalRegion & getOrInsertRegion(const Region & region); - InternalRegion & insertRegion(Table & table, const RegionRangeKeys & region_range_keys, RegionID region_id); + InternalRegion & insertRegion(Table & table, const RegionRangeKeys & region_range_keys, const Region & region); InternalRegion & insertRegion(Table & table, const Region & region); InternalRegion & doGetInternalRegion(KeyspaceTableID ks_table_id, RegionID region_id); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h new file mode 100644 index 00000000000..87870ed8364 --- /dev/null +++ b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h @@ -0,0 +1,23 @@ +// Copyright 2025 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +namespace DB +{ +using RegionTableSize = std::shared_ptr; +} // namespace DB \ No newline at end of file diff --git a/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp b/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp index d01c3aab43e..cd8474c2690 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp @@ -277,7 +277,7 @@ void KVStore::onSnapshot( const auto range = new_region_wrap->getRange(); auto & region_table = tmt.getRegionTable(); // extend region to make sure data won't be removed. - region_table.extendRegionRange(region_id, *range); + region_table.extendRegionRange(*new_region_wrap, *range); } // Register the new Region. diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp index a1883bca63b..c4f52f79901 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp @@ -199,7 +199,7 @@ RegionID RegionRaftCommandDelegate::execCommitMerge( : source_region_meta_delegate.regionState().getRegion().end_key(); region_table.extendRegionRange( - id(), + *this, RegionRangeKeys(TiKVKey::copyFrom(new_start_key), TiKVKey::copyFrom(new_end_key))); } diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionCFDataBase.h b/dbms/src/Storages/KVStore/MultiRaft/RegionCFDataBase.h index d84fba36cc7..4639ffe83b9 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionCFDataBase.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionCFDataBase.h @@ -52,6 +52,10 @@ struct RegionDataMemDiff payload -= other.payload; decoded -= other.decoded; } + + Type total() const { return payload + decoded; } + + size_t totalSize() const { return payload + decoded; } }; enum class DupCheck diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index 8285120cf68..12044b34f16 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -38,6 +38,10 @@ void RegionData::recordMemChange(const RegionDataMemDiff & delta) { root_of_kvstore_mem_trackers->free(-delta.payload); } + // A region splits and merges, but its derived region all belong to the same table. + // So we can summarize here rather than `updateMemoryUsage`. + if (region_table_size) + *region_table_size += delta.total(); } void RegionData::updateMemoryUsage(const RegionDataMemDiff & delta) @@ -79,7 +83,7 @@ RegionDataMemDiff RegionData::insert(ColumnFamilyType cf, TiKVKey && key, TiKVVa return delta; } -void RegionData::remove(ColumnFamilyType cf, const TiKVKey & key) +RegionDataMemDiff RegionData::remove(ColumnFamilyType cf, const TiKVKey & key) { RegionDataMemDiff delta; switch (cf) @@ -110,6 +114,7 @@ void RegionData::remove(ColumnFamilyType cf, const TiKVKey & key) } recordMemChange(delta); updateMemoryUsage(delta); + return delta; } RegionData::WriteCFIter RegionData::removeDataByWriteIt(const WriteCFIter & write_it) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h index c623334faa4..d785d8e95a9 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h @@ -15,6 +15,7 @@ #pragma once #include +#include #include #include @@ -39,7 +40,7 @@ class RegionData using LockInfoPtr = std::unique_ptr; RegionDataMemDiff insert(ColumnFamilyType cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); - void remove(ColumnFamilyType cf, const TiKVKey & key); + RegionDataMemDiff remove(ColumnFamilyType cf, const TiKVKey & key); WriteCFIter removeDataByWriteIt(const WriteCFIter & write_it); std::optional readDataByWriteIt( @@ -120,7 +121,7 @@ class RegionData private: // The memory difference to the KVStore. - static void recordMemChange(const RegionDataMemDiff &); + void recordMemChange(const RegionDataMemDiff &); // The memory difference to this Region. void updateMemoryUsage(const RegionDataMemDiff &); void resetMemoryUsage(); @@ -138,6 +139,7 @@ class RegionData std::atomic cf_data_size = 0; // Size of decoded structures for convenient access, considered as amplification in memory. std::atomic decoded_data_size = 0; + mutable RegionTableSize region_table_size; }; } // namespace DB diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index bfbcbab45ee..ecf6209af42 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -92,7 +92,11 @@ void Region::remove(const std::string & cf, const TiKVKey & key) void Region::doRemove(ColumnFamilyType type, const TiKVKey & key) { - data.remove(type, key); + auto diff = data.remove(type, key); + if (data.region_table_size) + { + *(data.region_table_size) += diff.total(); + } } void Region::clearAllData() @@ -184,6 +188,11 @@ size_t Region::dataSize() const return data.dataSize(); } +size_t Region::totalSize() const +{ + return data.totalSize() + sizeof(RegionMeta); +} + size_t Region::writeCFCount() const { std::shared_lock lock(mutex); diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index da5ed6166d9..b2271d88606 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,8 @@ class Region : public std::enable_shared_from_this // Payload size in RegionData, show how much data flows in/out of the Region. size_t dataSize() const; + // How much memory the Region consumes. + size_t totalSize() const; size_t writeCFCount() const; std::string dataInfo() const; @@ -228,6 +231,8 @@ class Region : public std::enable_shared_from_this RegionData::OrphanKeysInfo & orphanKeysInfo() { return data.orphan_keys_info; } const RegionData::OrphanKeysInfo & orphanKeysInfo() const { return data.orphan_keys_info; } + void setRegionTableSize(RegionTableSize size) const { data.region_table_size = size; } + public: // Raft Read and Write CommittedScanner createCommittedScanner(bool use_lock, bool need_value); CommittedRemover createCommittedRemover(bool use_lock = true); @@ -278,6 +283,7 @@ class Region : public std::enable_shared_from_this friend class tests::RegionKVStoreTest; friend struct RegionBench::DebugRegion; +private: // Private methods no need to lock mutex, normally // Returns the size of data change(inc or dec) diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index 4ad8ee27ff2..e7d76a3b1d3 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -87,16 +87,15 @@ try = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 111, 999).toString(); MockRaftStoreProxy::FailCond cond; const auto decoded_lock_size = sizeof(DecodedLockCFValue) + sizeof(DecodedLockCFValue::Inner); - proxy_instance->debugAddRegions( - kvs, - ctx.getTMTContext(), - {1, 2, 3}, - {{RecordKVFormat::genKey(table_id, 0), RecordKVFormat::genKey(table_id, 10)}, - {RecordKVFormat::genKey(table_id, 11), RecordKVFormat::genKey(table_id, 20)}, - {RecordKVFormat::genKey(table_id, 21), RecordKVFormat::genKey(table_id, 30)}}); + auto & region_table = ctx.getTMTContext().getRegionTable(); { // default + proxy_instance->debugAddRegions( + kvs, + ctx.getTMTContext(), + {1}, + {{RecordKVFormat::genKey(table_id, 0), RecordKVFormat::genKey(table_id, 10)}}); auto region_id = 1; auto kvr1 = kvs.getRegion(region_id); auto [index, term] @@ -107,10 +106,16 @@ try ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(kvr1->dataSize(), kvr1->getData().totalSize()); + ASSERT_EQ(kvr1->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); } { // lock root_of_kvstore_mem_trackers->reset(); + proxy_instance->debugAddRegions( + kvs, + ctx.getTMTContext(), + {2}, + {{RecordKVFormat::genKey(table_id, 11), RecordKVFormat::genKey(table_id, 20)}}); auto region_id = 2; auto kvr1 = kvs.getRegion(region_id); auto [index, term] @@ -125,6 +130,11 @@ try { // lock with largetxn root_of_kvstore_mem_trackers->reset(); + proxy_instance->debugAddRegions( + kvs, + ctx.getTMTContext(), + {3}, + {{RecordKVFormat::genKey(table_id, 21), RecordKVFormat::genKey(table_id, 30)}}); auto region_id = 3; auto kvr1 = kvs.getRegion(region_id); ASSERT_NE(kvr1, nullptr); From a7624862f6d2fab2af58c29a17f1aa05d0139d9a Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 5 Feb 2025 14:22:10 +0800 Subject: [PATCH 02/46] clang-format Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h index 87870ed8364..a3bdf4e6f1b 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h @@ -14,10 +14,10 @@ #pragma once -#include #include +#include namespace DB { using RegionTableSize = std::shared_ptr; -} // namespace DB \ No newline at end of file +} // namespace DB From 38707c9fbf5c8548082ee7439ca7b2bff42c14be Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 5 Feb 2025 15:56:45 +0800 Subject: [PATCH 03/46] fix tests Signed-off-by: Calvin Neo --- .../Storages/KVStore/MultiRaft/RegionData.cpp | 2 ++ .../KVStore/tests/gtest_new_kvstore.cpp | 25 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index 12044b34f16..b7b31fb6a01 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -41,7 +41,9 @@ void RegionData::recordMemChange(const RegionDataMemDiff & delta) // A region splits and merges, but its derived region all belong to the same table. // So we can summarize here rather than `updateMemoryUsage`. if (region_table_size) + { *region_table_size += delta.total(); + } } void RegionData::updateMemoryUsage(const RegionDataMemDiff & delta) diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index e7d76a3b1d3..ea42a5385bd 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -106,7 +106,7 @@ try ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(kvr1->dataSize(), kvr1->getData().totalSize()); - ASSERT_EQ(kvr1->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvr1->getData().totalSize(), region_table.getTableRegionSize(NullspaceID, table_id)); } { // lock @@ -117,15 +117,19 @@ try {2}, {{RecordKVFormat::genKey(table_id, 11), RecordKVFormat::genKey(table_id, 20)}}); auto region_id = 2; - auto kvr1 = kvs.getRegion(region_id); + auto kvr1 = kvs.getRegion(1); + auto kvr2 = kvs.getRegion(region_id); auto [index, term] = proxy_instance ->rawWrite(region_id, {str_key}, {str_lock_value}, {WriteCmdType::Put}, {ColumnFamilyType::Lock}); UNUSED(term); proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(kvr1->dataSize() + decoded_lock_size, kvr1->getData().totalSize()); + ASSERT_EQ(kvr2->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(kvr2->dataSize() + decoded_lock_size, kvr2->getData().totalSize()); + ASSERT_EQ( + kvr2->getData().totalSize() + kvr1->getData().totalSize(), + region_table.getTableRegionSize(NullspaceID, table_id)); } { // lock with largetxn @@ -136,8 +140,10 @@ try {3}, {{RecordKVFormat::genKey(table_id, 21), RecordKVFormat::genKey(table_id, 30)}}); auto region_id = 3; - auto kvr1 = kvs.getRegion(region_id); - ASSERT_NE(kvr1, nullptr); + auto kvr1 = kvs.getRegion(1); + auto kvr2 = kvs.getRegion(2); + auto kvr3 = kvs.getRegion(region_id); + ASSERT_NE(kvr3, nullptr); std::string shor_value = "value"; auto lock_for_update_ts = 7777, txn_size = 1; const std::vector & async_commit = {"s1", "s2"}; @@ -160,8 +166,11 @@ try UNUSED(term); proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(kvr1->dataSize() + decoded_lock_size, kvr1->getData().totalSize()); + ASSERT_EQ(kvr3->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(kvr3->dataSize() + decoded_lock_size, kvr3->getData().totalSize()); + ASSERT_EQ( + kvr3->getData().totalSize() + kvr2->getData().totalSize() + kvr1->getData().totalSize(), + region_table.getTableRegionSize(NullspaceID, table_id)); } { // insert & remove From 8def5f8e52ad17fe65625ef6a50430c3a17b6ee5 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 5 Feb 2025 17:45:42 +0800 Subject: [PATCH 04/46] enhance test Signed-off-by: Calvin Neo --- .../Storages/KVStore/MultiRaft/RegionData.cpp | 3 + .../KVStore/tests/gtest_new_kvstore.cpp | 209 ++++++++++++------ 2 files changed, 144 insertions(+), 68 deletions(-) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index b7b31fb6a01..448fbaffcbc 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -30,6 +30,7 @@ extern const int ILLFORMAT_RAFT_ROW; void RegionData::recordMemChange(const RegionDataMemDiff & delta) { + LOG_INFO(DB::Logger::get(), "!!!! recordMemChange {}", delta.payload + delta.decoded); if (delta.payload > 0) { root_of_kvstore_mem_trackers->alloc(delta.payload, false); @@ -48,12 +49,14 @@ void RegionData::recordMemChange(const RegionDataMemDiff & delta) void RegionData::updateMemoryUsage(const RegionDataMemDiff & delta) { + LOG_INFO(DB::Logger::get(), "!!!! updateMemoryUsage {}", delta.payload + delta.decoded); cf_data_size += delta.payload; decoded_data_size += delta.decoded; } void RegionData::resetMemoryUsage() { + LOG_INFO(DB::Logger::get(), "!!!! resetMemoryUsage {}", cf_data_size + decoded_data_size); cf_data_size = 0; decoded_data_size = 0; } diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index ea42a5385bd..2e3cda5c38f 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -79,24 +79,33 @@ try initStorages(); KVStore & kvs = getKVS(); auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); - auto start = RecordKVFormat::genKey(table_id, 0); - auto end = RecordKVFormat::genKey(table_id, 100); - auto str_key = RecordKVFormat::genKey(table_id, 1, 111); - auto [str_val_write, str_val_default] = proxy_instance->generateTiKVKeyValue(111, 999); - auto str_lock_value - = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 111, 999).toString(); MockRaftStoreProxy::FailCond cond; const auto decoded_lock_size = sizeof(DecodedLockCFValue) + sizeof(DecodedLockCFValue::Inner); auto & region_table = ctx.getTMTContext().getRegionTable(); + auto getStartEnd = [&](RegionID region_id) { + return std::make_pair( + RecordKVFormat::genKey(table_id, region_id), + RecordKVFormat::genKey(table_id, region_id + 99)); + }; + auto pickKey = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::genKey(table_id, region_id + number, 111); + }; + auto pickWriteDefault = [&](RegionID, UInt64) { + return proxy_instance->generateTiKVKeyValue(111, 999); + }; + auto pickLock = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) + .toString(); + }; { // default - proxy_instance->debugAddRegions( - kvs, - ctx.getTMTContext(), - {1}, - {{RecordKVFormat::genKey(table_id, 0), RecordKVFormat::genKey(table_id, 10)}}); - auto region_id = 1; + RegionID region_id = 4100; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); auto kvr1 = kvs.getRegion(region_id); auto [index, term] = proxy_instance @@ -111,13 +120,13 @@ try { // lock root_of_kvstore_mem_trackers->reset(); - proxy_instance->debugAddRegions( - kvs, - ctx.getTMTContext(), - {2}, - {{RecordKVFormat::genKey(table_id, 11), RecordKVFormat::genKey(table_id, 20)}}); - auto region_id = 2; - auto kvr1 = kvs.getRegion(1); + RegionID region_id = 4200; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(4100); auto kvr2 = kvs.getRegion(region_id); auto [index, term] = proxy_instance @@ -125,7 +134,7 @@ try UNUSED(term); proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(kvr2->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(kvr2->dataSize(), str_key.dataSize() + str_lock_value.size()); ASSERT_EQ(kvr2->dataSize() + decoded_lock_size, kvr2->getData().totalSize()); ASSERT_EQ( kvr2->getData().totalSize() + kvr1->getData().totalSize(), @@ -134,14 +143,14 @@ try { // lock with largetxn root_of_kvstore_mem_trackers->reset(); - proxy_instance->debugAddRegions( - kvs, - ctx.getTMTContext(), - {3}, - {{RecordKVFormat::genKey(table_id, 21), RecordKVFormat::genKey(table_id, 30)}}); - auto region_id = 3; - auto kvr1 = kvs.getRegion(1); - auto kvr2 = kvs.getRegion(2); + RegionID region_id = 4300; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(4100); + auto kvr2 = kvs.getRegion(4200); auto kvr3 = kvs.getRegion(region_id); ASSERT_NE(kvr3, nullptr); std::string shor_value = "value"; @@ -175,37 +184,60 @@ try { // insert & remove root_of_kvstore_mem_trackers->reset(); - RegionPtr region = tests::makeRegion(700, start, end, proxy_helper.get()); + RegionID region_id = 5000; + auto originTableSize = region_table.getTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + auto delta = str_key.dataSize() + str_val_default.size(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), delta); + LOG_INFO( + log, + "!!!! originTableSize {} delta {} T {}", + originTableSize, + delta, + region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(originTableSize + delta, region_table.getTableRegionSize(NullspaceID, table_id)); region->remove("default", TiKVKey::copyFrom(str_key)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + // ASSERT_EQ(originTableSize, region_table.getTableRegionSize(NullspaceID, table_id)); } ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { // insert + RegionID region_id = 6000; root_of_kvstore_mem_trackers->reset(); - RegionPtr region = tests::makeRegion(701, start, end, proxy_helper.get()); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); } - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { // reload - proxy_instance->debugAddRegions( - kvs, - ctx.getTMTContext(), - {702}, - {{RecordKVFormat::genKey(table_id, 7020), RecordKVFormat::genKey(table_id, 7030)}}); + RegionID region_id = 7000; + root_of_kvstore_mem_trackers->reset(); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); root_of_kvstore_mem_trackers->reset(); - RegionPtr region = kvs.getRegion(702); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - tryPersistRegion(kvs, 702); + tryPersistRegion(kvs, region_id); root_of_kvstore_mem_trackers->reset(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); reloadKVSFromDisk(false); @@ -217,7 +249,14 @@ try { // commit root_of_kvstore_mem_trackers->reset(); - RegionPtr region = tests::makeRegion(800, start, end, proxy_helper.get()); + RegionID region_id = 8000; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); region->insert("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); @@ -233,10 +272,18 @@ try { // split & merge root_of_kvstore_mem_trackers->reset(); - RegionPtr region = tests::makeRegion(900, start, end, proxy_helper.get()); + RegionID region_id = 12000; + RegionID region_id2 = 12002; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 22); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); + auto str_lock_value = pickLock(region_id, 22); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - auto str_key2 = RecordKVFormat::genKey(table_id, 80, 111); - auto [str_val_write2, str_val_default2] = proxy_instance->generateTiKVKeyValue(111, 999); + auto str_key2 = pickKey(region_id, 80); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); + auto str_lock_value2 = pickLock(region_id, 80); region->insert("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); auto expected = str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); @@ -244,8 +291,11 @@ try auto new_region = splitRegion( region, RegionMeta( - createPeer(901, true), - createRegionInfo(902, RecordKVFormat::genKey(table_id, 50), end), + createPeer(region_id + 1, true), + createRegionInfo( + region_id2, + RecordKVFormat::genKey(table_id, 12050), + RecordKVFormat::genKey(table_id, 12099)), initialApplyState())); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_val_default.size()); @@ -261,14 +311,21 @@ try { // split & merge with lock root_of_kvstore_mem_trackers->reset(); - RegionPtr region = tests::makeRegion(1000, start, end, proxy_helper.get()); + RegionID region_id = 13100; + RegionID region_id2 = 13102; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 22); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); + auto str_lock_value = pickLock(region_id, 22); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); region->insert("lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); auto expected = str_key.dataSize() + str_lock_value.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - auto str_key2 = RecordKVFormat::genKey(table_id, 80, 111); + auto str_key2 = pickKey(region_id, 80); std::string short_value(97, 'a'); auto str_lock_value2 - = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 20, 111, &short_value) + = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13180, 111, &short_value) .toString(); region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); expected += str_key2.dataSize() + str_lock_value2.size(); @@ -276,8 +333,11 @@ try auto new_region = splitRegion( region, RegionMeta( - createPeer(1001, true), - createRegionInfo(1002, RecordKVFormat::genKey(table_id, 50), end), + createPeer(region_id + 1, true), + createRegionInfo( + region_id2, + RecordKVFormat::genKey(table_id, 13150), + RecordKVFormat::genKey(table_id, 13199)), initialApplyState())); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_lock_value.size()); @@ -292,7 +352,7 @@ try // replace a lock region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); auto str_lock_value2_2 - = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 20, 111).toString(); + = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13022, 111).toString(); region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); expected -= short_value.size(); expected -= 2; // Short value prefix and length @@ -302,21 +362,20 @@ try } { // insert & snapshot - UInt64 region_id = 1100; + UInt64 region_id = 14100; root_of_kvstore_mem_trackers->reset(); - proxy_instance->debugAddRegions( - kvs, - ctx.getTMTContext(), - {region_id}, - {{{RecordKVFormat::genKey(table_id, 1100), RecordKVFormat::genKey(table_id, 1200)}}}); - + auto [start, end] = getStartEnd(region_id); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); ASSERT_NE(region, nullptr); - auto str_key2 = RecordKVFormat::genKey(table_id, 1120, 111); - auto [str_val_write2, str_val_default2] = proxy_instance->generateTiKVKeyValue(111, 999); - auto str_key3 = RecordKVFormat::genKey(table_id, 1180, 111); - auto [str_val_write3, str_val_default3] = proxy_instance->generateTiKVKeyValue(111, 999); + auto str_key2 = pickKey(region_id, 20); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 20); + auto str_lock_value2 = pickLock(region_id, 20); + + auto str_key3 = pickKey(region_id, 80); + auto [str_val_write3, str_val_default3] = pickWriteDefault(region_id, 80); + auto str_lock_value3 = pickLock(region_id, 80); region->insert("default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key3.dataSize() + str_val_default3.size()); @@ -325,7 +384,7 @@ try MockSSTReader::getMockSSTData().clear(); MockSSTGenerator default_cf{region_id, table_id, ColumnFamilyType::Default}; - default_cf.insert(1180, str_val_default2); + default_cf.insert(14180, str_val_default2); default_cf.finish_file(); default_cf.freeze(); kvs.mutProxyHelperUnsafe()->sst_reader_interfaces = make_mock_sst_reader_interface(); @@ -337,13 +396,25 @@ try { // assign root_of_kvstore_mem_trackers->reset(); - RegionPtr region = tests::makeRegion(1200, start, end, proxy_helper.get()); + RegionID region_id = 15100; + RegionID region_id2 = 15200; + auto [start1, end1] = getStartEnd(1100); + auto [start2, end2] = getStartEnd(1200); + proxy_instance + ->debugAddRegions(kvs, ctx.getTMTContext(), {region_id, region_id2}, {{start1, end1}, {start2, end2}}); + RegionPtr region = kvs.getRegion(region_id); + RegionPtr region2 = kvs.getRegion(region_id2); + + auto str_key = pickKey(region_id, 70); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 70); + auto str_lock_value = pickLock(region_id, 70); + region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - auto str_key2 = RecordKVFormat::genKey(table_id, 80, 111); - auto [str_val_write2, str_val_default2] = proxy_instance->generateTiKVKeyValue(111, 999); - RegionPtr region2 = tests::makeRegion(1201, start, end, proxy_helper.get()); + auto str_key2 = pickKey(region_id, 80); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); + auto str_lock_value2 = pickLock(region_id, 80); region2->insert("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); region2->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); @@ -352,12 +423,14 @@ try root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ( + region->dataSize(), + str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); ASSERT_EQ(region->getData().totalSize(), region->dataSize()); // `region2` is not allowed to access after move, however, we assert here in order to make sure the logic. ASSERT_EQ(region2->dataSize(), 0); ASSERT_EQ(region2->getData().totalSize(), region2->dataSize()); } - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); } CATCH From 53e5cd5aea28ccf87bc2d2ccd386a29782e1a63e Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 5 Feb 2025 17:55:35 +0800 Subject: [PATCH 05/46] fix table memory Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Region.cpp | 6 +----- dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index ecf6209af42..ea77813cf67 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -92,11 +92,7 @@ void Region::remove(const std::string & cf, const TiKVKey & key) void Region::doRemove(ColumnFamilyType type, const TiKVKey & key) { - auto diff = data.remove(type, key); - if (data.region_table_size) - { - *(data.region_table_size) += diff.total(); - } + data.remove(type, key); } void Region::clearAllData() diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index 2e3cda5c38f..dff318aae02 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -201,12 +201,12 @@ try originTableSize, delta, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(originTableSize + delta, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize + delta); region->remove("default", TiKVKey::copyFrom(str_key)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - // ASSERT_EQ(originTableSize, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize); } ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { From 12745a4b2714330eaad29147d5d68c8bd3a790cd Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Thu, 6 Feb 2025 17:34:26 +0800 Subject: [PATCH 06/46] fix test Signed-off-by: Calvin Neo --- .../Storages/KVStore/Decode/RegionTable.cpp | 25 +++++++++++++++++++ .../src/Storages/KVStore/Decode/RegionTable.h | 6 +++++ .../KVStore/MultiRaft/ApplySnapshot.cpp | 4 +-- .../Storages/KVStore/MultiRaft/RegionData.cpp | 21 ++++++++++++++++ .../Storages/KVStore/MultiRaft/RegionData.h | 2 ++ dbms/src/Storages/KVStore/Region.cpp | 8 ++++++ dbms/src/Storages/KVStore/Region.h | 5 +++- .../KVStore/tests/gtest_new_kvstore.cpp | 21 +++++++++++++++- 8 files changed, 87 insertions(+), 5 deletions(-) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index a4a94e15ec0..dd9da5f5803 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -179,6 +179,17 @@ size_t RegionTable::getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) return 0; } +void RegionTable::debugClearTableRegionSize(KeyspaceID keyspace_id, TableID table_id) { + std::scoped_lock lock(mutex); + + auto it = tables.find(KeyspaceTableID{keyspace_id, table_id}); + if (it == tables.end()) + return; + const auto & table = it->second; + if (table.size) + *(table.size) = 0; +} + namespace { /// Remove obsolete data for table after data of `handle_range` is removed from this TiFlash node. @@ -401,6 +412,20 @@ void RegionTable::shrinkRegionRange(const Region & region) internal_region.updateRegionCacheBytes(region.dataSize()); } +void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & new_region) { + const auto region_range_keys = new_region->getRange(); + // Extend region range to make sure data won't be removed. + extendRegionRange(*new_region, *region_range_keys); + if (old_region) { + // `old_region` will no longer contribute to the memory of the table. + auto keyspace_id = region_range_keys->getKeyspaceID(); + auto table_id = region_range_keys->getMappedTableID(); + auto & table = getOrCreateTable(keyspace_id, table_id); + old_region->resetRegionTableSize(); + new_region->setRegionTableSize(table.size); + } +} + void RegionTable::extendRegionRange(const Region & region, const RegionRangeKeys & region_range_keys) { std::lock_guard lock(mutex); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 51d2fdec4e8..5340449c4e3 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -104,10 +104,15 @@ class RegionTable : private boost::noncopyable }; explicit RegionTable(Context & context_); + + // Iterate over all regions in KVStore, and add them to RegionTable. void restore(); void updateRegion(const Region & region); + // Used by apply snapshot. + void replaceRegion(const RegionPtr & old_region, const RegionPtr & new_region); + /// This functional only shrink the table range of this region_id void shrinkRegionRange(const Region & region); @@ -156,6 +161,7 @@ class RegionTable : private boost::noncopyable void clear(); size_t getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const; + void debugClearTableRegionSize(KeyspaceID keyspace_id, TableID table_id); public: // safe ts is maintained by check_leader RPC (https://github.com/tikv/tikv/blob/1ea26a2ac8761af356cc5c0825eb89a0b8fc9749/components/resolved_ts/src/advance.rs#L262), diff --git a/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp b/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp index cd8474c2690..abf5100100f 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/ApplySnapshot.cpp @@ -274,10 +274,8 @@ void KVStore::onSnapshot( // 2. Dump data to RegionTable. { - const auto range = new_region_wrap->getRange(); auto & region_table = tmt.getRegionTable(); - // extend region to make sure data won't be removed. - region_table.extendRegionRange(*new_region_wrap, *range); + region_table.replaceRegion(old_region, new_region_wrap.base); } // Register the new Region. diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index 448fbaffcbc..61cd2d61b30 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -290,6 +290,7 @@ size_t RegionData::totalSize() const void RegionData::assignRegionData(RegionData && rhs) { + auto size = rhs.resetRegionTableSize(); recordMemChange(RegionDataMemDiff{-cf_data_size.load(), -decoded_data_size.load()}); resetMemoryUsage(); @@ -299,6 +300,7 @@ void RegionData::assignRegionData(RegionData && rhs) orphan_keys_info = std::move(rhs.orphan_keys_info); updateMemoryUsage(RegionDataMemDiff{rhs.cf_data_size.load(), rhs.decoded_data_size.load()}); + setRegionTableSize(size); rhs.resetMemoryUsage(); } @@ -411,4 +413,23 @@ size_t RegionData::tryCompactionFilter(Timestamp safe_point) return del_write; } +void RegionData::setRegionTableSize(RegionTableSize size) const { + region_table_size = size; + if(region_table_size) { + LOG_INFO(DB::Logger::get(), "!!!!! ADDD {} O {}", dataSize(), *region_table_size); + region_table_size->fetch_add(dataSize()); + } +} + +RegionTableSize RegionData::resetRegionTableSize() const { + if(region_table_size) { + LOG_INFO(DB::Logger::get(), "!!!!! SUBB {} O {}", dataSize(), *region_table_size); + region_table_size->fetch_sub(dataSize()); + } + auto prev = region_table_size; + // The region no longer binds to a table. + region_table_size = nullptr; + return prev; +} + } // namespace DB diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h index d785d8e95a9..4fcbb24a4e3 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h @@ -84,6 +84,8 @@ class RegionData String summary() const; size_t tryCompactionFilter(Timestamp safe_point); + void setRegionTableSize(RegionTableSize size) const; + RegionTableSize resetRegionTableSize() const; struct OrphanKeysInfo { diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index ea77813cf67..b0c241877db 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -392,4 +392,12 @@ Timestamp Region::getLastObservedReadTso() const return last_observed_read_tso.load(); } +void Region::setRegionTableSize(RegionTableSize size) const { + data.setRegionTableSize(size); +} + +RegionTableSize Region::resetRegionTableSize() const { + return data.resetRegionTableSize(); +} + } // namespace DB diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index b2271d88606..4e607c95f5c 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -231,7 +231,10 @@ class Region : public std::enable_shared_from_this RegionData::OrphanKeysInfo & orphanKeysInfo() { return data.orphan_keys_info; } const RegionData::OrphanKeysInfo & orphanKeysInfo() const { return data.orphan_keys_info; } - void setRegionTableSize(RegionTableSize size) const { data.region_table_size = size; } + // Bind a region to a RegionTable. It could not be bound to another table any more. + // All memory changes to this region would relect to the binded table. + void setRegionTableSize(RegionTableSize size) const; + RegionTableSize resetRegionTableSize() const; public: // Raft Read and Write CommittedScanner createCommittedScanner(bool use_lock, bool need_value); diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index dff318aae02..c79d735f414 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -241,9 +241,13 @@ try root_of_kvstore_mem_trackers->reset(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); reloadKVSFromDisk(false); + ctx.getTMTContext().debugSetKVStore(kvstore); + region_table.restore(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + // Only this region is persisted. + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); } ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { @@ -254,12 +258,14 @@ try auto str_key = pickKey(region_id, 1); auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); auto str_lock_value = pickLock(region_id, 1); - + + region_table.debugClearTableRegionSize(NullspaceID, table_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); region->insert("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); + ASSERT_EQ(str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), region_table.getTableRegionSize(NullspaceID, table_id)); std::optional data_list_read = ReadRegionCommitCache(region, true); ASSERT_TRUE(data_list_read); ASSERT_EQ(1, data_list_read->size()); @@ -267,6 +273,7 @@ try ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); } ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { @@ -278,6 +285,7 @@ try auto str_key = pickKey(region_id, 22); auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); auto str_lock_value = pickLock(region_id, 22); + region_table.debugClearTableRegionSize(NullspaceID, table_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); @@ -285,6 +293,7 @@ try auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); auto str_lock_value2 = pickLock(region_id, 80); region->insert("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); auto expected = str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), expected); @@ -297,6 +306,7 @@ try RecordKVFormat::genKey(table_id, 12050), RecordKVFormat::genKey(table_id, 12099)), initialApplyState())); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(new_region->dataSize(), str_key2.dataSize() + str_val_default2.size()); @@ -307,10 +317,12 @@ try ASSERT_EQ(region->dataSize(), expected); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); ASSERT_EQ(new_region->dataSize(), new_region->getData().totalSize()); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); } { // split & merge with lock root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); RegionID region_id = 13100; RegionID region_id2 = 13102; auto [start, end] = getStartEnd(region_id); @@ -328,6 +340,7 @@ try = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13180, 111, &short_value) .toString(); region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); expected += str_key2.dataSize() + str_lock_value2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); auto new_region = splitRegion( @@ -339,12 +352,14 @@ try RecordKVFormat::genKey(table_id, 13150), RecordKVFormat::genKey(table_id, 13199)), initialApplyState())); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_lock_value.size()); ASSERT_EQ(region->getData().totalSize(), region->dataSize() + decoded_lock_size); ASSERT_EQ(new_region->dataSize(), str_key2.dataSize() + str_lock_value2.size()); ASSERT_EQ(new_region->getData().totalSize(), new_region->dataSize() + decoded_lock_size); region->mergeDataFrom(*new_region); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), expected); ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); @@ -363,6 +378,7 @@ try { // insert & snapshot UInt64 region_id = 14100; + region_table.debugClearTableRegionSize(NullspaceID, table_id); root_of_kvstore_mem_trackers->reset(); auto [start, end] = getStartEnd(region_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); @@ -392,10 +408,12 @@ try ASSERT_EQ(region->dataSize(), str_key2.dataSize() + str_val_default2.size()); ASSERT_EQ(region->getData().totalSize(), region->dataSize()); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key2.dataSize() + str_val_default2.size()); + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); } { // assign root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); RegionID region_id = 15100; RegionID region_id2 = 15200; auto [start1, end1] = getStartEnd(1100); @@ -423,6 +441,7 @@ try root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); ASSERT_EQ( region->dataSize(), str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); From caa245b855ce9347b5991c8fa65d1a1c8622ee61 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 11:35:15 +0800 Subject: [PATCH 07/46] rename Signed-off-by: Calvin Neo --- .../Debug/MockKVStore/MockRaftStoreProxy.cpp | 2 +- .../Storages/KVStore/Decode/RegionTable.cpp | 63 +++++++++---------- .../src/Storages/KVStore/Decode/RegionTable.h | 16 +++-- dbms/src/Storages/KVStore/KVStore.cpp | 2 + .../KVStore/MultiRaft/RaftCommandsKVS.cpp | 2 +- .../Storages/KVStore/MultiRaft/RegionData.cpp | 17 +++-- dbms/src/Storages/KVStore/Region.cpp | 6 +- .../KVStore/tests/gtest_new_kvstore.cpp | 31 ++++++--- 8 files changed, 75 insertions(+), 64 deletions(-) diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index 7c5b4ebb145..1bd0e20aea1 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -183,7 +183,7 @@ void MockRaftStoreProxy::debugAddRegions( auto region = tests::makeRegion(region_ids[i], ranges[i].first, ranges[i].second, kvs.getProxyHelper()); lock.regions.emplace(region_ids[i], region); lock.index.add(region); - tmt.getRegionTable().updateRegion(*region); + tmt.getRegionTable().addRegion(*region); } } } diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index dd9da5f5803..ba52f524fa8 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -46,11 +46,6 @@ namespace FailPoints extern const char force_set_num_regions_for_table[]; } // namespace FailPoints -void RegionTable::InternalRegion::updateRegionCacheBytes(size_t cache_bytes_) -{ - cache_bytes = cache_bytes_; -} - RegionTable::Table & RegionTable::getOrCreateTable(const KeyspaceID keyspace_id, const TableID table_id) { auto ks_table_id = KeyspaceTableID{keyspace_id, table_id}; @@ -78,7 +73,7 @@ RegionTable::InternalRegion & RegionTable::insertRegion( auto region_id = region.id(); region.setRegionTableSize(table.size); auto keyspace_id = region_range_keys.getKeyspaceID(); - auto & table_regions = table.regions; + auto & table_regions = table.internal_regions; // Insert table mapping. // todo check if region_range_keys.mapped_table_id == table.table_id ?? auto [it, ok] = table_regions.emplace(region_id, InternalRegion(region_id, region_range_keys.rawKeys())); @@ -90,14 +85,14 @@ RegionTable::InternalRegion & RegionTable::insertRegion( region_id); // Insert region mapping. - regions[region_id] = KeyspaceTableID{keyspace_id, table.table_id}; + region_infos[region_id] = KeyspaceTableID{keyspace_id, table.table_id}; return it->second; } RegionTable::InternalRegion & RegionTable::doGetInternalRegion(KeyspaceTableID ks_table_id, DB::RegionID region_id) { - return tables.find(ks_table_id)->second.regions.find(region_id)->second; + return tables.find(ks_table_id)->second.internal_regions.find(region_id)->second; } RegionTable::InternalRegion & RegionTable::getOrInsertRegion(const Region & region) @@ -105,7 +100,7 @@ RegionTable::InternalRegion & RegionTable::getOrInsertRegion(const Region & regi auto keyspace_id = region.getKeyspaceID(); auto table_id = region.getMappedTableID(); auto & table = getOrCreateTable(keyspace_id, table_id); - auto & table_regions = table.regions; + auto & table_regions = table.internal_regions; if (auto it = table_regions.find(region.id()); it != table_regions.end()) return it->second; @@ -119,7 +114,7 @@ RegionTable::RegionTable(Context & context_) void RegionTable::clear() { - regions.clear(); + region_infos.clear(); tables.clear(); safe_ts_map.clear(); } @@ -129,7 +124,7 @@ void RegionTable::restore() LOG_INFO(log, "RegionTable restore start"); const auto & tmt = context->getTMTContext(); - tmt.getKVStore()->traverseRegions([this](const RegionID, const RegionPtr & region) { updateRegion(*region); }); + tmt.getKVStore()->traverseRegions([this](const RegionID, const RegionPtr & region) { addRegion(*region); }); LOG_INFO(log, "RegionTable restore end, n_tables={}", tables.size()); } @@ -144,9 +139,9 @@ void RegionTable::removeTable(KeyspaceID keyspace_id, TableID table_id) auto & table = it->second; // Remove from region list. - for (const auto & region_info : table.regions) + for (const auto & region_info : table.internal_regions) { - regions.erase(region_info.first); + region_infos.erase(region_info.first); { std::unique_lock write_lock(rw_lock); safe_ts_map.erase(region_info.first); @@ -159,11 +154,10 @@ void RegionTable::removeTable(KeyspaceID keyspace_id, TableID table_id) LOG_INFO(log, "remove table from RegionTable success, keyspace={} table_id={}", keyspace_id, table_id); } -void RegionTable::updateRegion(const Region & region) +void RegionTable::addRegion(const Region & region) { std::lock_guard lock(mutex); - auto & internal_region = getOrInsertRegion(region); - internal_region.updateRegionCacheBytes(region.dataSize()); + getOrInsertRegion(region); } size_t RegionTable::getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const @@ -179,7 +173,8 @@ size_t RegionTable::getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) return 0; } -void RegionTable::debugClearTableRegionSize(KeyspaceID keyspace_id, TableID table_id) { +void RegionTable::debugClearTableRegionSize(KeyspaceID keyspace_id, TableID table_id) +{ std::scoped_lock lock(mutex); auto it = tables.find(KeyspaceTableID{keyspace_id, table_id}); @@ -239,11 +234,11 @@ void RegionTable::removeRegion(const RegionID region_id, bool remove_data, const std::pair handle_range; { - /// We need to protect `regions` and `table` under mutex lock + /// We need to protect `region_infos` and `table` under mutex lock std::lock_guard lock(mutex); - auto it = regions.find(region_id); - if (it == regions.end()) + auto it = region_infos.find(region_id); + if (it == region_infos.end()) { LOG_WARNING(log, "region does not exist, region_id={}", region_id); return; @@ -251,16 +246,16 @@ void RegionTable::removeRegion(const RegionID region_id, bool remove_data, const ks_table_id = it->second; auto & table = tables.find(ks_table_id)->second; - auto internal_region_it = table.regions.find(region_id); + auto internal_region_it = table.internal_regions.find(region_id); handle_range = internal_region_it->second.range_in_table; - regions.erase(it); + region_infos.erase(it); { std::unique_lock write_lock(rw_lock); safe_ts_map.erase(region_id); } - table.regions.erase(internal_region_it); - if (table.regions.empty()) + table.internal_regions.erase(internal_region_it); + if (table.internal_regions.empty()) { tables.erase(ks_table_id); } @@ -287,7 +282,7 @@ RegionDataReadInfoList RegionTable::tryWriteBlockByRegion(const RegionPtr & regi const auto func_update_region = [&](std::function && callback) -> bool { std::lock_guard lock(mutex); - if (auto it = regions.find(region_id); it != regions.end()) + if (auto it = region_infos.find(region_id); it != region_infos.end()) { auto & internal_region = doGetInternalRegion(it->second, region_id); return callback(internal_region); @@ -339,7 +334,6 @@ RegionDataReadInfoList RegionTable::tryWriteBlockByRegion(const RegionPtr & regi func_update_region([&](InternalRegion & internal_region) -> bool { internal_region.pause_flush = false; - internal_region.updateRegionCacheBytes(region->dataSize()); return true; }); @@ -358,7 +352,7 @@ void RegionTable::handleInternalRegionsByTable( if (auto it = tables.find(KeyspaceTableID{keyspace_id, table_id}); it != tables.end()) { - callback(it->second.regions); + callback(it->second.internal_regions); } } @@ -377,8 +371,8 @@ std::vector RegionTable::getRegionIdsByTable(KeyspaceID keyspace_id, T unlikely(iter != tables.end())) { std::vector ret_regions; - ret_regions.reserve(iter->second.regions.size()); - for (const auto & r : iter->second.regions) + ret_regions.reserve(iter->second.internal_regions.size()); + for (const auto & r : iter->second.internal_regions) { ret_regions.emplace_back(r.first); } @@ -409,14 +403,15 @@ void RegionTable::shrinkRegionRange(const Region & region) std::lock_guard lock(mutex); auto & internal_region = getOrInsertRegion(region); internal_region.range_in_table = region.getRange()->rawKeys(); - internal_region.updateRegionCacheBytes(region.dataSize()); } -void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & new_region) { +void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & new_region) +{ const auto region_range_keys = new_region->getRange(); // Extend region range to make sure data won't be removed. extendRegionRange(*new_region, *region_range_keys); - if (old_region) { + if (old_region) + { // `old_region` will no longer contribute to the memory of the table. auto keyspace_id = region_range_keys->getKeyspaceID(); auto table_id = region_range_keys->getMappedTableID(); @@ -434,7 +429,7 @@ void RegionTable::extendRegionRange(const Region & region, const RegionRangeKeys auto table_id = region_range_keys.getMappedTableID(); auto new_handle_range = region_range_keys.rawKeys(); - if (auto it = regions.find(region_id); it != regions.end()) + if (auto it = region_infos.find(region_id); it != region_infos.end()) { auto ks_tbl_id = KeyspaceTableID{keyspace_id, table_id}; RUNTIME_CHECK_MSG( @@ -506,7 +501,7 @@ bool RegionTable::isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 log, "region_id={} table_id={} leader_safe_ts={} self_safe_ts={}", region_id, - regions[region_id], + region_infos[region_id], *leader_safe_ts, *self_safe_ts); return (*leader_safe_ts > *self_safe_ts) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 5340449c4e3..82013dcacd7 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -79,14 +79,9 @@ class RegionTable : private boost::noncopyable , range_in_table(range_in_table_) {} - void updateRegionCacheBytes(size_t); - RegionID region_id; std::pair range_in_table; bool pause_flush = false; - - private: - Int64 cache_bytes = 0; }; using InternalRegions = std::unordered_map; @@ -99,7 +94,7 @@ class RegionTable : private boost::noncopyable size = std::make_shared(0); } TableID table_id; - InternalRegions regions; + InternalRegions internal_regions; RegionTableSize size; }; @@ -108,7 +103,11 @@ class RegionTable : private boost::noncopyable // Iterate over all regions in KVStore, and add them to RegionTable. void restore(); - void updateRegion(const Region & region); + // When a region is added to region table, happens when split ans restore. + void addRegion(const Region & region); + + // When a reigon is removed out of TiFlash. + void removeRegion(RegionID region_id, bool remove_data, const RegionTaskLock &); // Used by apply snapshot. void replaceRegion(const RegionPtr & old_region, const RegionPtr & new_region); @@ -119,7 +118,6 @@ class RegionTable : private boost::noncopyable /// extend range for possible InternalRegion or add one. void extendRegionRange(const Region & region, const RegionRangeKeys & region_range_keys); - void removeRegion(RegionID region_id, bool remove_data, const RegionTaskLock &); // Protects writeBlockByRegionAndFlush and ensures it's executed by only one thread at the same time. // Only one thread can do this at the same time. @@ -203,7 +201,7 @@ class RegionTable : private boost::noncopyable TableMap tables; using RegionInfoMap = std::unordered_map; - RegionInfoMap regions; + RegionInfoMap region_infos; SafeTsMap safe_ts_map; Context * const context; diff --git a/dbms/src/Storages/KVStore/KVStore.cpp b/dbms/src/Storages/KVStore/KVStore.cpp index 4344bec5044..88830b6629b 100644 --- a/dbms/src/Storages/KVStore/KVStore.cpp +++ b/dbms/src/Storages/KVStore/KVStore.cpp @@ -270,6 +270,8 @@ void KVStore::removeRegion( { auto manage_lock = genRegionMgrWriteLock(task_lock); auto it = manage_lock.regions.find(region_id); + // Disregister from region table size. + it->second->resetRegionTableSize(); manage_lock.index.remove( it->second->makeRaftCommandDelegate(task_lock).getRange().comparableKeys(), region_id); // remove index diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommandsKVS.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommandsKVS.cpp index 9e1031c7e63..4ce88ec3555 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommandsKVS.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommandsKVS.cpp @@ -266,7 +266,7 @@ EngineStoreApplyRes KVStore::handleAdminRaftCmd( // update region_table first is safe, because the core rule is established: the range in RegionTable // is always >= range in KVStore. for (const auto & new_region : split_regions) - region_table.updateRegion(*new_region); + region_table.addRegion(*new_region); region_table.shrinkRegionRange(curr_region); } diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index 61cd2d61b30..f0da03f6d77 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -30,7 +30,6 @@ extern const int ILLFORMAT_RAFT_ROW; void RegionData::recordMemChange(const RegionDataMemDiff & delta) { - LOG_INFO(DB::Logger::get(), "!!!! recordMemChange {}", delta.payload + delta.decoded); if (delta.payload > 0) { root_of_kvstore_mem_trackers->alloc(delta.payload, false); @@ -49,14 +48,12 @@ void RegionData::recordMemChange(const RegionDataMemDiff & delta) void RegionData::updateMemoryUsage(const RegionDataMemDiff & delta) { - LOG_INFO(DB::Logger::get(), "!!!! updateMemoryUsage {}", delta.payload + delta.decoded); cf_data_size += delta.payload; decoded_data_size += delta.decoded; } void RegionData::resetMemoryUsage() { - LOG_INFO(DB::Logger::get(), "!!!! resetMemoryUsage {}", cf_data_size + decoded_data_size); cf_data_size = 0; decoded_data_size = 0; } @@ -413,17 +410,19 @@ size_t RegionData::tryCompactionFilter(Timestamp safe_point) return del_write; } -void RegionData::setRegionTableSize(RegionTableSize size) const { +void RegionData::setRegionTableSize(RegionTableSize size) const +{ region_table_size = size; - if(region_table_size) { - LOG_INFO(DB::Logger::get(), "!!!!! ADDD {} O {}", dataSize(), *region_table_size); + if (region_table_size) + { region_table_size->fetch_add(dataSize()); } } -RegionTableSize RegionData::resetRegionTableSize() const { - if(region_table_size) { - LOG_INFO(DB::Logger::get(), "!!!!! SUBB {} O {}", dataSize(), *region_table_size); +RegionTableSize RegionData::resetRegionTableSize() const +{ + if (region_table_size) + { region_table_size->fetch_sub(dataSize()); } auto prev = region_table_size; diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index b0c241877db..c542ca14202 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -392,11 +392,13 @@ Timestamp Region::getLastObservedReadTso() const return last_observed_read_tso.load(); } -void Region::setRegionTableSize(RegionTableSize size) const { +void Region::setRegionTableSize(RegionTableSize size) const +{ data.setRegionTableSize(size); } -RegionTableSize Region::resetRegionTableSize() const { +RegionTableSize Region::resetRegionTableSize() const +{ return data.resetRegionTableSize(); } diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index c79d735f414..687ee28493b 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -195,12 +195,6 @@ try region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); auto delta = str_key.dataSize() + str_val_default.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), delta); - LOG_INFO( - log, - "!!!! originTableSize {} delta {} T {}", - originTableSize, - delta, - region_table.getTableRegionSize(NullspaceID, table_id)); ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize + delta); region->remove("default", TiKVKey::copyFrom(str_key)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); @@ -258,14 +252,16 @@ try auto str_key = pickKey(region_id, 1); auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); auto str_lock_value = pickLock(region_id, 1); - + region_table.debugClearTableRegionSize(NullspaceID, table_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); region->insert("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); - ASSERT_EQ(str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ( + str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), + region_table.getTableRegionSize(NullspaceID, table_id)); std::optional data_list_read = ReadRegionCommitCache(region, true); ASSERT_TRUE(data_list_read); ASSERT_EQ(1, data_list_read->size()); @@ -450,6 +446,25 @@ try ASSERT_EQ(region2->dataSize(), 0); ASSERT_EQ(region2->getData().totalSize(), region2->dataSize()); } + { + // remove region + RegionID region_id = 16000; + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(region_id); + auto [index, term] + = proxy_instance + ->rawWrite(region_id, {str_key}, {str_val_default}, {WriteCmdType::Put}, {ColumnFamilyType::Default}); + UNUSED(term); + proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); + kvs.handleDestroy(region_id, ctx.getTMTContext()); + ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); + } } CATCH From 2974c44b94323e19c7991939667af279cd07b4ed Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 11:46:42 +0800 Subject: [PATCH 08/46] get table size Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp | 9 +++++++++ dbms/src/Storages/KVStore/MultiRaft/RegionData.h | 1 + dbms/src/Storages/KVStore/Region.cpp | 4 ++++ dbms/src/Storages/KVStore/Region.h | 1 + 4 files changed, 15 insertions(+) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index f0da03f6d77..b5553ee134b 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -431,4 +431,13 @@ RegionTableSize RegionData::resetRegionTableSize() const return prev; } +size_t RegionData::getRegionTableSize() const +{ + if (region_table_size) + { + return (*region_table_size); + } + return 0; +} + } // namespace DB diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h index 4fcbb24a4e3..e18f48c8ba4 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h @@ -86,6 +86,7 @@ class RegionData size_t tryCompactionFilter(Timestamp safe_point); void setRegionTableSize(RegionTableSize size) const; RegionTableSize resetRegionTableSize() const; + size_t getRegionTableSize() const; struct OrphanKeysInfo { diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index c542ca14202..8e48a9883ff 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -402,4 +402,8 @@ RegionTableSize Region::resetRegionTableSize() const return data.resetRegionTableSize(); } +size_t getRegionTableSize() const { + return data.getRegionTableSize(); +} + } // namespace DB diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index 4e607c95f5c..5056d63ac88 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -235,6 +235,7 @@ class Region : public std::enable_shared_from_this // All memory changes to this region would relect to the binded table. void setRegionTableSize(RegionTableSize size) const; RegionTableSize resetRegionTableSize() const; + size_t getRegionTableSize() const; public: // Raft Read and Write CommittedScanner createCommittedScanner(bool use_lock, bool need_value); From 523baabeae34bb7dc86bdbc289ea3398bc05da9b Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 13:48:34 +0800 Subject: [PATCH 09/46] introduce safe ts mgr Signed-off-by: Calvin Neo --- .../Storages/KVStore/Decode/RegionTable.cpp | 76 +---------------- .../src/Storages/KVStore/Decode/RegionTable.h | 41 ++------- .../src/Storages/KVStore/Decode/SafeTsMgr.cpp | 83 +++++++++++++++++++ dbms/src/Storages/KVStore/Decode/SafeTsMgr.h | 77 +++++++++++++++++ dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp | 4 +- .../KVStore/FFI/ProxyFFIStatusService.cpp | 2 +- .../KVStore/Read/LearnerReadWorker.cpp | 2 +- dbms/src/Storages/KVStore/Region.cpp | 3 +- .../KVStore/tests/gtest_learner_read.cpp | 4 +- .../KVStore/tests/gtest_sync_status.cpp | 5 +- 10 files changed, 180 insertions(+), 117 deletions(-) create mode 100644 dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp create mode 100644 dbms/src/Storages/KVStore/Decode/SafeTsMgr.h diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index ba52f524fa8..1d4dc7d3918 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -116,7 +116,7 @@ void RegionTable::clear() { region_infos.clear(); tables.clear(); - safe_ts_map.clear(); + safe_ts_mgr.safe_ts_map.clear(); } void RegionTable::restore() @@ -143,8 +143,7 @@ void RegionTable::removeTable(KeyspaceID keyspace_id, TableID table_id) { region_infos.erase(region_info.first); { - std::unique_lock write_lock(rw_lock); - safe_ts_map.erase(region_info.first); + safe_ts_mgr.remove(region_info.first); } } @@ -250,10 +249,7 @@ void RegionTable::removeRegion(const RegionID region_id, bool remove_data, const handle_range = internal_region_it->second.range_in_table; region_infos.erase(it); - { - std::unique_lock write_lock(rw_lock); - safe_ts_map.erase(region_id); - } + safe_ts_mgr.remove(region_id); table.internal_regions.erase(internal_region_it); if (table.internal_regions.empty()) { @@ -485,70 +481,4 @@ RegionPtrWithCheckpointInfo::RegionPtrWithCheckpointInfo(const Base & base_, Che , checkpoint_info(std::move(checkpoint_info_)) {} -bool RegionTable::isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * self_safe_ts) -{ - { - std::shared_lock lock(rw_lock); - auto it = safe_ts_map.find(region_id); - if (it == safe_ts_map.end()) - { - return false; - } - *leader_safe_ts = it->second->leader_safe_ts.load(std::memory_order_relaxed); - *self_safe_ts = it->second->self_safe_ts.load(std::memory_order_relaxed); - } - LOG_TRACE( - log, - "region_id={} table_id={} leader_safe_ts={} self_safe_ts={}", - region_id, - region_infos[region_id], - *leader_safe_ts, - *self_safe_ts); - return (*leader_safe_ts > *self_safe_ts) - && ((*leader_safe_ts >> TsoPhysicalShiftBits) - (*self_safe_ts >> TsoPhysicalShiftBits) > SafeTsDiffThreshold); -} - -UInt64 RegionTable::getSelfSafeTS(UInt64 region_id) const -{ - std::shared_lock lock(rw_lock); - auto it = safe_ts_map.find(region_id); - if (it == safe_ts_map.end()) - { - return 0; - } - return it->second->self_safe_ts.load(std::memory_order_relaxed); -} - -void RegionTable::updateSafeTS(UInt64 region_id, UInt64 leader_safe_ts, UInt64 self_safe_ts) -{ - { - std::shared_lock lock(rw_lock); - auto it = safe_ts_map.find(region_id); - if (it == safe_ts_map.end() && (leader_safe_ts == InvalidSafeTS || self_safe_ts == InvalidSafeTS)) - { - LOG_TRACE( - log, - "safe_ts_map empty but safe ts invalid, region_id={} leader_safe_ts={} self_safe_ts={}", - region_id, - leader_safe_ts, - self_safe_ts); - return; - } - if (it != safe_ts_map.end()) - { - if (leader_safe_ts != InvalidSafeTS) - { - it->second->leader_safe_ts.store(leader_safe_ts, std::memory_order_relaxed); - } - if (self_safe_ts != InvalidSafeTS) - { - it->second->self_safe_ts.store(self_safe_ts, std::memory_order_relaxed); - } - return; - } - } - std::unique_lock lock(rw_lock); - safe_ts_map.emplace(region_id, std::make_unique(leader_safe_ts, self_safe_ts)); -} - } // namespace DB diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 82013dcacd7..fc259b13d83 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -55,18 +56,6 @@ using CheckpointInfoPtr = std::shared_ptr; struct CheckpointIngestInfo; using CheckpointIngestInfoPtr = std::shared_ptr; -using SafeTS = UInt64; -enum : SafeTS -{ - InvalidSafeTS = std::numeric_limits::max(), -}; - -using TsoShiftBits = UInt64; -enum : TsoShiftBits -{ - TsoPhysicalShiftBits = 18, -}; - class RegionTable : private boost::noncopyable { public: @@ -161,29 +150,9 @@ class RegionTable : private boost::noncopyable size_t getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const; void debugClearTableRegionSize(KeyspaceID keyspace_id, TableID table_id); -public: - // safe ts is maintained by check_leader RPC (https://github.com/tikv/tikv/blob/1ea26a2ac8761af356cc5c0825eb89a0b8fc9749/components/resolved_ts/src/advance.rs#L262), - // leader_safe_ts is the safe_ts in leader, leader will send to learner to advance safe_ts of learner, and TiFlash will record the safe_ts into safe_ts_map in check_leader RPC. - // self_safe_ts is the safe_ts in TiFlah learner. When TiFlash proxy receive from leader, TiFlash will update safe_ts_map when TiFlash has applied the raft log to applied_index. - struct SafeTsEntry - { - explicit SafeTsEntry(UInt64 leader_safe_ts, UInt64 self_safe_ts) - : leader_safe_ts(leader_safe_ts) - , self_safe_ts(self_safe_ts) - {} - std::atomic leader_safe_ts; - std::atomic self_safe_ts; - }; - using SafeTsEntryPtr = std::unique_ptr; - using SafeTsMap = std::unordered_map; + SafeTsMgr & safeTsMgr() { return safe_ts_mgr; } + const SafeTsMgr & safeTsMgr() const { return safe_ts_mgr; } - void updateSafeTS(UInt64 region_id, UInt64 leader_safe_ts, UInt64 self_safe_ts); - - // unit: ms. If safe_ts diff is larger than 2min, we think the data synchronization progress is far behind the leader. - static const UInt64 SafeTsDiffThreshold = 2 * 60 * 1000; - bool isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * self_safe_ts); - - UInt64 getSelfSafeTS(UInt64 region_id) const; private: friend class MockTiDB; @@ -202,12 +171,12 @@ class RegionTable : private boost::noncopyable using RegionInfoMap = std::unordered_map; RegionInfoMap region_infos; - SafeTsMap safe_ts_map; Context * const context; + SafeTsMgr safe_ts_mgr; + mutable std::mutex mutex; - mutable std::shared_mutex rw_lock; LoggerPtr log; }; diff --git a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp b/dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp new file mode 100644 index 00000000000..2ec9b58ada2 --- /dev/null +++ b/dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp @@ -0,0 +1,83 @@ +// Copyright 2025 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +namespace DB +{ +bool SafeTsMgr::isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * self_safe_ts) +{ + { + std::shared_lock lock(rw_lock); + auto it = safe_ts_map.find(region_id); + if (it == safe_ts_map.end()) + { + return false; + } + *leader_safe_ts = it->second->leader_safe_ts.load(std::memory_order_relaxed); + *self_safe_ts = it->second->self_safe_ts.load(std::memory_order_relaxed); + } + LOG_TRACE( + DB::Logger::get(), + "region_id={} leader_safe_ts={} self_safe_ts={}", + region_id, + *leader_safe_ts, + *self_safe_ts); + return (*leader_safe_ts > *self_safe_ts) + && ((*leader_safe_ts >> TsoPhysicalShiftBits) - (*self_safe_ts >> TsoPhysicalShiftBits) > SafeTsDiffThreshold); +} + +UInt64 SafeTsMgr::getSelfSafeTS(UInt64 region_id) const +{ + std::shared_lock lock(rw_lock); + auto it = safe_ts_map.find(region_id); + if (it == safe_ts_map.end()) + { + return 0; + } + return it->second->self_safe_ts.load(std::memory_order_relaxed); +} + +void SafeTsMgr::updateSafeTS(UInt64 region_id, UInt64 leader_safe_ts, UInt64 self_safe_ts) +{ + { + std::shared_lock lock(rw_lock); + auto it = safe_ts_map.find(region_id); + if (it == safe_ts_map.end() && (leader_safe_ts == InvalidSafeTS || self_safe_ts == InvalidSafeTS)) + { + LOG_TRACE( + DB::Logger::get(), + "safe_ts_map empty but safe ts invalid, region_id={} leader_safe_ts={} self_safe_ts={}", + region_id, + leader_safe_ts, + self_safe_ts); + return; + } + if (it != safe_ts_map.end()) + { + if (leader_safe_ts != InvalidSafeTS) + { + it->second->leader_safe_ts.store(leader_safe_ts, std::memory_order_relaxed); + } + if (self_safe_ts != InvalidSafeTS) + { + it->second->self_safe_ts.store(self_safe_ts, std::memory_order_relaxed); + } + return; + } + } + std::unique_lock lock(rw_lock); + safe_ts_map.emplace(region_id, std::make_unique(leader_safe_ts, self_safe_ts)); +} +} // namespace DB diff --git a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h b/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h new file mode 100644 index 00000000000..40fe9078321 --- /dev/null +++ b/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h @@ -0,0 +1,77 @@ +// Copyright 2025 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace DB +{ + +using SafeTS = UInt64; +enum : SafeTS +{ + InvalidSafeTS = std::numeric_limits::max(), +}; + +using TsoShiftBits = UInt64; +enum : TsoShiftBits +{ + TsoPhysicalShiftBits = 18, +}; + +struct SafeTsMgr +{ + // safe ts is maintained by check_leader RPC (https://github.com/tikv/tikv/blob/1ea26a2ac8761af356cc5c0825eb89a0b8fc9749/components/resolved_ts/src/advance.rs#L262), + // leader_safe_ts is the safe_ts in leader, leader will send to learner to advance safe_ts of learner, and TiFlash will record the safe_ts into safe_ts_map in check_leader RPC. + // self_safe_ts is the safe_ts in TiFlah learner. When TiFlash proxy receive from leader, TiFlash will update safe_ts_map when TiFlash has applied the raft log to applied_index. + struct SafeTsEntry + { + explicit SafeTsEntry(UInt64 leader_safe_ts, UInt64 self_safe_ts) + : leader_safe_ts(leader_safe_ts) + , self_safe_ts(self_safe_ts) + {} + std::atomic leader_safe_ts; + std::atomic self_safe_ts; + }; + using SafeTsEntryPtr = std::unique_ptr; + using SafeTsMap = std::unordered_map; + + void updateSafeTS(UInt64 region_id, UInt64 leader_safe_ts, UInt64 self_safe_ts); + + // unit: ms. If safe_ts diff is larger than 2min, we think the data synchronization progress is far behind the leader. + static const UInt64 SafeTsDiffThreshold = 2 * 60 * 1000; + bool isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * self_safe_ts); + + UInt64 getSelfSafeTS(UInt64 region_id) const; + + void remove(UInt64 region_id) + { + std::unique_lock write_lock(rw_lock); + safe_ts_map.erase(region_id); + } + + SafeTsMap safe_ts_map; + mutable std::shared_mutex rw_lock; +}; +} // namespace DB diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp index f143b693775..819b018806f 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp @@ -978,7 +978,7 @@ void HandleSafeTSUpdate( try { RegionTable & region_table = server->tmt->getRegionTable(); - region_table.updateSafeTS(region_id, leader_safe_ts, self_safe_ts); + region_table.safeTsMgr().updateSafeTS(region_id, leader_safe_ts, self_safe_ts); } catch (...) { @@ -1072,4 +1072,4 @@ void ReportThreadAllocateBatch( } } -} // namespace DB \ No newline at end of file +} // namespace DB diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFIStatusService.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFIStatusService.cpp index 41b72968164..f79b8110957 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFIStatusService.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFIStatusService.cpp @@ -117,7 +117,7 @@ HttpRequestRes HandleHttpRequestSyncStatus( { UInt64 leader_safe_ts; UInt64 self_safe_ts; - if (!region_table.isSafeTSLag(region.first, &leader_safe_ts, &self_safe_ts)) + if (!region_table.safeTsMgr().isSafeTSLag(region.first, &leader_safe_ts, &self_safe_ts)) { region_list.push_back(region.first); } diff --git a/dbms/src/Storages/KVStore/Read/LearnerReadWorker.cpp b/dbms/src/Storages/KVStore/Read/LearnerReadWorker.cpp index ee2df9cb4f0..3a6f5f2c82f 100644 --- a/dbms/src/Storages/KVStore/Read/LearnerReadWorker.cpp +++ b/dbms/src/Storages/KVStore/Read/LearnerReadWorker.cpp @@ -125,7 +125,7 @@ std::vector LearnerReadWorker::buildBatchReadIndexReq const RegionID region_id = region_to_query.region_id; // don't stale read in test scenarios. bool can_stale_read = mvcc_query_info.start_ts != std::numeric_limits::max() - && start_ts <= region_table.getSelfSafeTS(region_id); + && start_ts <= region_table.safeTsMgr().getSelfSafeTS(region_id); if (can_stale_read) { batch_read_index_result.emplace(region_id, kvrpcpb::ReadIndexResponse()); diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 8e48a9883ff..34f91a70b4b 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -402,7 +402,8 @@ RegionTableSize Region::resetRegionTableSize() const return data.resetRegionTableSize(); } -size_t getRegionTableSize() const { +size_t Region::getRegionTableSize() const +{ return data.getRegionTableSize(); } diff --git a/dbms/src/Storages/KVStore/tests/gtest_learner_read.cpp b/dbms/src/Storages/KVStore/tests/gtest_learner_read.cpp index eeaecedfd6a..d2077ff541f 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_learner_read.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_learner_read.cpp @@ -125,8 +125,8 @@ try // region_202 has no safe ts info, can not stale read // region_203 read index cache exist in the `mvcc_query_info` RegionTable region_table(global_ctx); - region_table.updateSafeTS(region_id_200, /*leader_safe_ts*/ 10005, /*self_safe_ts*/ 10005); - region_table.updateSafeTS(region_id_201, /*leader_safe_ts*/ 9995, /*self_safe_ts*/ 9995); + region_table.safeTsMgr().updateSafeTS(region_id_200, /*leader_safe_ts*/ 10005, /*self_safe_ts*/ 10005); + region_table.safeTsMgr().updateSafeTS(region_id_201, /*leader_safe_ts*/ 9995, /*self_safe_ts*/ 9995); RegionsReadIndexResult read_index_result; auto requests = buildBatchReadIndex(worker, region_table, snapshot, read_index_result); diff --git a/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp b/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp index 36a9df765bf..babe922e675 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp @@ -193,7 +193,10 @@ void makeRegionsLag(size_t lag_num) auto & tmt = TiFlashTestEnv::getContext()->getTMTContext(); for (size_t i = 0; i < lag_num; i++) { - tmt.getRegionTable().updateSafeTS(i, (RegionTable::SafeTsDiffThreshold + 1) << TsoPhysicalShiftBits, 0); + tmt.getRegionTable().safeTsMgr().updateSafeTS( + i, + (SafeTsMgr::SafeTsDiffThreshold + 1) << TsoPhysicalShiftBits, + 0); } } From 7f67ccba937e6e98b349a607a8d78fda9a81a925 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 16:33:15 +0800 Subject: [PATCH 10/46] warn table Signed-off-by: Calvin Neo --- dbms/src/Server/Server.cpp | 1 + .../Storages/KVStore/Decode/RegionTable.cpp | 15 ++++--- .../src/Storages/KVStore/Decode/RegionTable.h | 5 +-- .../Storages/KVStore/Decode/RegionTable_fwd.h | 9 +++- dbms/src/Storages/KVStore/KVStore.cpp | 2 +- dbms/src/Storages/KVStore/KVStore.h | 5 ++- .../KVStore/MultiRaft/RaftCommands.cpp | 24 ++++++++++ .../Storages/KVStore/MultiRaft/RegionData.cpp | 45 ++++++++++++------- .../Storages/KVStore/MultiRaft/RegionData.h | 8 ++-- dbms/src/Storages/KVStore/Region.cpp | 8 ++-- dbms/src/Storages/KVStore/Region.h | 6 ++- 11 files changed, 91 insertions(+), 37 deletions(-) diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index bd17d44a997..d504bfd5736 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -1140,6 +1140,7 @@ int Server::main(const std::vector & /*args*/) store_meta.set_id(store_ident->store_id()); store_meta.set_node_state(metapb::NodeState::Preparing); kvstore->setStore(store_meta); + kvstore->setKVStoreMemoryLimit(settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity)); } global_context->getTMTContext().reloadConfig(config()); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index 1d4dc7d3918..165ff6554aa 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -71,7 +71,7 @@ RegionTable::InternalRegion & RegionTable::insertRegion( const Region & region) { auto region_id = region.id(); - region.setRegionTableSize(table.size); + region.setRegionTableCtx(table.ctx); auto keyspace_id = region_range_keys.getKeyspaceID(); auto & table_regions = table.internal_regions; // Insert table mapping. @@ -167,8 +167,8 @@ size_t RegionTable::getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) if (it == tables.end()) return 0; const auto & table = it->second; - if (table.size) - return *(table.size); + if (table.ctx) + return table.ctx->table_size; return 0; } @@ -180,8 +180,8 @@ void RegionTable::debugClearTableRegionSize(KeyspaceID keyspace_id, TableID tabl if (it == tables.end()) return; const auto & table = it->second; - if (table.size) - *(table.size) = 0; + if (table.ctx) + table.ctx->table_size = 0; } namespace @@ -272,6 +272,7 @@ void RegionTable::removeRegion(const RegionID region_id, bool remove_data, const } } +// RaftCommands will directly call `writeCommittedByRegion`. RegionDataReadInfoList RegionTable::tryWriteBlockByRegion(const RegionPtr & region) { const RegionID region_id = region->id(); @@ -412,8 +413,8 @@ void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & auto keyspace_id = region_range_keys->getKeyspaceID(); auto table_id = region_range_keys->getMappedTableID(); auto & table = getOrCreateTable(keyspace_id, table_id); - old_region->resetRegionTableSize(); - new_region->setRegionTableSize(table.size); + old_region->resetRegionTableCtx(); + new_region->setRegionTableCtx(table.ctx); } } diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index fc259b13d83..0dd300fe8c7 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -80,11 +80,11 @@ class RegionTable : private boost::noncopyable explicit Table(const TableID table_id_) : table_id(table_id_) { - size = std::make_shared(0); + ctx = createRegionTableCtx(); } TableID table_id; InternalRegions internal_regions; - RegionTableSize size; + RegionTableCtx ctx; }; explicit RegionTable(Context & context_); @@ -107,7 +107,6 @@ class RegionTable : private boost::noncopyable /// extend range for possible InternalRegion or add one. void extendRegionRange(const Region & region, const RegionRangeKeys & region_range_keys); - // Protects writeBlockByRegionAndFlush and ensures it's executed by only one thread at the same time. // Only one thread can do this at the same time. // The original name for this function is tryFlushRegion. diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h index a3bdf4e6f1b..f571b3591ad 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h @@ -19,5 +19,12 @@ namespace DB { -using RegionTableSize = std::shared_ptr; +struct RegionTableCtxInner { + std::atomic_int64_t table_size; + std::atomic_bool warned; +}; +using RegionTableCtx = std::shared_ptr; +inline RegionTableCtx createRegionTableCtx() { + return std::make_shared(0, false); +} } // namespace DB diff --git a/dbms/src/Storages/KVStore/KVStore.cpp b/dbms/src/Storages/KVStore/KVStore.cpp index 88830b6629b..f9dbe6e4b3a 100644 --- a/dbms/src/Storages/KVStore/KVStore.cpp +++ b/dbms/src/Storages/KVStore/KVStore.cpp @@ -271,7 +271,7 @@ void KVStore::removeRegion( auto manage_lock = genRegionMgrWriteLock(task_lock); auto it = manage_lock.regions.find(region_id); // Disregister from region table size. - it->second->resetRegionTableSize(); + it->second->resetRegionTableCtx(); manage_lock.index.remove( it->second->makeRaftCommandDelegate(task_lock).getRange().comparableKeys(), region_id); // remove index diff --git a/dbms/src/Storages/KVStore/KVStore.h b/dbms/src/Storages/KVStore/KVStore.h index 953b95047b6..5b85d799bcd 100644 --- a/dbms/src/Storages/KVStore/KVStore.h +++ b/dbms/src/Storages/KVStore/KVStore.h @@ -158,7 +158,9 @@ class KVStore final : private boost::noncopyable void traverseRegions(std::function && callback) const; RegionPtr genRegionPtr(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term); void handleDestroy(UInt64 region_id, TMTContext & tmt); - + void setKVStoreMemoryLimit(size_t s) { maximum_kvstore_memory = s; } + size_t getKVStoreMemoryLimit() const { return maximum_kvstore_memory; } + public: // Raft Read and Write EngineStoreApplyRes handleAdminRaftCmd( raft_cmdpb::AdminRequest && request, @@ -417,6 +419,7 @@ class KVStore final : private boost::noncopyable ProxyConfigSummary proxy_config_summary; JointThreadInfoJeallocMapPtr joint_memory_allocation_map; + size_t maximum_kvstore_memory = 0; }; /// Encapsulation of lock guard of task mutex in KVStore diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp index c4f52f79901..0d468999af6 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp @@ -28,6 +28,8 @@ #include #include +extern std::atomic real_rss; + namespace DB { Region::CommittedScanner Region::createCommittedScanner(bool use_lock, bool need_value) @@ -473,6 +475,25 @@ std::pair Region::handleWriteRaftCmd( handle_write_cmd_func(); } + if (default_put_key_count + lock_put_key_count > 0) { + // If there are data flow in, we will check if the memory is exhaused. + auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); + auto current = real_rss.load(); + /// Region management such as split/merge doesn't change the memory consumed by a table in KVStore. + /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. + /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. + /// So, we only print once for a table, until one memory reduce event will happen. + if unlikely (limit > 0 && current > 0 && static_cast(current) > limit) { + auto table_size = getRegionTableSize(); + if (table_size > 0.5 * current) { + if (!setRegionTableWarned(true)) { + // If it is the first time. + LOG_INFO(log, "Memory limit exeeded, current{} limit={} table_id={} keyspace_id={} region_id={}", current, limit, mapped_table_id, keyspace_id, id()); + } + } + } + } + // If transfer-leader happened during ingest-sst, there might be illegal data. if (0 != cmds.len) { @@ -509,6 +530,9 @@ std::pair Region::handleWriteRaftCmd( fmt::join(entry_infos.begin(), entry_infos.end(), ":")); e.rethrow(); } + if (!data_list_to_remove.empty()) { + setRegionTableWarned(false); + } } meta.setApplied(index, term); diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index b5553ee134b..0a3be92c412 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -40,9 +40,9 @@ void RegionData::recordMemChange(const RegionDataMemDiff & delta) } // A region splits and merges, but its derived region all belong to the same table. // So we can summarize here rather than `updateMemoryUsage`. - if (region_table_size) + if (region_table_ctx) { - *region_table_size += delta.total(); + region_table_ctx->table_size += delta.total(); } } @@ -287,7 +287,7 @@ size_t RegionData::totalSize() const void RegionData::assignRegionData(RegionData && rhs) { - auto size = rhs.resetRegionTableSize(); + auto size = rhs.resetRegionTableCtx(); recordMemChange(RegionDataMemDiff{-cf_data_size.load(), -decoded_data_size.load()}); resetMemoryUsage(); @@ -297,7 +297,7 @@ void RegionData::assignRegionData(RegionData && rhs) orphan_keys_info = std::move(rhs.orphan_keys_info); updateMemoryUsage(RegionDataMemDiff{rhs.cf_data_size.load(), rhs.decoded_data_size.load()}); - setRegionTableSize(size); + setRegionTableCtx(size); rhs.resetMemoryUsage(); } @@ -410,34 +410,49 @@ size_t RegionData::tryCompactionFilter(Timestamp safe_point) return del_write; } -void RegionData::setRegionTableSize(RegionTableSize size) const +void RegionData::setRegionTableCtx(RegionTableCtx ctx) const { - region_table_size = size; - if (region_table_size) + region_table_ctx = ctx; + if (region_table_ctx) { - region_table_size->fetch_add(dataSize()); + region_table_ctx->table_size.fetch_add(dataSize()); } } -RegionTableSize RegionData::resetRegionTableSize() const +RegionTableCtx RegionData::resetRegionTableCtx() const { - if (region_table_size) + if (region_table_ctx) { - region_table_size->fetch_sub(dataSize()); + region_table_ctx->table_size.fetch_sub(dataSize()); } - auto prev = region_table_size; + auto prev = region_table_ctx; // The region no longer binds to a table. - region_table_size = nullptr; + region_table_ctx = nullptr; return prev; } size_t RegionData::getRegionTableSize() const { - if (region_table_size) + if (region_table_ctx) { - return (*region_table_size); + return region_table_ctx->table_size; } return 0; } +bool RegionData::getRegionTableWarned() const { + if (region_table_ctx) + { + return region_table_ctx->warned; + } + return 0; +} + +bool RegionData::setRegionTableWarned(bool desired) const { + if (region_table_ctx){ + return region_table_ctx->warned.exchange(desired); + } + return false; +} + } // namespace DB diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h index e18f48c8ba4..e3215e2b1da 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h @@ -84,9 +84,11 @@ class RegionData String summary() const; size_t tryCompactionFilter(Timestamp safe_point); - void setRegionTableSize(RegionTableSize size) const; - RegionTableSize resetRegionTableSize() const; + void setRegionTableCtx(RegionTableCtx) const; + RegionTableCtx resetRegionTableCtx() const; size_t getRegionTableSize() const; + bool getRegionTableWarned() const; + bool setRegionTableWarned(bool) const; struct OrphanKeysInfo { @@ -142,7 +144,7 @@ class RegionData std::atomic cf_data_size = 0; // Size of decoded structures for convenient access, considered as amplification in memory. std::atomic decoded_data_size = 0; - mutable RegionTableSize region_table_size; + mutable RegionTableCtx region_table_ctx; }; } // namespace DB diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 34f91a70b4b..d68f6b3925c 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -392,14 +392,14 @@ Timestamp Region::getLastObservedReadTso() const return last_observed_read_tso.load(); } -void Region::setRegionTableSize(RegionTableSize size) const +void Region::setRegionTableCtx(RegionTableCtx size) const { - data.setRegionTableSize(size); + data.setRegionTableCtx(size); } -RegionTableSize Region::resetRegionTableSize() const +RegionTableCtx Region::resetRegionTableCtx() const { - return data.resetRegionTableSize(); + return data.resetRegionTableCtx(); } size_t Region::getRegionTableSize() const diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index 5056d63ac88..a53714a9a5e 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -233,9 +233,11 @@ class Region : public std::enable_shared_from_this // Bind a region to a RegionTable. It could not be bound to another table any more. // All memory changes to this region would relect to the binded table. - void setRegionTableSize(RegionTableSize size) const; - RegionTableSize resetRegionTableSize() const; + void setRegionTableCtx(RegionTableCtx size) const; + RegionTableCtx resetRegionTableCtx() const; size_t getRegionTableSize() const; + bool getRegionTableWarned() const { return data.getRegionTableWarned(); } + bool setRegionTableWarned(bool desired) const { return data.setRegionTableWarned(desired); } public: // Raft Read and Write CommittedScanner createCommittedScanner(bool use_lock, bool need_value); From 11e285bc7243b5e2677988f790f28b711cc7cc2d Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 16:34:01 +0800 Subject: [PATCH 11/46] fmt Signed-off-by: Calvin Neo --- dbms/src/Server/Server.cpp | 3 ++- .../Storages/KVStore/Decode/RegionTable_fwd.h | 6 +++-- dbms/src/Storages/KVStore/KVStore.h | 2 +- .../KVStore/MultiRaft/RaftCommands.cpp | 24 ++++++++++++++----- .../Storages/KVStore/MultiRaft/RegionData.cpp | 9 ++++--- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index d504bfd5736..a9b39f79658 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -1140,7 +1140,8 @@ int Server::main(const std::vector & /*args*/) store_meta.set_id(store_ident->store_id()); store_meta.set_node_state(metapb::NodeState::Preparing); kvstore->setStore(store_meta); - kvstore->setKVStoreMemoryLimit(settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity)); + kvstore->setKVStoreMemoryLimit( + settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity)); } global_context->getTMTContext().reloadConfig(config()); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h index f571b3591ad..e94e384c730 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h @@ -19,12 +19,14 @@ namespace DB { -struct RegionTableCtxInner { +struct RegionTableCtxInner +{ std::atomic_int64_t table_size; std::atomic_bool warned; }; using RegionTableCtx = std::shared_ptr; -inline RegionTableCtx createRegionTableCtx() { +inline RegionTableCtx createRegionTableCtx() +{ return std::make_shared(0, false); } } // namespace DB diff --git a/dbms/src/Storages/KVStore/KVStore.h b/dbms/src/Storages/KVStore/KVStore.h index 5b85d799bcd..fd44abe5836 100644 --- a/dbms/src/Storages/KVStore/KVStore.h +++ b/dbms/src/Storages/KVStore/KVStore.h @@ -160,7 +160,7 @@ class KVStore final : private boost::noncopyable void handleDestroy(UInt64 region_id, TMTContext & tmt); void setKVStoreMemoryLimit(size_t s) { maximum_kvstore_memory = s; } size_t getKVStoreMemoryLimit() const { return maximum_kvstore_memory; } - + public: // Raft Read and Write EngineStoreApplyRes handleAdminRaftCmd( raft_cmdpb::AdminRequest && request, diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp index 0d468999af6..1879ef128b9 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp @@ -475,7 +475,8 @@ std::pair Region::handleWriteRaftCmd( handle_write_cmd_func(); } - if (default_put_key_count + lock_put_key_count > 0) { + if (default_put_key_count + lock_put_key_count > 0) + { // If there are data flow in, we will check if the memory is exhaused. auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); auto current = real_rss.load(); @@ -483,12 +484,22 @@ std::pair Region::handleWriteRaftCmd( /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. /// So, we only print once for a table, until one memory reduce event will happen. - if unlikely (limit > 0 && current > 0 && static_cast(current) > limit) { + if unlikely (limit > 0 && current > 0 && static_cast(current) > limit) + { auto table_size = getRegionTableSize(); - if (table_size > 0.5 * current) { - if (!setRegionTableWarned(true)) { + if (table_size > 0.5 * current) + { + if (!setRegionTableWarned(true)) + { // If it is the first time. - LOG_INFO(log, "Memory limit exeeded, current{} limit={} table_id={} keyspace_id={} region_id={}", current, limit, mapped_table_id, keyspace_id, id()); + LOG_INFO( + log, + "Memory limit exeeded, current{} limit={} table_id={} keyspace_id={} region_id={}", + current, + limit, + mapped_table_id, + keyspace_id, + id()); } } } @@ -530,7 +541,8 @@ std::pair Region::handleWriteRaftCmd( fmt::join(entry_infos.begin(), entry_infos.end(), ":")); e.rethrow(); } - if (!data_list_to_remove.empty()) { + if (!data_list_to_remove.empty()) + { setRegionTableWarned(false); } } diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index 0a3be92c412..133f2c0c63e 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -440,7 +440,8 @@ size_t RegionData::getRegionTableSize() const return 0; } -bool RegionData::getRegionTableWarned() const { +bool RegionData::getRegionTableWarned() const +{ if (region_table_ctx) { return region_table_ctx->warned; @@ -448,8 +449,10 @@ bool RegionData::getRegionTableWarned() const { return 0; } -bool RegionData::setRegionTableWarned(bool desired) const { - if (region_table_ctx){ +bool RegionData::setRegionTableWarned(bool desired) const +{ + if (region_table_ctx) + { return region_table_ctx->warned.exchange(desired); } return false; From 49fe956e51e49182b8f635cbe8de884899bffb23 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 20:33:52 +0800 Subject: [PATCH 12/46] warn Signed-off-by: Calvin Neo --- dbms/src/Common/BackgroundTask.cpp | 1 + .../Debug/MockKVStore/MockRaftStoreProxy.h | 51 +++++++ dbms/src/Storages/KVStore/KVStore.h | 4 + .../KVStore/MultiRaft/RaftCommands.cpp | 12 +- .../KVStore/tests/gtest_new_kvstore.cpp | 137 ++++++++++++++---- 5 files changed, 173 insertions(+), 32 deletions(-) diff --git a/dbms/src/Common/BackgroundTask.cpp b/dbms/src/Common/BackgroundTask.cpp index 81786c05f5b..11158714471 100644 --- a/dbms/src/Common/BackgroundTask.cpp +++ b/dbms/src/Common/BackgroundTask.cpp @@ -90,6 +90,7 @@ void CollectProcInfoBackgroundTask::memCheckJob() { try { + LOG_INFO(DB::Logger::get(), "!!!! CollectProcInfoBackgroundTask"); double resident_set; Int64 cur_proc_num_threads = 1; UInt64 cur_virt_size = 0; diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h index e346b5155f6..9bfcff01424 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h @@ -266,6 +266,57 @@ struct MockRaftStoreProxy : MutexLockWrap void clear(); + struct WriteCmdsViewHolder + { + WriteCmdsViewHolder( + std::vector kk, + std::vector vv, + std::vector tt, + std::vector ff) + { + kholder = std::move(kk); + vholder = std::move(vv); + for (size_t i = 0; i < kholder.size(); i++) + { + kbuff.push_back(strIntoView(&kholder[i])); + } + for (size_t i = 0; i < vholder.size(); i++) + { + vbuff.push_back(strIntoView(&vholder[i])); + } + cmd_type = std::move(tt); + cmd_cf = std::move(ff); + } + + const BaseBuffView * getKeys() const { return kbuff.data(); } + + const BaseBuffView * getVals() const { return vbuff.data(); } + + const WriteCmdType * getTypes() const { return cmd_type.data(); } + + const ColumnFamilyType * getCfs() const { return cmd_cf.data(); } + + std::vector kholder; + std::vector vholder; + std::vector kbuff; + std::vector vbuff; + std::vector cmd_type; + std::vector cmd_cf; + }; + + static std::tuple> createWriteCmdsView( + std::vector keys, + std::vector vals, + std::vector cmd_types, + std::vector cmd_cf) + { + std::shared_ptr holder + = std::make_shared(keys, vals, cmd_types, cmd_cf); + return std::make_tuple( + WriteCmdsView{holder->getKeys(), holder->getVals(), holder->getTypes(), holder->getCfs(), keys.size()}, + holder); + } + std::pair generateTiKVKeyValue(uint64_t tso, int64_t t) const; MockRaftStoreProxy() diff --git a/dbms/src/Storages/KVStore/KVStore.h b/dbms/src/Storages/KVStore/KVStore.h index fd44abe5836..3aa28ec8155 100644 --- a/dbms/src/Storages/KVStore/KVStore.h +++ b/dbms/src/Storages/KVStore/KVStore.h @@ -420,6 +420,10 @@ class KVStore final : private boost::noncopyable JointThreadInfoJeallocMapPtr joint_memory_allocation_map; size_t maximum_kvstore_memory = 0; + +#ifdef DBMS_PUBLIC_GTEST + std::atomic debug_memory_limit_warning_count = 0; +#endif }; /// Encapsulation of lock guard of task mutex in KVStore diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp index 1879ef128b9..4437dd90d90 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp @@ -477,6 +477,7 @@ std::pair Region::handleWriteRaftCmd( if (default_put_key_count + lock_put_key_count > 0) { + LOG_INFO(log, "!!!!!! DDDDDD 1"); // If there are data flow in, we will check if the memory is exhaused. auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); auto current = real_rss.load(); @@ -484,17 +485,23 @@ std::pair Region::handleWriteRaftCmd( /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. /// So, we only print once for a table, until one memory reduce event will happen. - if unlikely (limit > 0 && current > 0 && static_cast(current) > limit) + LOG_INFO(log, "!!!!!! DDDDDD info limit {} current {}", limit, current); + if unlikely (limit > 0 && current > 0 && static_cast(current) >= limit) { auto table_size = getRegionTableSize(); + LOG_INFO(log, "!!!!!! DDDDDD 2 table_size {}", table_size); if (table_size > 0.5 * current) { + LOG_INFO(log, "!!!!!! DDDDDD 3"); if (!setRegionTableWarned(true)) { // If it is the first time. +#ifdef DBMS_PUBLIC_GTEST + tmt.getKVStore()->debug_memory_limit_warning_count++; +#endif LOG_INFO( log, - "Memory limit exeeded, current{} limit={} table_id={} keyspace_id={} region_id={}", + "Memory limit exeeded, current={} limit={} table_id={} keyspace_id={} region_id={}", current, limit, mapped_table_id, @@ -543,6 +550,7 @@ std::pair Region::handleWriteRaftCmd( } if (!data_list_to_remove.empty()) { + LOG_INFO(log, "!!!!!! EEEEEEEE 3"); setRegionTableWarned(false); } } diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index 687ee28493b..5ac9d400c9c 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -34,6 +34,8 @@ #include extern std::shared_ptr root_of_kvstore_mem_trackers; +extern std::atomic real_rss; + namespace DB::tests { using namespace DB::RecordKVFormat; @@ -72,12 +74,13 @@ try CATCH -TEST_F(RegionKVStoreTest, MemoryTracker) +TEST_F(RegionKVStoreTest, MemoryTracker1) try { auto & ctx = TiFlashTestEnv::getGlobalContext(); initStorages(); KVStore & kvs = getKVS(); + ctx.getTMTContext().debugSetKVStore(kvstore); auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); MockRaftStoreProxy::FailCond cond; const auto decoded_lock_size = sizeof(DecodedLockCFValue) + sizeof(DecodedLockCFValue::Inner); @@ -98,6 +101,8 @@ try return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) .toString(); }; + real_rss.store(1); + kvs.setKVStoreMemoryLimit(1); { // default RegionID region_id = 4100; @@ -116,6 +121,7 @@ try ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(kvr1->dataSize(), kvr1->getData().totalSize()); ASSERT_EQ(kvr1->getData().totalSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); } { // lock @@ -139,6 +145,7 @@ try ASSERT_EQ( kvr2->getData().totalSize() + kvr1->getData().totalSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); } { // lock with largetxn @@ -180,6 +187,7 @@ try ASSERT_EQ( kvr3->getData().totalSize() + kvr2->getData().totalSize() + kvr1->getData().totalSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); } { // insert & remove @@ -201,12 +209,14 @@ try ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); } ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { // insert RegionID region_id = 6000; root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); auto [start, end] = getStartEnd(region_id); auto str_key = pickKey(region_id, 1); auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); @@ -217,43 +227,18 @@ try ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); } - { - // reload - RegionID region_id = 7000; - root_of_kvstore_mem_trackers->reset(); - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - root_of_kvstore_mem_trackers->reset(); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - tryPersistRegion(kvs, region_id); - root_of_kvstore_mem_trackers->reset(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); - reloadKVSFromDisk(false); - ctx.getTMTContext().debugSetKVStore(kvstore); - region_table.restore(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - // Only this region is persisted. - ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); - } - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { // commit root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + RegionID region_id = 8000; auto [start, end] = getStartEnd(region_id); auto str_key = pickKey(region_id, 1); auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); auto str_lock_value = pickLock(region_id, 1); - - region_table.debugClearTableRegionSize(NullspaceID, table_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); @@ -270,8 +255,43 @@ try ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + // commit by handleWriteRaftCmd + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + + RegionID region_id = 8100; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + { + auto [view, holder] = MockRaftStoreProxy::createWriteCmdsView( + {str_key, str_key}, + {str_val_default, str_val_write}, + {WriteCmdType::Put, WriteCmdType::Put}, + {ColumnFamilyType::Default, ColumnFamilyType::Write}); + region->handleWriteRaftCmd(view, 66, 6, ctx.getTMTContext()); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + auto [view, holder] = MockRaftStoreProxy::createWriteCmdsView( + {str_key}, + {str_lock_value}, + {WriteCmdType::Put}, + {ColumnFamilyType::Lock}); + region->handleWriteRaftCmd(view, 67, 6, ctx.getTMTContext()); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); + } } - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); { // split & merge root_of_kvstore_mem_trackers->reset(); @@ -314,6 +334,7 @@ try ASSERT_EQ(region->dataSize(), region->getData().totalSize()); ASSERT_EQ(new_region->dataSize(), new_region->getData().totalSize()); ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); } { // split & merge with lock @@ -468,6 +489,62 @@ try } CATCH +TEST_F(RegionKVStoreTest, MemoryTracker2) +try +{ + auto & ctx = TiFlashTestEnv::getGlobalContext(); + initStorages(); + KVStore & kvs = getKVS(); + ctx.getTMTContext().debugSetKVStore(kvstore); + auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); + + auto & region_table = ctx.getTMTContext().getRegionTable(); + auto getStartEnd = [&](RegionID region_id) { + return std::make_pair( + RecordKVFormat::genKey(table_id, region_id), + RecordKVFormat::genKey(table_id, region_id + 99)); + }; + auto pickKey = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::genKey(table_id, region_id + number, 111); + }; + auto pickWriteDefault = [&](RegionID, UInt64) { + return proxy_instance->generateTiKVKeyValue(111, 999); + }; + auto pickLock = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) + .toString(); + }; + { + // reload + RegionID region_id = 7000; + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + root_of_kvstore_mem_trackers->reset(); + region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + tryPersistRegion(kvs, region_id); + root_of_kvstore_mem_trackers->reset(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + reloadKVSFromDisk(false); + ctx.getTMTContext().debugSetKVStore(kvstore); + region_table.restore(); + LOG_INFO(log, "!!!!! fdfdfdf {}", root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + LOG_INFO(log, "!!!!! ddddd {}", root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + // Only this region is persisted. + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + } +} +CATCH + TEST_F(RegionKVStoreTest, KVStoreFailRecovery) try { From 75898dde2af27f62a57cdd15bfc5e7ef30e1ff88 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 7 Feb 2025 20:34:25 +0800 Subject: [PATCH 13/46] remvoe helper Signed-off-by: Calvin Neo --- dbms/src/Common/BackgroundTask.cpp | 1 - dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp | 5 ----- dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp | 2 -- 3 files changed, 8 deletions(-) diff --git a/dbms/src/Common/BackgroundTask.cpp b/dbms/src/Common/BackgroundTask.cpp index 11158714471..81786c05f5b 100644 --- a/dbms/src/Common/BackgroundTask.cpp +++ b/dbms/src/Common/BackgroundTask.cpp @@ -90,7 +90,6 @@ void CollectProcInfoBackgroundTask::memCheckJob() { try { - LOG_INFO(DB::Logger::get(), "!!!! CollectProcInfoBackgroundTask"); double resident_set; Int64 cur_proc_num_threads = 1; UInt64 cur_virt_size = 0; diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp index 4437dd90d90..291c985746e 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp @@ -477,7 +477,6 @@ std::pair Region::handleWriteRaftCmd( if (default_put_key_count + lock_put_key_count > 0) { - LOG_INFO(log, "!!!!!! DDDDDD 1"); // If there are data flow in, we will check if the memory is exhaused. auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); auto current = real_rss.load(); @@ -485,14 +484,11 @@ std::pair Region::handleWriteRaftCmd( /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. /// So, we only print once for a table, until one memory reduce event will happen. - LOG_INFO(log, "!!!!!! DDDDDD info limit {} current {}", limit, current); if unlikely (limit > 0 && current > 0 && static_cast(current) >= limit) { auto table_size = getRegionTableSize(); - LOG_INFO(log, "!!!!!! DDDDDD 2 table_size {}", table_size); if (table_size > 0.5 * current) { - LOG_INFO(log, "!!!!!! DDDDDD 3"); if (!setRegionTableWarned(true)) { // If it is the first time. @@ -550,7 +546,6 @@ std::pair Region::handleWriteRaftCmd( } if (!data_list_to_remove.empty()) { - LOG_INFO(log, "!!!!!! EEEEEEEE 3"); setRegionTableWarned(false); } } diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index 5ac9d400c9c..4f38565cef9 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -534,9 +534,7 @@ try reloadKVSFromDisk(false); ctx.getTMTContext().debugSetKVStore(kvstore); region_table.restore(); - LOG_INFO(log, "!!!!! fdfdfdf {}", root_of_kvstore_mem_trackers->get()); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - LOG_INFO(log, "!!!!! ddddd {}", root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); // Only this region is persisted. From 9fb32de5ccac20444bb973cba167d1b12e0391d8 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 13:14:11 +0800 Subject: [PATCH 14/46] rename Signed-off-by: Calvin Neo --- .../dbgKVStore/dbgFuncMockRaftSnapshot.cpp | 2 +- .../Decode/SSTFilesToBlockInputStream.cpp | 6 +-- .../Storages/KVStore/Decode/RegionTable.cpp | 2 +- .../KVStore/MultiRaft/RaftCommands.cpp | 34 +----------- dbms/src/Storages/KVStore/Region.cpp | 45 ++++++++++++++-- dbms/src/Storages/KVStore/Region.h | 6 ++- .../Storages/KVStore/tests/gtest_kvstore.cpp | 54 +++++++++---------- .../KVStore/tests/gtest_new_kvstore.cpp | 30 +++++------ .../tests/gtest_region_block_reader.cpp | 2 +- .../KVStore/tests/gtest_region_persister.cpp | 42 +++++++-------- 10 files changed, 117 insertions(+), 106 deletions(-) diff --git a/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp b/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp index 2c1aec5d265..76c1fdf2172 100644 --- a/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp +++ b/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp @@ -154,7 +154,7 @@ RegionPtr GenDbgRegionSnapshotWithData(Context & context, const ASTs & args) : RecordKVFormat::encodeWriteCfValue(Region::PutFlag, prewrite_ts, value); TiKVKey commit_key = RecordKVFormat::appendTs(key, commit_ts); - region->insert(ColumnFamilyType::Write, std::move(commit_key), std::move(commit_value)); + region->insertFromSnap(ColumnFamilyType::Write, std::move(commit_key), std::move(commit_value)); } MockTiKV::instance().getRaftIndex(region_id); } diff --git a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp index 92422543c9c..21ad601883e 100644 --- a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp +++ b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp @@ -194,7 +194,7 @@ Block SSTFilesToBlockInputStream::read() BaseBuffView key = write_cf_reader->keyView(); BaseBuffView value = write_cf_reader->valueView(); auto tikv_key = TiKVKey(key.data, key.len); - region->insert(ColumnFamilyType::Write, std::move(tikv_key), TiKVValue(value.data, value.len)); + region->insertFromSnap(ColumnFamilyType::Write, std::move(tikv_key), TiKVValue(value.data, value.len)); ++process_keys.write_cf; process_keys.write_cf_bytes += (key.len + value.len); if (process_keys.write_cf % opts.expected_size == 0) @@ -277,7 +277,7 @@ void SSTFilesToBlockInputStream::loadCFDataFromSST( BaseBuffView key = reader->keyView(); BaseBuffView value = reader->valueView(); // TODO: use doInsert to avoid locking - region->insert(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); + region->insertFromSnap(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); (*p_process_keys) += 1; (*p_process_keys_bytes) += (key.len + value.len); reader->next(); @@ -337,7 +337,7 @@ void SSTFilesToBlockInputStream::loadCFDataFromSST( BaseBuffView key = reader->keyView(); BaseBuffView value = reader->valueView(); // TODO: use doInsert to avoid locking - region->insert(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len)); + region->insertFromSnap(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len)); (*p_process_keys) += 1; (*p_process_keys_bytes) += (key.len + value.len); if (*p_process_keys == process_keys_offset_end) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index 2dac157a26e..6003657bf95 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -366,7 +366,7 @@ void RegionTable::handleInternalRegionsByKeyspace( for (auto table_id : table_set->second) { if (auto it = tables.find(KeyspaceTableID{keyspace_id, table_id}); it != tables.end()) - callback(table_id, it->second.regions); + callback(table_id, it->second.internal_regions); } } } diff --git a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp index 291c985746e..63b32366d73 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RaftCommands.cpp @@ -28,8 +28,6 @@ #include #include -extern std::atomic real_rss; - namespace DB { Region::CommittedScanner Region::createCommittedScanner(bool use_lock, bool need_value) @@ -477,35 +475,7 @@ std::pair Region::handleWriteRaftCmd( if (default_put_key_count + lock_put_key_count > 0) { - // If there are data flow in, we will check if the memory is exhaused. - auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); - auto current = real_rss.load(); - /// Region management such as split/merge doesn't change the memory consumed by a table in KVStore. - /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. - /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. - /// So, we only print once for a table, until one memory reduce event will happen. - if unlikely (limit > 0 && current > 0 && static_cast(current) >= limit) - { - auto table_size = getRegionTableSize(); - if (table_size > 0.5 * current) - { - if (!setRegionTableWarned(true)) - { - // If it is the first time. -#ifdef DBMS_PUBLIC_GTEST - tmt.getKVStore()->debug_memory_limit_warning_count++; -#endif - LOG_INFO( - log, - "Memory limit exeeded, current={} limit={} table_id={} keyspace_id={} region_id={}", - current, - limit, - mapped_table_id, - keyspace_id, - id()); - } - } - } + maybeWarnMemoryLimitByTable(tmt, "put"); } // If transfer-leader happened during ingest-sst, there might be illegal data. @@ -546,7 +516,7 @@ std::pair Region::handleWriteRaftCmd( } if (!data_list_to_remove.empty()) { - setRegionTableWarned(false); + resetWarnMemoryLimitByTable(); } } diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index d68f6b3925c..ff22bb49277 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -28,6 +28,8 @@ #include #include +extern std::atomic real_rss; + namespace DB { RegionData::WriteCFIter Region::removeDataByWriteIt(const RegionData::WriteCFIter & write_it) @@ -56,12 +58,12 @@ LockInfoPtr Region::getLockInfo(const RegionLockReadQuery & query) const return data.getLockInfo(query); } -void Region::insert(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) +void Region::insertFromSnap(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) { - insert(NameToCF(cf), std::move(key), std::move(value), mode); + insertFromSnap(NameToCF(cf), std::move(key), std::move(value), mode); } -void Region::insert(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode) +void Region::insertFromSnap(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode) { std::unique_lock lock(mutex); doInsert(type, std::move(key), std::move(value), mode); @@ -407,4 +409,41 @@ size_t Region::getRegionTableSize() const return data.getRegionTableSize(); } +void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { + // If there are data flow in, we will check if the memory is exhaused. + auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); + auto current = real_rss.load(); + /// Region management such as split/merge doesn't change the memory consumed by a table in KVStore. + /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. + /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. + /// So, we only print once for a table, until one memory reduce event will happen. + if unlikely (limit > 0 && current > 0 && static_cast(current) >= limit) + { + auto table_size = getRegionTableSize(); + if (table_size > 0.5 * current) + { + if (!setRegionTableWarned(true)) + { + // If it is the first time. +#ifdef DBMS_PUBLIC_GTEST + tmt.getKVStore()->debug_memory_limit_warning_count++; +#endif + LOG_INFO( + log, + "Memory limit exeeded, current={} limit={} table_id={} keyspace_id={} region_id={} from={}", + current, + limit, + mapped_table_id, + keyspace_id, + id(), + from); + } + } + } +} + +void Region::resetWarnMemoryLimitByTable() { + setRegionTableWarned(false); +} + } // namespace DB diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index a53714a9a5e..683f6351f56 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -134,8 +134,8 @@ class Region : public std::enable_shared_from_this Region() = delete; ~Region(); - void insert(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); - void insert(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); + void insertFromSnap(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); + void insertFromSnap(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); void remove(const std::string & cf, const TiKVKey & key); // Directly drop all data in this Region object. @@ -238,6 +238,8 @@ class Region : public std::enable_shared_from_this size_t getRegionTableSize() const; bool getRegionTableWarned() const { return data.getRegionTableWarned(); } bool setRegionTableWarned(bool desired) const { return data.setRegionTableWarned(desired); } + void resetWarnMemoryLimitByTable(); + void maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from); public: // Raft Read and Write CommittedScanner createCommittedScanner(bool use_lock, bool need_value); diff --git a/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp index 5264700fb78..79fa54d157b 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp @@ -328,22 +328,22 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insert("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); // row with handle_id == 8 - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 8), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insert("default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 8, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -391,21 +391,21 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insert("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 8), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insert("default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 8, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -456,12 +456,12 @@ void RegionKVStoreOldTest::testRaftMerge(Context & ctx, KVStore & kvs, TMTContex { // Region 1 with handle_id == 6 auto region = kvs.getRegion(target_region_id); - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 6), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insert("default", RecordKVFormat::genKey(table_id, 6, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 6, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 6, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -470,12 +470,12 @@ void RegionKVStoreOldTest::testRaftMerge(Context & ctx, KVStore & kvs, TMTContex { // Region 7 with handle_id == 2 auto region = kvs.getRegion(source_region_id); - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 2), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insert("default", RecordKVFormat::genKey(table_id, 2, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 2, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 2, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -640,12 +640,12 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { // Test read committed and lock with CommittedScanner. - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20, nullptr, 5)); - region->insert("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); - region->insert( + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -694,7 +694,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) region->clearAllData(); } { - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::LockType::Lock, "PK", 3, 20, nullptr, 5)); @@ -706,7 +706,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) region->clearAllData(); } { - region->insert( + region->insertFromSnap( "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::LockType::Pessimistic, "PK", 3, 20, nullptr, 5)); @@ -719,7 +719,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { // Test duplicate and tryCompactionFilter - region->insert( + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -729,7 +729,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) try { // insert duplicate records - region->insert( + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -748,7 +748,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { // Test read and delete committed Del record. - region->insert( + region->insertFromSnap( "write", RecordKVFormat::genKey(table_id, 4, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::DelFlag, 5)); @@ -765,7 +765,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { ASSERT_EQ(0, region->dataSize()); - region->insert("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); ASSERT_LT(0, region->dataSize()); region->remove("default", RecordKVFormat::genKey(table_id, 3, 5)); ASSERT_EQ(0, region->dataSize()); diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index a2f4ee1964c..cf775458223 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -200,7 +200,7 @@ try auto str_lock_value = pickLock(region_id, 1); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); auto delta = str_key.dataSize() + str_val_default.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), delta); ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize + delta); @@ -223,7 +223,7 @@ try auto str_lock_value = pickLock(region_id, 1); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); @@ -241,9 +241,9 @@ try auto str_lock_value = pickLock(region_id, 1); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - region->insert("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); + region->insertFromSnap("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); ASSERT_EQ( str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), region_table.getTableRegionSize(NullspaceID, table_id)); @@ -304,11 +304,11 @@ try region_table.debugClearTableRegionSize(NullspaceID, table_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); auto str_key2 = pickKey(region_id, 80); auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); auto str_lock_value2 = pickLock(region_id, 80); - region->insert("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); auto expected = str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); @@ -348,7 +348,7 @@ try auto str_lock_value = pickLock(region_id, 22); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insert("lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); auto expected = str_key.dataSize() + str_lock_value.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); auto str_key2 = pickKey(region_id, 80); @@ -356,7 +356,7 @@ try auto str_lock_value2 = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13180, 111, &short_value) .toString(); - region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); expected += str_key2.dataSize() + str_lock_value2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); @@ -382,10 +382,10 @@ try ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); // replace a lock - region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); auto str_lock_value2_2 = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13022, 111).toString(); - region->insert("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); expected -= short_value.size(); expected -= 2; // Short value prefix and length ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); @@ -410,7 +410,7 @@ try auto [str_val_write3, str_val_default3] = pickWriteDefault(region_id, 80); auto str_lock_value3 = pickLock(region_id, 80); - region->insert("default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key3.dataSize() + str_val_default3.size()); ASSERT_EQ(region->dataSize(), str_key3.dataSize() + str_val_default3.size()); ASSERT_EQ(region->getData().totalSize(), region->dataSize()); @@ -444,14 +444,14 @@ try auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 70); auto str_lock_value = pickLock(region_id, 70); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); auto str_key2 = pickKey(region_id, 80); auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); auto str_lock_value2 = pickLock(region_id, 80); - region2->insert("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); - region2->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region2->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + region2->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); region->assignRegion(std::move(*region2)); ASSERT_EQ( @@ -526,7 +526,7 @@ try proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); root_of_kvstore_mem_trackers->reset(); - region->insert("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); tryPersistRegion(kvs, region_id); root_of_kvstore_mem_trackers->reset(); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp index 8902e6305e0..a90ff39950b 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp @@ -665,7 +665,7 @@ try }; for (const auto & [k, v] : kvs) { - region->insert(ColumnFamilyType::Write, TiKVKey(bytesFromHexString(k)), TiKVValue(bytesFromHexString(v))); + region->insertFromSnap(ColumnFamilyType::Write, TiKVKey(bytesFromHexString(k)), TiKVValue(bytesFromHexString(v))); } auto data_list_read = ReadRegionCommitCache(region, true); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index beef2c03cb9..c8644f87e9b 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -205,9 +205,9 @@ try TableID table_id = 100; auto region = makeTmpRegion(); TiKVKey key = RecordKVFormat::genKey(table_id, 323, 9983); - region->insert("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insert("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertFromSnap("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); region->updateRaftLogEagerIndex(1024); @@ -237,9 +237,9 @@ try TableID table_id = 100; auto region = makeTmpRegion(); TiKVKey key = RecordKVFormat::genKey(table_id, 323, 9983); - region->insert("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insert("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertFromSnap("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); region->updateRaftLogEagerIndex(1024); @@ -284,9 +284,9 @@ try } TiKVKey key = RecordKVFormat::genKey(table_id, 323, 9983); - region->insert("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insert("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertFromSnap("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); const auto path = dir_path + "/region_state.test"; WriteBufferFromFile write_buf(path, DBMS_DEFAULT_BUFFER_SIZE, O_WRONLY | O_CREAT); @@ -567,9 +567,9 @@ try auto region = makeRegion(createRegionMeta(region_100, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_100, diff++); - region->insert(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insert(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert( + region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -588,9 +588,9 @@ try auto region = makeRegion(createRegionMeta(region_101, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_101, diff++); - region->insert(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insert(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert( + region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -633,9 +633,9 @@ try auto region = makeRegion(createRegionMeta(i, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, i, diff++); - region->insert(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insert(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert( + region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -726,12 +726,12 @@ try break; } TiKVKey key = RecordKVFormat::genKey(table_id, handle_id, tso++); - region->insert(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue(large_value.data())); - region->insert( + region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue(large_value.data())); + region->insertFromSnap( ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insert( + region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); From dea150bf37fcfdb5854cec64b6b0b266c2c5efab Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 13:43:31 +0800 Subject: [PATCH 15/46] try record snapshot Signed-off-by: Calvin Neo --- .../Debug/MockKVStore/MockRaftStoreProxy.cpp | 6 ++++-- dbms/src/Debug/dbgTools.cpp | 2 ++ .../Decode/SSTFilesToBlockInputStream.cpp | 3 ++- .../Storages/KVStore/Decode/RegionTable.cpp | 16 ++++++++++++++- .../src/Storages/KVStore/Decode/RegionTable.h | 2 ++ dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp | 3 ++- .../KVStore/MultiRaft/PrehandleSnapshot.cpp | 1 + .../Storages/KVStore/MultiRaft/RegionData.cpp | 5 +++++ .../Storages/KVStore/MultiRaft/RegionData.h | 2 ++ dbms/src/Storages/KVStore/Region.cpp | 14 +++---------- dbms/src/Storages/KVStore/Region.h | 5 +++-- .../tests/gtest_region_block_reader.cpp | 5 ++++- .../KVStore/tests/gtest_region_persister.cpp | 20 +++++++++++++++---- 13 files changed, 61 insertions(+), 23 deletions(-) diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index 1bd0e20aea1..0227c55f9b4 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -640,10 +640,12 @@ std::tuple MockRaftStoreProxy::snapshot( term = region->getLatestCommitTerm(); } - auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term); // The new entry is committed on Proxy's side. region->updateCommitIndex(index); - new_kv_region->setApplied(index, term); + // Would set `appleid_index` in genRegionPtr. + auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term); + auto & region_table = tmt.getRegionTable(); + region_table.addPrehandlingRegion(*new_kv_region); std::vector ssts; for (auto & cf : cfs) diff --git a/dbms/src/Debug/dbgTools.cpp b/dbms/src/Debug/dbgTools.cpp index 8edf28d732d..2c8a9349938 100644 --- a/dbms/src/Debug/dbgTools.cpp +++ b/dbms/src/Debug/dbgTools.cpp @@ -785,6 +785,8 @@ void handleApplySnapshot( TMTContext & tmt) { auto new_region = kvstore.genRegionPtr(std::move(region), peer_id, index, term); + auto & region_table = tmt.getRegionTable(); + region_table.addPrehandlingRegion(*new_region); auto prehandle_result = kvstore.preHandleSnapshotToFiles(new_region, snaps, index, term, deadline_index, tmt); kvstore.applyPreHandledSnapshot( RegionPtrWithSnapshotFiles{new_region, std::move(prehandle_result.ingest_ids)}, diff --git a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp index 21ad601883e..e13518063f7 100644 --- a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp +++ b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp @@ -277,7 +277,8 @@ void SSTFilesToBlockInputStream::loadCFDataFromSST( BaseBuffView key = reader->keyView(); BaseBuffView value = reader->valueView(); // TODO: use doInsert to avoid locking - region->insertFromSnap(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); + region + ->insertFromSnap(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); (*p_process_keys) += 1; (*p_process_keys_bytes) += (key.len + value.len); reader->next(); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index 6003657bf95..7a0316b82ac 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -161,6 +161,15 @@ void RegionTable::addRegion(const Region & region) getOrInsertRegion(region); } +void RegionTable::addPrehandlingRegion(const Region & region) +{ + std::lock_guard lock(mutex); + auto keyspace_id = region.getKeyspaceID(); + auto table_id = region.getMappedTableID(); + auto & table = getOrCreateTable(keyspace_id, table_id); + region.setRegionTableCtx(table.ctx); +} + size_t RegionTable::getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const { std::scoped_lock lock(mutex); @@ -432,7 +441,12 @@ void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & auto table_id = region_range_keys->getMappedTableID(); auto & table = getOrCreateTable(keyspace_id, table_id); old_region->resetRegionTableCtx(); - new_region->setRegionTableCtx(table.ctx); + if unlikely (!new_region->getRegionTableCtx()) + { + // For most of the cases, the region is prehandled, so the ctx is set at that moment. + LOG_INFO(DB::Logger::get(), "!!!! fdsfdfsdf"); + new_region->setRegionTableCtx(table.ctx); + } } } diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index bd9a0a51541..2429f3886e3 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -95,6 +95,8 @@ class RegionTable : private boost::noncopyable // When a region is added to region table, happens when split ans restore. void addRegion(const Region & region); + void addPrehandlingRegion(const Region & region); + // When a reigon is removed out of TiFlash. void removeRegion(RegionID region_id, bool remove_data, const RegionTaskLock &); diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp index badc9143342..71653b414de 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp @@ -667,10 +667,11 @@ RawCppPtr PreHandleSnapshot( auto & tmt = *server->tmt; auto & kvstore = tmt.getKVStore(); auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term); + auto & region_table = tmt.getRegionTable(); + region_table.addPrehandlingRegion(*new_region); #ifndef NDEBUG { - auto & kvstore = server->tmt->getKVStore(); auto state = kvstore->getProxyHelper()->getRegionLocalState(new_region->id()); assert(state.state() == raft_serverpb::PeerState::Applying); } diff --git a/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp b/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp index db6e0956560..5933c941fa9 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp @@ -457,6 +457,7 @@ static void runInParallel( const size_t split_id = part_limit.split_id; auto part_new_region = std::make_shared(new_region->getMeta().clone(), proxy_helper); + part_new_region->setRegionTableCtx(new_region->getRegionTableCtx()); auto part_sst_stream = std::make_shared( part_new_region, prehandle_ctx.snapshot_index, diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index ae1599a75f2..7dcd6c4eaa1 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -420,6 +420,11 @@ void RegionData::setRegionTableCtx(RegionTableCtx ctx) const } } +RegionTableCtx RegionData::getRegionTableCtx() const +{ + return region_table_ctx; +} + RegionTableCtx RegionData::resetRegionTableCtx() const { if (region_table_ctx) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h index e3215e2b1da..4221d8462f5 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h @@ -84,7 +84,9 @@ class RegionData String summary() const; size_t tryCompactionFilter(Timestamp safe_point); + void setRegionTableCtx(RegionTableCtx) const; + RegionTableCtx getRegionTableCtx() const; RegionTableCtx resetRegionTableCtx() const; size_t getRegionTableSize() const; bool getRegionTableWarned() const; diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index ff22bb49277..2f8969492b4 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -399,17 +399,8 @@ void Region::setRegionTableCtx(RegionTableCtx size) const data.setRegionTableCtx(size); } -RegionTableCtx Region::resetRegionTableCtx() const +void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { - return data.resetRegionTableCtx(); -} - -size_t Region::getRegionTableSize() const -{ - return data.getRegionTableSize(); -} - -void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { // If there are data flow in, we will check if the memory is exhaused. auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); auto current = real_rss.load(); @@ -442,7 +433,8 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { } } -void Region::resetWarnMemoryLimitByTable() { +void Region::resetWarnMemoryLimitByTable() +{ setRegionTableWarned(false); } diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index 683f6351f56..63c45ec9968 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -234,8 +234,9 @@ class Region : public std::enable_shared_from_this // Bind a region to a RegionTable. It could not be bound to another table any more. // All memory changes to this region would relect to the binded table. void setRegionTableCtx(RegionTableCtx size) const; - RegionTableCtx resetRegionTableCtx() const; - size_t getRegionTableSize() const; + RegionTableCtx getRegionTableCtx() const { return data.getRegionTableCtx(); } + RegionTableCtx resetRegionTableCtx() const { return data.resetRegionTableCtx(); } + size_t getRegionTableSize() const { return data.getRegionTableSize(); } bool getRegionTableWarned() const { return data.getRegionTableWarned(); } bool setRegionTableWarned(bool desired) const { return data.setRegionTableWarned(desired); } void resetWarnMemoryLimitByTable(); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp index a90ff39950b..e7cd8096b06 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp @@ -665,7 +665,10 @@ try }; for (const auto & [k, v] : kvs) { - region->insertFromSnap(ColumnFamilyType::Write, TiKVKey(bytesFromHexString(k)), TiKVValue(bytesFromHexString(v))); + region->insertFromSnap( + ColumnFamilyType::Write, + TiKVKey(bytesFromHexString(k)), + TiKVValue(bytesFromHexString(v))); } auto data_list_read = ReadRegionCommitCache(region, true); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index c8644f87e9b..37b18f7647e 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -568,7 +568,10 @@ try auto region = makeRegion(createRegionMeta(region_100, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_100, diff++); region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap( + ColumnFamilyType::Write, + TiKVKey::copyFrom(key), + RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), @@ -589,7 +592,10 @@ try auto region = makeRegion(createRegionMeta(region_101, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_101, diff++); region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap( + ColumnFamilyType::Write, + TiKVKey::copyFrom(key), + RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), @@ -634,7 +640,10 @@ try auto region = makeRegion(createRegionMeta(i, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, i, diff++); region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap(ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap( + ColumnFamilyType::Write, + TiKVKey::copyFrom(key), + RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( ColumnFamilyType::Lock, TiKVKey::copyFrom(key), @@ -726,7 +735,10 @@ try break; } TiKVKey key = RecordKVFormat::genKey(table_id, handle_id, tso++); - region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue(large_value.data())); + region->insertFromSnap( + ColumnFamilyType::Default, + TiKVKey::copyFrom(key), + TiKVValue(large_value.data())); region->insertFromSnap( ColumnFamilyType::Write, TiKVKey::copyFrom(key), From 047bd3768de5fb1b52e3930e6bf71f65c95228bb Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 14:50:22 +0800 Subject: [PATCH 16/46] add some tests Signed-off-by: Calvin Neo --- .../Debug/MockKVStore/MockRaftStoreProxy.cpp | 5 +- .../Debug/MockKVStore/MockRaftStoreProxy.h | 4 +- dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp | 1 + .../tests/gtest_kvstore_fast_add_peer.cpp | 6 +- .../Storages/KVStore/tests/gtest_memory.cpp | 614 ++++++++++++++++++ .../KVStore/tests/gtest_new_kvstore.cpp | 561 +--------------- 6 files changed, 627 insertions(+), 564 deletions(-) create mode 100644 dbms/src/Storages/KVStore/tests/gtest_memory.cpp diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index 0227c55f9b4..d3b076c585b 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -601,7 +601,7 @@ std::tuple MockRaftStoreProxy::snapshot( uint64_t index, uint64_t term, std::optional deadline_index, - bool cancel_after_prehandle) + std::optional> cancel_after_prehandle) { auto old_kv_region = kvs.getRegion(region_id); RUNTIME_CHECK(old_kv_region != nullptr); @@ -628,7 +628,7 @@ std::tuple MockRaftStoreProxy::snapshot( uint64_t index, uint64_t term, std::optional deadline_index, - bool cancel_after_prehandle) + std::optional> cancel_after_prehandle) { auto region = getRegion(region_id); RUNTIME_CHECK(region != nullptr); @@ -665,6 +665,7 @@ std::tuple MockRaftStoreProxy::snapshot( auto rg = RegionPtrWithSnapshotFiles{new_kv_region, std::vector(prehandle_result.ingest_ids)}; if (cancel_after_prehandle) { + cancel_after_prehandle.value()(); kvs.releasePreHandledSnapshot(rg, tmt); return std::make_tuple(kvs.getRegion(region_id), prehandle_result); } diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h index 9bfcff01424..bcabd825a75 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.h @@ -242,7 +242,7 @@ struct MockRaftStoreProxy : MutexLockWrap uint64_t index, uint64_t term, std::optional deadline_index, - bool cancel_after_prehandle); + std::optional> cancel_after_prehandle); std::tuple snapshot( KVStore & kvs, TMTContext & tmt, @@ -251,7 +251,7 @@ struct MockRaftStoreProxy : MutexLockWrap uint64_t index, uint64_t term, std::optional deadline_index, - bool cancel_after_prehandle = false); + std::optional> cancel_after_prehandle = std::nullopt); void doApply( KVStore & kvs, diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp index 71653b414de..0a126e5aa69 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp @@ -666,6 +666,7 @@ RawCppPtr PreHandleSnapshot( CHECK_PARSE_PB_BUFF(region, region_buff.data, region_buff.len); auto & tmt = *server->tmt; auto & kvstore = tmt.getKVStore(); + // TODO move this inside `preHandleSnapshotToFiles`, or change `genRegionPtr`. auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term); auto & region_table = tmt.getRegionTable(); region_table.addPrehandlingRegion(*new_region); diff --git a/dbms/src/Storages/KVStore/tests/gtest_kvstore_fast_add_peer.cpp b/dbms/src/Storages/KVStore/tests/gtest_kvstore_fast_add_peer.cpp index 276770a85a3..a2aab5e14df 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_kvstore_fast_add_peer.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_kvstore_fast_add_peer.cpp @@ -853,7 +853,7 @@ try 11, 11, std::nullopt, - false); + std::nullopt); eventuallyPredicate([&]() { return !CheckpointIngestInfo::restore(global_context.getTMTContext(), proxy_helper.get(), region_id, 2333); }); @@ -975,7 +975,7 @@ try 10, 10, std::nullopt, - false); + std::nullopt); std::mutex exe_mut; std::unique_lock exe_lock(exe_mut); @@ -1059,7 +1059,7 @@ try 0, 0, std::nullopt, - false); + std::nullopt); } ASSERT_EQ(fap_context->tasks_trace->queryState(region_id), FAPAsyncTasks::TaskState::NotScheduled); diff --git a/dbms/src/Storages/KVStore/tests/gtest_memory.cpp b/dbms/src/Storages/KVStore/tests/gtest_memory.cpp new file mode 100644 index 00000000000..2ee781a2911 --- /dev/null +++ b/dbms/src/Storages/KVStore/tests/gtest_memory.cpp @@ -0,0 +1,614 @@ +// Copyright 2025 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include +#include // Included for `USE_JEMALLOC` + +extern std::shared_ptr root_of_kvstore_mem_trackers; +extern std::atomic real_rss; + + +namespace DB::tests +{ +using namespace DB::RecordKVFormat; + + +TEST_F(RegionKVStoreTest, MemoryTracker1) +try +{ + auto & ctx = TiFlashTestEnv::getGlobalContext(); + initStorages(); + KVStore & kvs = getKVS(); + ctx.getTMTContext().debugSetKVStore(kvstore); + auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); + MockRaftStoreProxy::FailCond cond; + const auto decoded_lock_size = sizeof(DecodedLockCFValue) + sizeof(DecodedLockCFValue::Inner); + + auto & region_table = ctx.getTMTContext().getRegionTable(); + auto getStartEnd = [&](RegionID region_id) { + return std::make_pair( + RecordKVFormat::genKey(table_id, region_id), + RecordKVFormat::genKey(table_id, region_id + 99)); + }; + auto pickKey = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::genKey(table_id, region_id + number, 111); + }; + auto pickWriteDefault = [&](RegionID, UInt64) { + return proxy_instance->generateTiKVKeyValue(111, 999); + }; + auto pickLock = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) + .toString(); + }; + real_rss.store(1); + kvs.setKVStoreMemoryLimit(1); + { + // default + RegionID region_id = 4100; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(region_id); + auto [index, term] + = proxy_instance + ->rawWrite(region_id, {str_key}, {str_val_default}, {WriteCmdType::Put}, {ColumnFamilyType::Default}); + UNUSED(term); + proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(kvr1->dataSize(), kvr1->getData().totalSize()); + ASSERT_EQ(kvr1->getData().totalSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + // lock + root_of_kvstore_mem_trackers->reset(); + RegionID region_id = 4200; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(4100); + auto kvr2 = kvs.getRegion(region_id); + auto [index, term] + = proxy_instance + ->rawWrite(region_id, {str_key}, {str_lock_value}, {WriteCmdType::Put}, {ColumnFamilyType::Lock}); + UNUSED(term); + proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); + ASSERT_EQ(kvr2->dataSize(), str_key.dataSize() + str_lock_value.size()); + ASSERT_EQ(kvr2->dataSize() + decoded_lock_size, kvr2->getData().totalSize()); + ASSERT_EQ( + kvr2->getData().totalSize() + kvr1->getData().totalSize(), + region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + // lock with largetxn + root_of_kvstore_mem_trackers->reset(); + RegionID region_id = 4300; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(4100); + auto kvr2 = kvs.getRegion(4200); + auto kvr3 = kvs.getRegion(region_id); + ASSERT_NE(kvr3, nullptr); + std::string shor_value = "value"; + auto lock_for_update_ts = 7777, txn_size = 1; + const std::vector & async_commit = {"s1", "s2"}; + const std::vector & rollback = {3, 4}; + auto lock_value2 = DB::RegionBench::encodeFullLockCfValue( + Region::DelFlag, + "primary key", + 421321, + std::numeric_limits::max(), + &shor_value, + 66666, + lock_for_update_ts, + txn_size, + async_commit, + rollback, + 1111); + auto [index, term] + = proxy_instance + ->rawWrite(region_id, {str_key}, {str_lock_value}, {WriteCmdType::Put}, {ColumnFamilyType::Lock}); + UNUSED(term); + proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); + ASSERT_EQ(kvr3->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(kvr3->dataSize() + decoded_lock_size, kvr3->getData().totalSize()); + ASSERT_EQ( + kvr3->getData().totalSize() + kvr2->getData().totalSize() + kvr1->getData().totalSize(), + region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + // insert & remove + root_of_kvstore_mem_trackers->reset(); + RegionID region_id = 5000; + auto originTableSize = region_table.getTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + auto delta = str_key.dataSize() + str_val_default.size(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), delta); + ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize + delta); + region->remove("default", TiKVKey::copyFrom(str_key)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + { + // insert + RegionID region_id = 6000; + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + // commit + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + + RegionID region_id = 8000; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + region->insertFromSnap("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); + ASSERT_EQ( + str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), + region_table.getTableRegionSize(NullspaceID, table_id)); + std::optional data_list_read = ReadRegionCommitCache(region, true); + ASSERT_TRUE(data_list_read); + ASSERT_EQ(1, data_list_read->size()); + RemoveRegionCommitCache(region, *data_list_read); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + // commit by handleWriteRaftCmd + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + + RegionID region_id = 8100; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + { + auto [view, holder] = MockRaftStoreProxy::createWriteCmdsView( + {str_key, str_key}, + {str_val_default, str_val_write}, + {WriteCmdType::Put, WriteCmdType::Put}, + {ColumnFamilyType::Default, ColumnFamilyType::Write}); + region->handleWriteRaftCmd(view, 66, 6, ctx.getTMTContext()); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); + } + { + auto [view, holder] = MockRaftStoreProxy::createWriteCmdsView( + {str_key}, + {str_lock_value}, + {WriteCmdType::Put}, + {ColumnFamilyType::Lock}); + region->handleWriteRaftCmd(view, 67, 6, ctx.getTMTContext()); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); + } + } + { + // split & merge + root_of_kvstore_mem_trackers->reset(); + RegionID region_id = 12000; + RegionID region_id2 = 12002; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 22); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); + auto str_lock_value = pickLock(region_id, 22); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + auto str_key2 = pickKey(region_id, 80); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); + auto str_lock_value2 = pickLock(region_id, 80); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); + auto expected = str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + ASSERT_EQ(region->dataSize(), expected); + auto new_region = splitRegion( + region, + RegionMeta( + createPeer(region_id + 1, true), + createRegionInfo( + region_id2, + RecordKVFormat::genKey(table_id, 12050), + RecordKVFormat::genKey(table_id, 12099)), + initialApplyState())); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_val_default.size()); + ASSERT_EQ(new_region->dataSize(), str_key2.dataSize() + str_val_default2.size()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(new_region->dataSize(), new_region->getData().totalSize()); + region->mergeDataFrom(*new_region); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + ASSERT_EQ(region->dataSize(), expected); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + ASSERT_EQ(new_region->dataSize(), new_region->getData().totalSize()); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); + } + { + // split & merge with lock + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + RegionID region_id = 13100; + RegionID region_id2 = 13102; + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 22); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); + auto str_lock_value = pickLock(region_id, 22); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); + auto expected = str_key.dataSize() + str_lock_value.size(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + auto str_key2 = pickKey(region_id, 80); + std::string short_value(97, 'a'); + auto str_lock_value2 + = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13180, 111, &short_value) + .toString(); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); + expected += str_key2.dataSize() + str_lock_value2.size(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + auto new_region = splitRegion( + region, + RegionMeta( + createPeer(region_id + 1, true), + createRegionInfo( + region_id2, + RecordKVFormat::genKey(table_id, 13150), + RecordKVFormat::genKey(table_id, 13199)), + initialApplyState())); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_lock_value.size()); + ASSERT_EQ(region->getData().totalSize(), region->dataSize() + decoded_lock_size); + ASSERT_EQ(new_region->dataSize(), str_key2.dataSize() + str_lock_value2.size()); + ASSERT_EQ(new_region->getData().totalSize(), new_region->dataSize() + decoded_lock_size); + region->mergeDataFrom(*new_region); + ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + ASSERT_EQ(region->dataSize(), expected); + ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); + + // replace a lock + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + auto str_lock_value2_2 + = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13022, 111).toString(); + region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); + expected -= short_value.size(); + expected -= 2; // Short value prefix and length + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); + ASSERT_EQ(region->dataSize(), expected); + ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); + } + { + // insert & snapshot + UInt64 region_id = 14100; + region_table.debugClearTableRegionSize(NullspaceID, table_id); + root_of_kvstore_mem_trackers->reset(); + auto [start, end] = getStartEnd(region_id); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + ASSERT_NE(region, nullptr); + + auto str_key2 = pickKey(region_id, 20); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 20); + auto str_lock_value2 = pickLock(region_id, 20); + + auto str_key3 = pickKey(region_id, 80); + auto [str_val_write3, str_val_default3] = pickWriteDefault(region_id, 80); + auto str_lock_value3 = pickLock(region_id, 80); + + region->insertFromSnap("default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key3.dataSize() + str_val_default3.size()); + ASSERT_EQ(region->dataSize(), str_key3.dataSize() + str_val_default3.size()); + ASSERT_EQ(region->getData().totalSize(), region->dataSize()); + + MockSSTReader::getMockSSTData().clear(); + MockSSTGenerator default_cf{region_id, table_id, ColumnFamilyType::Default}; + default_cf.insert(14180, str_val_default2); + default_cf.finish_file(); + default_cf.freeze(); + kvs.mutProxyHelperUnsafe()->sst_reader_interfaces = make_mock_sst_reader_interface(); + proxy_instance->snapshot(kvs, ctx.getTMTContext(), region_id, {default_cf}, 0, 0, std::nullopt); + ASSERT_EQ(region->dataSize(), str_key2.dataSize() + str_val_default2.size()); + ASSERT_EQ(region->getData().totalSize(), region->dataSize()); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key2.dataSize() + str_val_default2.size()); + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + } + { + // prehandle snapshot and drop + UInt64 region_id = 14200; + region_table.debugClearTableRegionSize(NullspaceID, table_id); + root_of_kvstore_mem_trackers->reset(); + auto [start, end] = getStartEnd(region_id); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + ASSERT_NE(region, nullptr); + + auto str_key2 = pickKey(region_id, 20); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 20); + auto str_lock_value2 = pickLock(region_id, 20); + + MockSSTReader::getMockSSTData().clear(); + MockSSTGenerator default_cf{region_id, table_id, ColumnFamilyType::Default}; + default_cf.insert(14280, str_val_default2); + default_cf.finish_file(); + default_cf.freeze(); + kvs.mutProxyHelperUnsafe()->sst_reader_interfaces = make_mock_sst_reader_interface(); + proxy_instance->snapshot(kvs, ctx.getTMTContext(), region_id, {default_cf}, 0, 0, std::nullopt, [&](){ + ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), str_key2.dataSize() + str_val_default2.size()); + }); + ASSERT_EQ(region->dataSize(), 0); + ASSERT_EQ(region->getData().totalSize(), 0); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), 0); + } + { + // assign + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + RegionID region_id = 15100; + RegionID region_id2 = 15200; + auto [start1, end1] = getStartEnd(1100); + auto [start2, end2] = getStartEnd(1200); + proxy_instance + ->debugAddRegions(kvs, ctx.getTMTContext(), {region_id, region_id2}, {{start1, end1}, {start2, end2}}); + RegionPtr region = kvs.getRegion(region_id); + RegionPtr region2 = kvs.getRegion(region_id2); + + auto str_key = pickKey(region_id, 70); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 70); + auto str_lock_value = pickLock(region_id, 70); + + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + + auto str_key2 = pickKey(region_id, 80); + auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); + auto str_lock_value2 = pickLock(region_id, 80); + region2->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + region2->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + + region->assignRegion(std::move(*region2)); + ASSERT_EQ( + root_of_kvstore_mem_trackers->get(), + str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ( + region->dataSize(), + str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); + ASSERT_EQ(region->getData().totalSize(), region->dataSize()); + // `region2` is not allowed to access after move, however, we assert here in order to make sure the logic. + ASSERT_EQ(region2->dataSize(), 0); + ASSERT_EQ(region2->getData().totalSize(), region2->dataSize()); + } + { + // remove region + RegionID region_id = 16000; + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + auto kvr1 = kvs.getRegion(region_id); + auto [index, term] + = proxy_instance + ->rawWrite(region_id, {str_key}, {str_val_default}, {WriteCmdType::Put}, {ColumnFamilyType::Default}); + UNUSED(term); + proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); + kvs.handleDestroy(region_id, ctx.getTMTContext()); + ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); + } +} +CATCH + +TEST_F(RegionKVStoreTest, MemoryTracker2) +try +{ + auto & ctx = TiFlashTestEnv::getGlobalContext(); + initStorages(); + KVStore & kvs = getKVS(); + ctx.getTMTContext().debugSetKVStore(kvstore); + auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); + + auto & region_table = ctx.getTMTContext().getRegionTable(); + auto getStartEnd = [&](RegionID region_id) { + return std::make_pair( + RecordKVFormat::genKey(table_id, region_id), + RecordKVFormat::genKey(table_id, region_id + 99)); + }; + auto pickKey = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::genKey(table_id, region_id + number, 111); + }; + auto pickWriteDefault = [&](RegionID, UInt64) { + return proxy_instance->generateTiKVKeyValue(111, 999); + }; + auto pickLock = [&](RegionID region_id, UInt64 number) { + return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) + .toString(); + }; + { + // reload + RegionID region_id = 7000; + root_of_kvstore_mem_trackers->reset(); + region_table.debugClearTableRegionSize(NullspaceID, table_id); + auto [start, end] = getStartEnd(region_id); + auto str_key = pickKey(region_id, 1); + auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); + auto str_lock_value = pickLock(region_id, 1); + proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); + RegionPtr region = kvs.getRegion(region_id); + root_of_kvstore_mem_trackers->reset(); + region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + tryPersistRegion(kvs, region_id); + root_of_kvstore_mem_trackers->reset(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); + reloadKVSFromDisk(false); + ctx.getTMTContext().debugSetKVStore(kvstore); + region_table.restore(); + ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); + ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); + ASSERT_EQ(region->dataSize(), region->getData().totalSize()); + // Only this region is persisted. + ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + } +} +CATCH + + +#if USE_JEMALLOC // following tests depends on jemalloc +TEST(FFIJemallocTest, JemallocThread) +try +{ + std::thread t2([&]() { + char * a = new char[888888]; + std::thread t1([&]() { + auto [allocated, deallocated] = JointThreadInfoJeallocMap::getPtrs(); + ASSERT_TRUE(allocated != nullptr); + ASSERT_EQ(*allocated, 0); + ASSERT_TRUE(deallocated != nullptr); + ASSERT_EQ(*deallocated, 0); + }); + t1.join(); + auto [allocated, deallocated] = JointThreadInfoJeallocMap::getPtrs(); + ASSERT_TRUE(allocated != nullptr); + ASSERT_GE(*allocated, 888888); + ASSERT_TRUE(deallocated != nullptr); + delete[] a; + }); + t2.join(); + + std::thread t3([&]() { + // Will not cover mmap memory. + auto [allocated, deallocated] = JointThreadInfoJeallocMap::getPtrs(); + char * a = new char[120]; + void * buf = mmap(nullptr, 6000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_LT(*allocated, 6000); + munmap(buf, 0); + delete[] a; + }); + t3.join(); +} +CATCH + +TEST_F(RegionKVStoreTest, StorageBgPool) +try +{ + using namespace std::chrono_literals; + auto & ctx = TiFlashTestEnv::getGlobalContext(); + auto & pool = ctx.getBackgroundPool(); + const auto size = TiFlashTestEnv::DEFAULT_BG_POOL_SIZE; + std::atomic_bool b = false; + + JointThreadInfoJeallocMap & jm = *ctx.getJointThreadInfoJeallocMap(); + + size_t original_size + = TiFlashMetrics::instance().getStorageThreadMemory(TiFlashMetrics::MemoryAllocType::Alloc, "bg"); + + auto t = pool.addTask( + [&]() { + auto * x = new int[1000]; + LOG_INFO(Logger::get(), "allocated"); + while (!b.load()) + { + std::this_thread::sleep_for(1500ms); + } + delete[] x; + LOG_INFO(Logger::get(), "released"); + return false; + }, + false, + 5 * 60 * 1000); + std::this_thread::sleep_for(500ms); + + jm.recordThreadAllocInfo(); + + LOG_INFO(DB::Logger::get(), "bg pool size={}", size); + UInt64 r = TiFlashMetrics::instance().getStorageThreadMemory(TiFlashMetrics::MemoryAllocType::Alloc, "bg"); + ASSERT_GE(r, original_size + sizeof(int) * 1000); + jm.accessStorageMap([size](const JointThreadInfoJeallocMap::AllocMap & m) { + // There are some other bg thread pools + ASSERT_GE(m.size(), size) << m.size(); + }); + jm.accessProxyMap([](const JointThreadInfoJeallocMap::AllocMap & m) { ASSERT_EQ(m.size(), 0); }); + + b.store(true); + + ctx.getBackgroundPool().removeTask(t); +} +CATCH +#endif +} // namespace DB::tests \ No newline at end of file diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index cf775458223..977660e087e 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -33,8 +33,6 @@ #include -extern std::shared_ptr root_of_kvstore_mem_trackers; -extern std::atomic real_rss; namespace DB::tests { @@ -74,474 +72,6 @@ try CATCH -TEST_F(RegionKVStoreTest, MemoryTracker1) -try -{ - auto & ctx = TiFlashTestEnv::getGlobalContext(); - initStorages(); - KVStore & kvs = getKVS(); - ctx.getTMTContext().debugSetKVStore(kvstore); - auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); - MockRaftStoreProxy::FailCond cond; - const auto decoded_lock_size = sizeof(DecodedLockCFValue) + sizeof(DecodedLockCFValue::Inner); - - auto & region_table = ctx.getTMTContext().getRegionTable(); - auto getStartEnd = [&](RegionID region_id) { - return std::make_pair( - RecordKVFormat::genKey(table_id, region_id), - RecordKVFormat::genKey(table_id, region_id + 99)); - }; - auto pickKey = [&](RegionID region_id, UInt64 number) { - return RecordKVFormat::genKey(table_id, region_id + number, 111); - }; - auto pickWriteDefault = [&](RegionID, UInt64) { - return proxy_instance->generateTiKVKeyValue(111, 999); - }; - auto pickLock = [&](RegionID region_id, UInt64 number) { - return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) - .toString(); - }; - real_rss.store(1); - kvs.setKVStoreMemoryLimit(1); - { - // default - RegionID region_id = 4100; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - auto kvr1 = kvs.getRegion(region_id); - auto [index, term] - = proxy_instance - ->rawWrite(region_id, {str_key}, {str_val_default}, {WriteCmdType::Put}, {ColumnFamilyType::Default}); - UNUSED(term); - proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - ASSERT_EQ(kvr1->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(kvr1->dataSize(), kvr1->getData().totalSize()); - ASSERT_EQ(kvr1->getData().totalSize(), region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - { - // lock - root_of_kvstore_mem_trackers->reset(); - RegionID region_id = 4200; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - auto kvr1 = kvs.getRegion(4100); - auto kvr2 = kvs.getRegion(region_id); - auto [index, term] - = proxy_instance - ->rawWrite(region_id, {str_key}, {str_lock_value}, {WriteCmdType::Put}, {ColumnFamilyType::Lock}); - UNUSED(term); - proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(kvr2->dataSize(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(kvr2->dataSize() + decoded_lock_size, kvr2->getData().totalSize()); - ASSERT_EQ( - kvr2->getData().totalSize() + kvr1->getData().totalSize(), - region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - { - // lock with largetxn - root_of_kvstore_mem_trackers->reset(); - RegionID region_id = 4300; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - auto kvr1 = kvs.getRegion(4100); - auto kvr2 = kvs.getRegion(4200); - auto kvr3 = kvs.getRegion(region_id); - ASSERT_NE(kvr3, nullptr); - std::string shor_value = "value"; - auto lock_for_update_ts = 7777, txn_size = 1; - const std::vector & async_commit = {"s1", "s2"}; - const std::vector & rollback = {3, 4}; - auto lock_value2 = DB::RegionBench::encodeFullLockCfValue( - Region::DelFlag, - "primary key", - 421321, - std::numeric_limits::max(), - &shor_value, - 66666, - lock_for_update_ts, - txn_size, - async_commit, - rollback, - 1111); - auto [index, term] - = proxy_instance - ->rawWrite(region_id, {str_key}, {str_lock_value}, {WriteCmdType::Put}, {ColumnFamilyType::Lock}); - UNUSED(term); - proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(kvr3->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(kvr3->dataSize() + decoded_lock_size, kvr3->getData().totalSize()); - ASSERT_EQ( - kvr3->getData().totalSize() + kvr2->getData().totalSize() + kvr1->getData().totalSize(), - region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - { - // insert & remove - root_of_kvstore_mem_trackers->reset(); - RegionID region_id = 5000; - auto originTableSize = region_table.getTableRegionSize(NullspaceID, table_id); - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - auto delta = str_key.dataSize() + str_val_default.size(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), delta); - ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize + delta); - region->remove("default", TiKVKey::copyFrom(str_key)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); - { - // insert - RegionID region_id = 6000; - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - { - // commit - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - - RegionID region_id = 8000; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - region->insertFromSnap("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); - ASSERT_EQ( - str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), - region_table.getTableRegionSize(NullspaceID, table_id)); - std::optional data_list_read = ReadRegionCommitCache(region, true); - ASSERT_TRUE(data_list_read); - ASSERT_EQ(1, data_list_read->size()); - RemoveRegionCommitCache(region, *data_list_read); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - { - // commit by handleWriteRaftCmd - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - - RegionID region_id = 8100; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - { - auto [view, holder] = MockRaftStoreProxy::createWriteCmdsView( - {str_key, str_key}, - {str_val_default, str_val_write}, - {WriteCmdType::Put, WriteCmdType::Put}, - {ColumnFamilyType::Default, ColumnFamilyType::Write}); - region->handleWriteRaftCmd(view, 66, 6, ctx.getTMTContext()); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 1); - } - { - auto [view, holder] = MockRaftStoreProxy::createWriteCmdsView( - {str_key}, - {str_lock_value}, - {WriteCmdType::Put}, - {ColumnFamilyType::Lock}); - region->handleWriteRaftCmd(view, 67, 6, ctx.getTMTContext()); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); - } - } - { - // split & merge - root_of_kvstore_mem_trackers->reset(); - RegionID region_id = 12000; - RegionID region_id2 = 12002; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 22); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); - auto str_lock_value = pickLock(region_id, 22); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - auto str_key2 = pickKey(region_id, 80); - auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); - auto str_lock_value2 = pickLock(region_id, 80); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); - auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); - auto expected = str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - ASSERT_EQ(region->dataSize(), expected); - auto new_region = splitRegion( - region, - RegionMeta( - createPeer(region_id + 1, true), - createRegionInfo( - region_id2, - RecordKVFormat::genKey(table_id, 12050), - RecordKVFormat::genKey(table_id, 12099)), - initialApplyState())); - ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_val_default.size()); - ASSERT_EQ(new_region->dataSize(), str_key2.dataSize() + str_val_default2.size()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - ASSERT_EQ(new_region->dataSize(), new_region->getData().totalSize()); - region->mergeDataFrom(*new_region); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - ASSERT_EQ(region->dataSize(), expected); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - ASSERT_EQ(new_region->dataSize(), new_region->getData().totalSize()); - ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); - } - { - // split & merge with lock - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - RegionID region_id = 13100; - RegionID region_id2 = 13102; - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 22); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 22); - auto str_lock_value = pickLock(region_id, 22); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); - auto expected = str_key.dataSize() + str_lock_value.size(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - auto str_key2 = pickKey(region_id, 80); - std::string short_value(97, 'a'); - auto str_lock_value2 - = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13180, 111, &short_value) - .toString(); - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); - auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); - expected += str_key2.dataSize() + str_lock_value2.size(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - auto new_region = splitRegion( - region, - RegionMeta( - createPeer(region_id + 1, true), - createRegionInfo( - region_id2, - RecordKVFormat::genKey(table_id, 13150), - RecordKVFormat::genKey(table_id, 13199)), - initialApplyState())); - ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - ASSERT_EQ(region->dataSize(), str_key.dataSize() + str_lock_value.size()); - ASSERT_EQ(region->getData().totalSize(), region->dataSize() + decoded_lock_size); - ASSERT_EQ(new_region->dataSize(), str_key2.dataSize() + str_lock_value2.size()); - ASSERT_EQ(new_region->getData().totalSize(), new_region->dataSize() + decoded_lock_size); - region->mergeDataFrom(*new_region); - ASSERT_EQ(original_size, region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - ASSERT_EQ(region->dataSize(), expected); - ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); - - // replace a lock - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); - auto str_lock_value2_2 - = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13022, 111).toString(); - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); - expected -= short_value.size(); - expected -= 2; // Short value prefix and length - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); - ASSERT_EQ(region->dataSize(), expected); - ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); - } - { - // insert & snapshot - UInt64 region_id = 14100; - region_table.debugClearTableRegionSize(NullspaceID, table_id); - root_of_kvstore_mem_trackers->reset(); - auto [start, end] = getStartEnd(region_id); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - ASSERT_NE(region, nullptr); - - auto str_key2 = pickKey(region_id, 20); - auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 20); - auto str_lock_value2 = pickLock(region_id, 20); - - auto str_key3 = pickKey(region_id, 80); - auto [str_val_write3, str_val_default3] = pickWriteDefault(region_id, 80); - auto str_lock_value3 = pickLock(region_id, 80); - - region->insertFromSnap("default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key3.dataSize() + str_val_default3.size()); - ASSERT_EQ(region->dataSize(), str_key3.dataSize() + str_val_default3.size()); - ASSERT_EQ(region->getData().totalSize(), region->dataSize()); - - MockSSTReader::getMockSSTData().clear(); - MockSSTGenerator default_cf{region_id, table_id, ColumnFamilyType::Default}; - default_cf.insert(14180, str_val_default2); - default_cf.finish_file(); - default_cf.freeze(); - kvs.mutProxyHelperUnsafe()->sst_reader_interfaces = make_mock_sst_reader_interface(); - proxy_instance->snapshot(kvs, ctx.getTMTContext(), region_id, {default_cf}, 0, 0, std::nullopt); - ASSERT_EQ(region->dataSize(), str_key2.dataSize() + str_val_default2.size()); - ASSERT_EQ(region->getData().totalSize(), region->dataSize()); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key2.dataSize() + str_val_default2.size()); - ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); - } - { - // assign - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - RegionID region_id = 15100; - RegionID region_id2 = 15200; - auto [start1, end1] = getStartEnd(1100); - auto [start2, end2] = getStartEnd(1200); - proxy_instance - ->debugAddRegions(kvs, ctx.getTMTContext(), {region_id, region_id2}, {{start1, end1}, {start2, end2}}); - RegionPtr region = kvs.getRegion(region_id); - RegionPtr region2 = kvs.getRegion(region_id2); - - auto str_key = pickKey(region_id, 70); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 70); - auto str_lock_value = pickLock(region_id, 70); - - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - - auto str_key2 = pickKey(region_id, 80); - auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); - auto str_lock_value2 = pickLock(region_id, 80); - region2->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); - region2->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - - region->assignRegion(std::move(*region2)); - ASSERT_EQ( - root_of_kvstore_mem_trackers->get(), - str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); - ASSERT_EQ( - region->dataSize(), - str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size()); - ASSERT_EQ(region->getData().totalSize(), region->dataSize()); - // `region2` is not allowed to access after move, however, we assert here in order to make sure the logic. - ASSERT_EQ(region2->dataSize(), 0); - ASSERT_EQ(region2->getData().totalSize(), region2->dataSize()); - } - { - // remove region - RegionID region_id = 16000; - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - auto kvr1 = kvs.getRegion(region_id); - auto [index, term] - = proxy_instance - ->rawWrite(region_id, {str_key}, {str_val_default}, {WriteCmdType::Put}, {ColumnFamilyType::Default}); - UNUSED(term); - proxy_instance->doApply(kvs, ctx.getTMTContext(), cond, region_id, index); - kvs.handleDestroy(region_id, ctx.getTMTContext()); - ASSERT_EQ(0, region_table.getTableRegionSize(NullspaceID, table_id)); - } -} -CATCH - -TEST_F(RegionKVStoreTest, MemoryTracker2) -try -{ - auto & ctx = TiFlashTestEnv::getGlobalContext(); - initStorages(); - KVStore & kvs = getKVS(); - ctx.getTMTContext().debugSetKVStore(kvstore); - auto table_id = proxy_instance->bootstrapTable(ctx, kvs, ctx.getTMTContext()); - - auto & region_table = ctx.getTMTContext().getRegionTable(); - auto getStartEnd = [&](RegionID region_id) { - return std::make_pair( - RecordKVFormat::genKey(table_id, region_id), - RecordKVFormat::genKey(table_id, region_id + 99)); - }; - auto pickKey = [&](RegionID region_id, UInt64 number) { - return RecordKVFormat::genKey(table_id, region_id + number, 111); - }; - auto pickWriteDefault = [&](RegionID, UInt64) { - return proxy_instance->generateTiKVKeyValue(111, 999); - }; - auto pickLock = [&](RegionID region_id, UInt64 number) { - return RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", region_id + number, 999) - .toString(); - }; - { - // reload - RegionID region_id = 7000; - root_of_kvstore_mem_trackers->reset(); - region_table.debugClearTableRegionSize(NullspaceID, table_id); - auto [start, end] = getStartEnd(region_id); - auto str_key = pickKey(region_id, 1); - auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 1); - auto str_lock_value = pickLock(region_id, 1); - proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); - RegionPtr region = kvs.getRegion(region_id); - root_of_kvstore_mem_trackers->reset(); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - tryPersistRegion(kvs, region_id); - root_of_kvstore_mem_trackers->reset(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); - reloadKVSFromDisk(false); - ctx.getTMTContext().debugSetKVStore(kvstore); - region_table.restore(); - ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); - ASSERT_EQ(region->dataSize(), region->getData().totalSize()); - // Only this region is persisted. - ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); - } -} -CATCH TEST_F(RegionKVStoreTest, KVStoreFailRecovery) try @@ -1080,7 +610,7 @@ try 0, 0, std::nullopt, - /*cancel_after_prehandle=*/true); + [](){}); } } } @@ -1409,89 +939,6 @@ try } CATCH -#if USE_JEMALLOC // following tests depends on jemalloc -TEST(FFIJemallocTest, JemallocThread) -try -{ - std::thread t2([&]() { - char * a = new char[888888]; - std::thread t1([&]() { - auto [allocated, deallocated] = JointThreadInfoJeallocMap::getPtrs(); - ASSERT_TRUE(allocated != nullptr); - ASSERT_EQ(*allocated, 0); - ASSERT_TRUE(deallocated != nullptr); - ASSERT_EQ(*deallocated, 0); - }); - t1.join(); - auto [allocated, deallocated] = JointThreadInfoJeallocMap::getPtrs(); - ASSERT_TRUE(allocated != nullptr); - ASSERT_GE(*allocated, 888888); - ASSERT_TRUE(deallocated != nullptr); - delete[] a; - }); - t2.join(); - - std::thread t3([&]() { - // Will not cover mmap memory. - auto [allocated, deallocated] = JointThreadInfoJeallocMap::getPtrs(); - char * a = new char[120]; - void * buf = mmap(nullptr, 6000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ASSERT_LT(*allocated, 6000); - munmap(buf, 0); - delete[] a; - }); - t3.join(); -} -CATCH - -TEST_F(RegionKVStoreTest, StorageBgPool) -try -{ - using namespace std::chrono_literals; - auto & ctx = TiFlashTestEnv::getGlobalContext(); - auto & pool = ctx.getBackgroundPool(); - const auto size = TiFlashTestEnv::DEFAULT_BG_POOL_SIZE; - std::atomic_bool b = false; - - JointThreadInfoJeallocMap & jm = *ctx.getJointThreadInfoJeallocMap(); - - size_t original_size - = TiFlashMetrics::instance().getStorageThreadMemory(TiFlashMetrics::MemoryAllocType::Alloc, "bg"); - - auto t = pool.addTask( - [&]() { - auto * x = new int[1000]; - LOG_INFO(Logger::get(), "allocated"); - while (!b.load()) - { - std::this_thread::sleep_for(1500ms); - } - delete[] x; - LOG_INFO(Logger::get(), "released"); - return false; - }, - false, - 5 * 60 * 1000); - std::this_thread::sleep_for(500ms); - - jm.recordThreadAllocInfo(); - - LOG_INFO(DB::Logger::get(), "bg pool size={}", size); - UInt64 r = TiFlashMetrics::instance().getStorageThreadMemory(TiFlashMetrics::MemoryAllocType::Alloc, "bg"); - ASSERT_GE(r, original_size + sizeof(int) * 1000); - jm.accessStorageMap([size](const JointThreadInfoJeallocMap::AllocMap & m) { - // There are some other bg thread pools - ASSERT_GE(m.size(), size) << m.size(); - }); - jm.accessProxyMap([](const JointThreadInfoJeallocMap::AllocMap & m) { ASSERT_EQ(m.size(), 0); }); - - b.store(true); - - ctx.getBackgroundPool().removeTask(t); -} -CATCH -#endif - TEST(ProxyMode, Normal) try { @@ -1573,7 +1020,7 @@ try // Overlap EXPECT_THROW( proxy_instance - ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, false), + ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, std::nullopt), Exception); LOG_INFO(log, "Set to applying"); @@ -1582,7 +1029,7 @@ try ASSERT_EQ(proxy_helper->getRegionLocalState(1).state(), raft_serverpb::PeerState::Applying); EXPECT_THROW( proxy_instance - ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, false), + ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, std::nullopt), Exception); @@ -1592,7 +1039,7 @@ try r1->mutState().mutable_region()->set_start_key(RecordKVFormat::genKey(table_id, 0)); r1->mutState().mutable_region()->set_end_key(RecordKVFormat::genKey(table_id, 1)); proxy_instance - ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, false); + ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, std::nullopt); } } CATCH From 47f833ef25c409e4aecaa9402f954c602eb2f313 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 15:00:35 +0800 Subject: [PATCH 17/46] prehandle comsumes memory Signed-off-by: Calvin Neo --- .../Debug/MockKVStore/MockRaftStoreProxy.cpp | 2 +- dbms/src/Debug/dbgTools.cpp | 4 +- dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp | 4 +- dbms/src/Storages/KVStore/KVStore.cpp | 19 +++++++-- dbms/src/Storages/KVStore/KVStore.h | 8 +++- .../Storages/KVStore/MultiRaft/IngestSST.cpp | 2 +- .../Storages/KVStore/tests/gtest_memory.cpp | 8 ++-- .../KVStore/tests/gtest_new_kvstore.cpp | 42 +++++++++++++++---- 8 files changed, 65 insertions(+), 24 deletions(-) diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index d3b076c585b..e4508d94dfb 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -643,7 +643,7 @@ std::tuple MockRaftStoreProxy::snapshot( // The new entry is committed on Proxy's side. region->updateCommitIndex(index); // Would set `appleid_index` in genRegionPtr. - auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term); + auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term, tmt, true); auto & region_table = tmt.getRegionTable(); region_table.addPrehandlingRegion(*new_kv_region); diff --git a/dbms/src/Debug/dbgTools.cpp b/dbms/src/Debug/dbgTools.cpp index 2c8a9349938..f0ca1dac7be 100644 --- a/dbms/src/Debug/dbgTools.cpp +++ b/dbms/src/Debug/dbgTools.cpp @@ -784,9 +784,7 @@ void handleApplySnapshot( std::optional deadline_index, TMTContext & tmt) { - auto new_region = kvstore.genRegionPtr(std::move(region), peer_id, index, term); - auto & region_table = tmt.getRegionTable(); - region_table.addPrehandlingRegion(*new_region); + auto new_region = kvstore.genRegionPtr(std::move(region), peer_id, index, term, tmt, true); auto prehandle_result = kvstore.preHandleSnapshotToFiles(new_region, snaps, index, term, deadline_index, tmt); kvstore.applyPreHandledSnapshot( RegionPtrWithSnapshotFiles{new_region, std::move(prehandle_result.ingest_ids)}, diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp index 0a126e5aa69..f915487ee84 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp @@ -667,9 +667,7 @@ RawCppPtr PreHandleSnapshot( auto & tmt = *server->tmt; auto & kvstore = tmt.getKVStore(); // TODO move this inside `preHandleSnapshotToFiles`, or change `genRegionPtr`. - auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term); - auto & region_table = tmt.getRegionTable(); - region_table.addPrehandlingRegion(*new_region); + auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term, tmt, true); #ifndef NDEBUG { diff --git a/dbms/src/Storages/KVStore/KVStore.cpp b/dbms/src/Storages/KVStore/KVStore.cpp index f9dbe6e4b3a..212c33b035b 100644 --- a/dbms/src/Storages/KVStore/KVStore.cpp +++ b/dbms/src/Storages/KVStore/KVStore.cpp @@ -484,8 +484,14 @@ static const metapb::Peer & findPeer(const metapb::Region & region, UInt64 peer_ region.id()); } -// Generate a temporary region pointer by the given meta -RegionPtr KVStore::genRegionPtr(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term) +// The only way that to create a region associated to a piece of data, even if it is not going to be inserted in to KVStore. +RegionPtr KVStore::genRegionPtr( + metapb::Region && region, + UInt64 peer_id, + UInt64 index, + UInt64 term, + TMTContext & tmt, + bool register_to_table) { auto meta = ({ auto peer = findPeer(region, peer_id); @@ -497,8 +503,13 @@ RegionPtr KVStore::genRegionPtr(metapb::Region && region, UInt64 peer_id, UInt64 } RegionMeta(std::move(peer), std::move(region), std::move(apply_state)); }); - - return std::make_shared(std::move(meta), proxy_helper); + auto new_region = std::make_shared(std::move(meta), proxy_helper); + if (register_to_table) + { + auto & region_table = tmt.getRegionTable(); + region_table.addPrehandlingRegion(*new_region); + } + return new_region; } RegionTaskLock KVStore::genRegionTaskLock(UInt64 region_id) const diff --git a/dbms/src/Storages/KVStore/KVStore.h b/dbms/src/Storages/KVStore/KVStore.h index a6e7d769247..e35dc0626be 100644 --- a/dbms/src/Storages/KVStore/KVStore.h +++ b/dbms/src/Storages/KVStore/KVStore.h @@ -156,7 +156,13 @@ class KVStore final : private boost::noncopyable RegionPtr getRegion(RegionID region_id) const; RegionMap getRegionsByRangeOverlap(const RegionRange & range) const; void traverseRegions(std::function && callback) const; - RegionPtr genRegionPtr(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term); + RegionPtr genRegionPtr( + metapb::Region && region, + UInt64 peer_id, + UInt64 index, + UInt64 term, + TMTContext & tmt, + bool register_to_table); void handleDestroy(UInt64 region_id, TMTContext & tmt); void setKVStoreMemoryLimit(size_t s) { maximum_kvstore_memory = s; } size_t getKVStoreMemoryLimit() const { return maximum_kvstore_memory; } diff --git a/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp b/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp index 2379bce6c3b..22a0b302ce4 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp @@ -113,7 +113,7 @@ RegionPtr KVStore::handleIngestSSTByDTFile( auto meta_region = region->cloneMetaRegion(); auto meta_snap = region->dumpRegionMetaSnapshot(); auto peer_id = meta_snap.peer.id(); - tmp_region = genRegionPtr(std::move(meta_region), peer_id, index, term); + tmp_region = genRegionPtr(std::move(meta_region), peer_id, index, term, tmt, false); } // Decode the KV pairs in ingesting SST into DTFiles diff --git a/dbms/src/Storages/KVStore/tests/gtest_memory.cpp b/dbms/src/Storages/KVStore/tests/gtest_memory.cpp index 2ee781a2911..7b1f61187be 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_memory.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_memory.cpp @@ -404,8 +404,10 @@ try default_cf.finish_file(); default_cf.freeze(); kvs.mutProxyHelperUnsafe()->sst_reader_interfaces = make_mock_sst_reader_interface(); - proxy_instance->snapshot(kvs, ctx.getTMTContext(), region_id, {default_cf}, 0, 0, std::nullopt, [&](){ - ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), str_key2.dataSize() + str_val_default2.size()); + proxy_instance->snapshot(kvs, ctx.getTMTContext(), region_id, {default_cf}, 0, 0, std::nullopt, [&]() { + ASSERT_EQ( + region_table.getTableRegionSize(NullspaceID, table_id), + str_key2.dataSize() + str_val_default2.size()); }); ASSERT_EQ(region->dataSize(), 0); ASSERT_EQ(region->getData().totalSize(), 0); @@ -611,4 +613,4 @@ try } CATCH #endif -} // namespace DB::tests \ No newline at end of file +} // namespace DB::tests diff --git a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp index 977660e087e..a2d41e5d5f0 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_new_kvstore.cpp @@ -72,7 +72,6 @@ try CATCH - TEST_F(RegionKVStoreTest, KVStoreFailRecovery) try { @@ -610,7 +609,7 @@ try 0, 0, std::nullopt, - [](){}); + []() {}); } } } @@ -1019,8 +1018,17 @@ try // Overlap EXPECT_THROW( - proxy_instance - ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, std::nullopt), + proxy_instance->snapshot( + kvs, + ctx.getTMTContext(), + 2, + {default_cf}, + make_meta(), + peer_id, + 0, + 0, + std::nullopt, + std::nullopt), Exception); LOG_INFO(log, "Set to applying"); @@ -1028,8 +1036,17 @@ try r1->mutState().set_state(raft_serverpb::PeerState::Applying); ASSERT_EQ(proxy_helper->getRegionLocalState(1).state(), raft_serverpb::PeerState::Applying); EXPECT_THROW( - proxy_instance - ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, std::nullopt), + proxy_instance->snapshot( + kvs, + ctx.getTMTContext(), + 2, + {default_cf}, + make_meta(), + peer_id, + 0, + 0, + std::nullopt, + std::nullopt), Exception); @@ -1038,8 +1055,17 @@ try r1->mutState().set_state(raft_serverpb::PeerState::Applying); r1->mutState().mutable_region()->set_start_key(RecordKVFormat::genKey(table_id, 0)); r1->mutState().mutable_region()->set_end_key(RecordKVFormat::genKey(table_id, 1)); - proxy_instance - ->snapshot(kvs, ctx.getTMTContext(), 2, {default_cf}, make_meta(), peer_id, 0, 0, std::nullopt, std::nullopt); + proxy_instance->snapshot( + kvs, + ctx.getTMTContext(), + 2, + {default_cf}, + make_meta(), + peer_id, + 0, + 0, + std::nullopt, + std::nullopt); } } CATCH From fcab6615dc55fa9542380b03858cc19aa0c54d96 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 16:09:52 +0800 Subject: [PATCH 18/46] fix tests Signed-off-by: Calvin Neo --- .../Debug/MockKVStore/MockRaftStoreProxy.cpp | 2 - .../dbgKVStore/dbgFuncMockRaftSnapshot.cpp | 2 +- .../Decode/SSTFilesToBlockInputStream.cpp | 6 +-- .../Storages/KVStore/Decode/RegionTable.cpp | 1 - .../Storages/KVStore/Decode/RegionTable_fwd.h | 2 + .../KVStore/MultiRaft/PrehandleSnapshot.cpp | 2 + dbms/src/Storages/KVStore/Region.cpp | 14 ++++-- dbms/src/Storages/KVStore/Region.h | 7 +-- .../Storages/KVStore/tests/gtest_kvstore.cpp | 43 +++++++++++++++---- .../Storages/KVStore/tests/gtest_memory.cpp | 35 ++++++++------- .../tests/gtest_region_block_reader.cpp | 4 +- .../KVStore/tests/gtest_region_persister.cpp | 43 +++++++++++-------- 12 files changed, 105 insertions(+), 56 deletions(-) diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index e4508d94dfb..bf441847783 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -644,8 +644,6 @@ std::tuple MockRaftStoreProxy::snapshot( region->updateCommitIndex(index); // Would set `appleid_index` in genRegionPtr. auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term, tmt, true); - auto & region_table = tmt.getRegionTable(); - region_table.addPrehandlingRegion(*new_kv_region); std::vector ssts; for (auto & cf : cfs) diff --git a/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp b/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp index 76c1fdf2172..bd325bb6167 100644 --- a/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp +++ b/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp @@ -154,7 +154,7 @@ RegionPtr GenDbgRegionSnapshotWithData(Context & context, const ASTs & args) : RecordKVFormat::encodeWriteCfValue(Region::PutFlag, prewrite_ts, value); TiKVKey commit_key = RecordKVFormat::appendTs(key, commit_ts); - region->insertFromSnap(ColumnFamilyType::Write, std::move(commit_key), std::move(commit_value)); + region->insertFromSnap(context.getTMTContext(), ColumnFamilyType::Write, std::move(commit_key), std::move(commit_value)); } MockTiKV::instance().getRaftIndex(region_id); } diff --git a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp index e13518063f7..13386b4c774 100644 --- a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp +++ b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp @@ -194,7 +194,7 @@ Block SSTFilesToBlockInputStream::read() BaseBuffView key = write_cf_reader->keyView(); BaseBuffView value = write_cf_reader->valueView(); auto tikv_key = TiKVKey(key.data, key.len); - region->insertFromSnap(ColumnFamilyType::Write, std::move(tikv_key), TiKVValue(value.data, value.len)); + region->insertFromSnap(tmt, ColumnFamilyType::Write, std::move(tikv_key), TiKVValue(value.data, value.len)); ++process_keys.write_cf; process_keys.write_cf_bytes += (key.len + value.len); if (process_keys.write_cf % opts.expected_size == 0) @@ -278,7 +278,7 @@ void SSTFilesToBlockInputStream::loadCFDataFromSST( BaseBuffView value = reader->valueView(); // TODO: use doInsert to avoid locking region - ->insertFromSnap(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); + ->insertFromSnap(tmt, cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); (*p_process_keys) += 1; (*p_process_keys_bytes) += (key.len + value.len); reader->next(); @@ -338,7 +338,7 @@ void SSTFilesToBlockInputStream::loadCFDataFromSST( BaseBuffView key = reader->keyView(); BaseBuffView value = reader->valueView(); // TODO: use doInsert to avoid locking - region->insertFromSnap(cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len)); + region->insertFromSnap(tmt, cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len)); (*p_process_keys) += 1; (*p_process_keys_bytes) += (key.len + value.len); if (*p_process_keys == process_keys_offset_end) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index 7a0316b82ac..07e5492e011 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -444,7 +444,6 @@ void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & if unlikely (!new_region->getRegionTableCtx()) { // For most of the cases, the region is prehandled, so the ctx is set at that moment. - LOG_INFO(DB::Logger::get(), "!!!! fdsfdfsdf"); new_region->setRegionTableCtx(table.ctx); } } diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h index e94e384c730..b06a3df0097 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h @@ -21,6 +21,8 @@ namespace DB { struct RegionTableCtxInner { + // KVStore size of all regions of this table, including the prehandling one. + // So, this size may be larger than the table's real size. std::atomic_int64_t table_size; std::atomic_bool warned; }; diff --git a/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp b/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp index 5933c941fa9..767d5edca21 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/PrehandleSnapshot.cpp @@ -281,6 +281,7 @@ PrehandleResult KVStore::preHandleSnapshotToFiles( auto ongoing = ongoing_prehandle_task_count.fetch_sub(1) - 1; new_region->afterPrehandleSnapshot(ongoing); }); + new_region->resetWarnMemoryLimitByTable(); PrehandleResult result = preHandleSSTsToDTFiles( // new_region, snaps, @@ -289,6 +290,7 @@ PrehandleResult KVStore::preHandleSnapshotToFiles( DM::FileConvertJobType::ApplySnapshot, tmt); result.stats.start_time = start_time; + new_region->resetWarnMemoryLimitByTable(); return result; } catch (DB::Exception & e) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 2f8969492b4..6248c49c504 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -58,15 +58,21 @@ LockInfoPtr Region::getLockInfo(const RegionLockReadQuery & query) const return data.getLockInfo(query); } -void Region::insertFromSnap(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) +void Region::insertDebug(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) { + std::unique_lock lock(mutex); + doInsert(NameToCF(cf), std::move(key), std::move(value), mode); +} + +void Region::insertFromSnap(TMTContext & tmt, const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) { - insertFromSnap(NameToCF(cf), std::move(key), std::move(value), mode); + insertFromSnap(tmt, NameToCF(cf), std::move(key), std::move(value), mode); } -void Region::insertFromSnap(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode) +void Region::insertFromSnap(TMTContext & tmt, ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode) { std::unique_lock lock(mutex); doInsert(type, std::move(key), std::move(value), mode); + maybeWarnMemoryLimitByTable(tmt, "snapshot"); } RegionDataMemDiff Region::doInsert(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode) @@ -433,7 +439,7 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) } } -void Region::resetWarnMemoryLimitByTable() +void Region::resetWarnMemoryLimitByTable() const { setRegionTableWarned(false); } diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index 63c45ec9968..dcf2ff0d2de 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -134,8 +134,9 @@ class Region : public std::enable_shared_from_this Region() = delete; ~Region(); - void insertFromSnap(ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); - void insertFromSnap(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); + void insertDebug(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); + void insertFromSnap(TMTContext & tmt, ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); + void insertFromSnap(TMTContext & tmt, const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); void remove(const std::string & cf, const TiKVKey & key); // Directly drop all data in this Region object. @@ -239,7 +240,7 @@ class Region : public std::enable_shared_from_this size_t getRegionTableSize() const { return data.getRegionTableSize(); } bool getRegionTableWarned() const { return data.getRegionTableWarned(); } bool setRegionTableWarned(bool desired) const { return data.setRegionTableWarned(desired); } - void resetWarnMemoryLimitByTable(); + void resetWarnMemoryLimitByTable() const; void maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from); public: // Raft Read and Write diff --git a/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp index 79fa54d157b..f54a8b1b3d9 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp @@ -329,21 +329,27 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); // row with handle_id == 8 region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 8), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 8, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -392,20 +398,25 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 8), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 8, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -457,11 +468,14 @@ void RegionKVStoreOldTest::testRaftMerge(Context & ctx, KVStore & kvs, TMTContex // Region 1 with handle_id == 6 auto region = kvs.getRegion(target_region_id); region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 6), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 6, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 6, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 6, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -471,11 +485,14 @@ void RegionKVStoreOldTest::testRaftMerge(Context & ctx, KVStore & kvs, TMTContex // Region 7 with handle_id == 2 auto region = kvs.getRegion(source_region_id); region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 2), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 2, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 2, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 2, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -610,6 +627,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) { auto & ctx = TiFlashTestEnv::getGlobalContext(); TableID table_id = 100; + auto & tmt = ctx.getTMTContext(); KVStore & kvs = getKVS(); UInt64 region_id = 1; proxy_instance->bootstrapWithRegion( @@ -641,11 +659,14 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) { // Test read committed and lock with CommittedScanner. region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20, nullptr, 5)); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -695,6 +716,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::LockType::Lock, "PK", 3, 20, nullptr, 5)); @@ -707,6 +729,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { region->insertFromSnap( + tmt, "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::LockType::Pessimistic, "PK", 3, 20, nullptr, 5)); @@ -720,6 +743,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) { // Test duplicate and tryCompactionFilter region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -730,6 +754,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) { // insert duplicate records region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 3, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::PutFlag, 5)); @@ -749,6 +774,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) { // Test read and delete committed Del record. region->insertFromSnap( + tmt, "write", RecordKVFormat::genKey(table_id, 4, 8), RecordKVFormat::encodeWriteCfValue(RecordKVFormat::CFModifyFlag::DelFlag, 5)); @@ -765,7 +791,8 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { ASSERT_EQ(0, region->dataSize()); - region->insertFromSnap("default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap( + tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); ASSERT_LT(0, region->dataSize()); region->remove("default", RecordKVFormat::genKey(table_id, 3, 5)); ASSERT_EQ(0, region->dataSize()); diff --git a/dbms/src/Storages/KVStore/tests/gtest_memory.cpp b/dbms/src/Storages/KVStore/tests/gtest_memory.cpp index 7b1f61187be..59df4885f18 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_memory.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_memory.cpp @@ -35,6 +35,7 @@ TEST_F(RegionKVStoreTest, MemoryTracker1) try { auto & ctx = TiFlashTestEnv::getGlobalContext(); + auto & tmt = ctx.getTMTContext(); initStorages(); KVStore & kvs = getKVS(); ctx.getTMTContext().debugSetKVStore(kvstore); @@ -157,7 +158,7 @@ try auto str_lock_value = pickLock(region_id, 1); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); auto delta = str_key.dataSize() + str_val_default.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), delta); ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), originTableSize + delta); @@ -180,7 +181,7 @@ try auto str_lock_value = pickLock(region_id, 1); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); ASSERT_EQ(region->dataSize(), root_of_kvstore_mem_trackers->get()); ASSERT_EQ(region->dataSize(), region->getData().totalSize()); @@ -198,9 +199,9 @@ try auto str_lock_value = pickLock(region_id, 1); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); - region->insertFromSnap("write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); + region->insertFromSnap(tmt, "write", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_write)); ASSERT_EQ( str_key.dataSize() * 2 + str_val_default.size() + str_val_write.size(), region_table.getTableRegionSize(NullspaceID, table_id)); @@ -261,11 +262,11 @@ try region_table.debugClearTableRegionSize(NullspaceID, table_id); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); auto str_key2 = pickKey(region_id, 80); auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); auto str_lock_value2 = pickLock(region_id, 80); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); auto expected = str_key.dataSize() + str_val_default.size() + str_key2.dataSize() + str_val_default2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); @@ -305,7 +306,7 @@ try auto str_lock_value = pickLock(region_id, 22); proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); + region->insertFromSnap(tmt, "lock", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_lock_value)); auto expected = str_key.dataSize() + str_lock_value.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); auto str_key2 = pickKey(region_id, 80); @@ -313,7 +314,7 @@ try auto str_lock_value2 = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13180, 111, &short_value) .toString(); - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + region->insertFromSnap(tmt, "lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); auto original_size = region_table.getTableRegionSize(NullspaceID, table_id); expected += str_key2.dataSize() + str_lock_value2.size(); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); @@ -339,15 +340,16 @@ try ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); // replace a lock - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); + region->insertFromSnap(tmt, "lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2)); auto str_lock_value2_2 = RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 13022, 111).toString(); - region->insertFromSnap("lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); + region->insertFromSnap(tmt, "lock", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_lock_value2_2)); expected -= short_value.size(); expected -= 2; // Short value prefix and length ASSERT_EQ(root_of_kvstore_mem_trackers->get(), expected); ASSERT_EQ(region->dataSize(), expected); ASSERT_EQ(region->getData().totalSize(), region->dataSize() + 2 * decoded_lock_size); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 2); } { // insert & snapshot @@ -367,7 +369,7 @@ try auto [str_val_write3, str_val_default3] = pickWriteDefault(region_id, 80); auto str_lock_value3 = pickLock(region_id, 80); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key3), TiKVValue::copyFrom(str_val_default3)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key3.dataSize() + str_val_default3.size()); ASSERT_EQ(region->dataSize(), str_key3.dataSize() + str_val_default3.size()); ASSERT_EQ(region->getData().totalSize(), region->dataSize()); @@ -383,6 +385,7 @@ try ASSERT_EQ(region->getData().totalSize(), region->dataSize()); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key2.dataSize() + str_val_default2.size()); ASSERT_EQ(region->dataSize(), region_table.getTableRegionSize(NullspaceID, table_id)); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 3); } { // prehandle snapshot and drop @@ -413,6 +416,7 @@ try ASSERT_EQ(region->getData().totalSize(), 0); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), 0); ASSERT_EQ(region_table.getTableRegionSize(NullspaceID, table_id), 0); + ASSERT_EQ(kvs.debug_memory_limit_warning_count, 4); } { // assign @@ -431,14 +435,14 @@ try auto [str_val_write, str_val_default] = pickWriteDefault(region_id, 70); auto str_lock_value = pickLock(region_id, 70); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); auto str_key2 = pickKey(region_id, 80); auto [str_val_write2, str_val_default2] = pickWriteDefault(region_id, 80); auto str_lock_value2 = pickLock(region_id, 80); - region2->insertFromSnap("default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); - region2->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region2->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key2), TiKVValue::copyFrom(str_val_default2)); + region2->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); region->assignRegion(std::move(*region2)); ASSERT_EQ( @@ -480,6 +484,7 @@ TEST_F(RegionKVStoreTest, MemoryTracker2) try { auto & ctx = TiFlashTestEnv::getGlobalContext(); + auto & tmt = ctx.getTMTContext(); initStorages(); KVStore & kvs = getKVS(); ctx.getTMTContext().debugSetKVStore(kvstore); @@ -513,7 +518,7 @@ try proxy_instance->debugAddRegions(kvs, ctx.getTMTContext(), {region_id}, {{start, end}}); RegionPtr region = kvs.getRegion(region_id); root_of_kvstore_mem_trackers->reset(); - region->insertFromSnap("default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(str_key), TiKVValue::copyFrom(str_val_default)); ASSERT_EQ(root_of_kvstore_mem_trackers->get(), str_key.dataSize() + str_val_default.size()); tryPersistRegion(kvs, region_id); root_of_kvstore_mem_trackers->reset(); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp index e7cd8096b06..3e5f2c2bc06 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp @@ -665,8 +665,8 @@ try }; for (const auto & [k, v] : kvs) { - region->insertFromSnap( - ColumnFamilyType::Write, + region->insertDebug( + "write", TiKVKey(bytesFromHexString(k)), TiKVValue(bytesFromHexString(v))); } diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index 37b18f7647e..7278c2868de 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -205,9 +205,9 @@ try TableID table_id = 100; auto region = makeTmpRegion(); TiKVKey key = RecordKVFormat::genKey(table_id, 323, 9983); - region->insertFromSnap("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); region->updateRaftLogEagerIndex(1024); @@ -237,9 +237,9 @@ try TableID table_id = 100; auto region = makeTmpRegion(); TiKVKey key = RecordKVFormat::genKey(table_id, 323, 9983); - region->insertFromSnap("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); region->updateRaftLogEagerIndex(1024); @@ -284,9 +284,9 @@ try } TiKVKey key = RecordKVFormat::genKey(table_id, 323, 9983); - region->insertFromSnap("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); const auto path = dir_path + "/region_state.test"; WriteBufferFromFile write_buf(path, DBMS_DEFAULT_BUFFER_SIZE, O_WRONLY | O_CREAT); @@ -542,10 +542,10 @@ class RegionPersisterTest TEST_P(RegionPersisterTest, Concurrency) try { - RegionManager region_manager; - auto ctx = TiFlashTestEnv::getGlobalContext(); + auto & tmt = ctx.getTMTContext(); + RegionManager region_manager; RegionMap regions; const TableID table_id = 100; @@ -567,18 +567,19 @@ try auto region = makeRegion(createRegionMeta(region_100, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_100, diff++); - region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); region->insertFromSnap( + tmt, ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( + tmt, ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); persister.persist(*region, region_task_lock); - regions.emplace(region->id(), region); }); LOG_INFO(log, "paused before persisting region 100"); @@ -591,12 +592,14 @@ try auto region = makeRegion(createRegionMeta(region_101, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_101, diff++); - region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); region->insertFromSnap( + tmt, ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( + tmt, ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -620,6 +623,7 @@ try RegionManager region_manager; auto ctx = TiFlashTestEnv::getGlobalContext(); + auto & tmt = ctx.getTMTContext(); size_t region_num = 100; RegionMap regions; @@ -639,12 +643,14 @@ try auto region = makeRegion(createRegionMeta(i, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, i, diff++); - region->insertFromSnap(ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); region->insertFromSnap( + tmt, ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( + tmt, ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -707,10 +713,10 @@ CATCH TEST_P(RegionPersisterTest, LargeRegion) try { - RegionManager region_manager; - auto ctx = TiFlashTestEnv::getGlobalContext(); + auto & tmt = ctx.getTMTContext(); + RegionManager region_manager; const TableID table_id = 100; const RegionID region_id_base = 20; const String large_value(1024 * 512, 'v'); @@ -736,14 +742,17 @@ try } TiKVKey key = RecordKVFormat::genKey(table_id, handle_id, tso++); region->insertFromSnap( + tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue(large_value.data())); region->insertFromSnap( + tmt, ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( + tmt, ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); From e0de1c2853d0cf9de13e7b7580b0208c4cc45fcf Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 16:10:22 +0800 Subject: [PATCH 19/46] fmt Signed-off-by: Calvin Neo --- .../dbgKVStore/dbgFuncMockRaftSnapshot.cpp | 6 ++++- .../Decode/SSTFilesToBlockInputStream.cpp | 8 +++++-- dbms/src/Storages/KVStore/Region.cpp | 3 ++- dbms/src/Storages/KVStore/Region.h | 14 +++++++++-- .../Storages/KVStore/tests/gtest_kvstore.cpp | 23 +++++++------------ .../tests/gtest_region_block_reader.cpp | 5 +--- .../KVStore/tests/gtest_region_persister.cpp | 4 ++-- 7 files changed, 36 insertions(+), 27 deletions(-) diff --git a/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp b/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp index bd325bb6167..ebb844711c7 100644 --- a/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp +++ b/dbms/src/Debug/dbgKVStore/dbgFuncMockRaftSnapshot.cpp @@ -154,7 +154,11 @@ RegionPtr GenDbgRegionSnapshotWithData(Context & context, const ASTs & args) : RecordKVFormat::encodeWriteCfValue(Region::PutFlag, prewrite_ts, value); TiKVKey commit_key = RecordKVFormat::appendTs(key, commit_ts); - region->insertFromSnap(context.getTMTContext(), ColumnFamilyType::Write, std::move(commit_key), std::move(commit_value)); + region->insertFromSnap( + context.getTMTContext(), + ColumnFamilyType::Write, + std::move(commit_key), + std::move(commit_value)); } MockTiKV::instance().getRaftIndex(region_id); } diff --git a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp index 13386b4c774..282920bbe79 100644 --- a/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp +++ b/dbms/src/Storages/DeltaMerge/Decode/SSTFilesToBlockInputStream.cpp @@ -277,8 +277,12 @@ void SSTFilesToBlockInputStream::loadCFDataFromSST( BaseBuffView key = reader->keyView(); BaseBuffView value = reader->valueView(); // TODO: use doInsert to avoid locking - region - ->insertFromSnap(tmt, cf, TiKVKey(key.data, key.len), TiKVValue(value.data, value.len), DupCheck::AllowSame); + region->insertFromSnap( + tmt, + cf, + TiKVKey(key.data, key.len), + TiKVValue(value.data, value.len), + DupCheck::AllowSame); (*p_process_keys) += 1; (*p_process_keys_bytes) += (key.len + value.len); reader->next(); diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 6248c49c504..2e0fa704ea0 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -58,7 +58,8 @@ LockInfoPtr Region::getLockInfo(const RegionLockReadQuery & query) const return data.getLockInfo(query); } -void Region::insertDebug(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) { +void Region::insertDebug(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode) +{ std::unique_lock lock(mutex); doInsert(NameToCF(cf), std::move(key), std::move(value), mode); } diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index dcf2ff0d2de..64b17e6dc4d 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -135,8 +135,18 @@ class Region : public std::enable_shared_from_this ~Region(); void insertDebug(const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); - void insertFromSnap(TMTContext & tmt, ColumnFamilyType type, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); - void insertFromSnap(TMTContext & tmt, const std::string & cf, TiKVKey && key, TiKVValue && value, DupCheck mode = DupCheck::Deny); + void insertFromSnap( + TMTContext & tmt, + ColumnFamilyType type, + TiKVKey && key, + TiKVValue && value, + DupCheck mode = DupCheck::Deny); + void insertFromSnap( + TMTContext & tmt, + const std::string & cf, + TiKVKey && key, + TiKVValue && value, + DupCheck mode = DupCheck::Deny); void remove(const std::string & cf, const TiKVKey & key); // Directly drop all data in this Region object. diff --git a/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp b/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp index f54a8b1b3d9..8823692800b 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_kvstore.cpp @@ -333,8 +333,7 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); region->insertFromSnap( tmt, "write", @@ -346,8 +345,7 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 8, 5), TiKVValue("value1")); region->insertFromSnap( tmt, "write", @@ -402,8 +400,7 @@ static void testRaftSplit(KVStore & kvs, TMTContext & tmt, std::unique_ptrinsertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); region->insertFromSnap( tmt, "write", @@ -468,12 +465,11 @@ void RegionKVStoreOldTest::testRaftMerge(Context & ctx, KVStore & kvs, TMTContex // Region 1 with handle_id == 6 auto region = kvs.getRegion(target_region_id); region->insertFromSnap( - tmt, + tmt, "lock", RecordKVFormat::genKey(table_id, 6), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 6, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 6, 5), TiKVValue("value1")); region->insertFromSnap( tmt, "write", @@ -489,8 +485,7 @@ void RegionKVStoreOldTest::testRaftMerge(Context & ctx, KVStore & kvs, TMTContex "lock", RecordKVFormat::genKey(table_id, 2), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20)); - region->insertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 2, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 2, 5), TiKVValue("value1")); region->insertFromSnap( tmt, "write", @@ -663,8 +658,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) "lock", RecordKVFormat::genKey(table_id, 3), RecordKVFormat::encodeLockCfValue(RecordKVFormat::CFModifyFlag::PutFlag, "PK", 3, 20, nullptr, 5)); - region->insertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); region->insertFromSnap( tmt, "write", @@ -791,8 +785,7 @@ TEST_F(RegionKVStoreOldTest, RegionReadWrite) } { ASSERT_EQ(0, region->dataSize()); - region->insertFromSnap( - tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); + region->insertFromSnap(tmt, "default", RecordKVFormat::genKey(table_id, 3, 5), TiKVValue("value1")); ASSERT_LT(0, region->dataSize()); region->remove("default", RecordKVFormat::genKey(table_id, 3, 5)); ASSERT_EQ(0, region->dataSize()); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp index 3e5f2c2bc06..174b19866bc 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_block_reader.cpp @@ -665,10 +665,7 @@ try }; for (const auto & [k, v] : kvs) { - region->insertDebug( - "write", - TiKVKey(bytesFromHexString(k)), - TiKVValue(bytesFromHexString(v))); + region->insertDebug("write", TiKVKey(bytesFromHexString(k)), TiKVValue(bytesFromHexString(v))); } auto data_list_read = ReadRegionCommitCache(region, true); diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index 7278c2868de..1b6453ba160 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -594,12 +594,12 @@ try TiKVKey key = RecordKVFormat::genKey(table_id, region_101, diff++); region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); region->insertFromSnap( - tmt, + tmt, ColumnFamilyType::Write, TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( - tmt, + tmt, ColumnFamilyType::Lock, TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); From 2b2522f403d694a45a79be8f52c31d1a63cd9491 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 16:13:14 +0800 Subject: [PATCH 20/46] fmt Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp index f915487ee84..d8e8ede0cf5 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp @@ -666,7 +666,6 @@ RawCppPtr PreHandleSnapshot( CHECK_PARSE_PB_BUFF(region, region_buff.data, region_buff.len); auto & tmt = *server->tmt; auto & kvstore = tmt.getKVStore(); - // TODO move this inside `preHandleSnapshotToFiles`, or change `genRegionPtr`. auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term, tmt, true); #ifndef NDEBUG From 1383412948ffd131d94d5b261793b6dca20a4dfd Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Sat, 8 Feb 2025 16:39:04 +0800 Subject: [PATCH 21/46] clippy Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index 7dcd6c4eaa1..ac619cd712a 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -452,7 +452,7 @@ bool RegionData::getRegionTableWarned() const { return region_table_ctx->warned; } - return 0; + return false; } bool RegionData::setRegionTableWarned(bool desired) const From 7693fb65a99b3945d19018dc57562c459ba059ba Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 12:02:41 +0800 Subject: [PATCH 22/46] pick some Signed-off-by: Calvin Neo --- dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp | 2 +- dbms/src/Debug/dbgTools.cpp | 2 +- dbms/src/Storages/KVStore/Decode/RegionTable.h | 8 ++++---- dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp | 2 +- dbms/src/Storages/KVStore/KVStore.cpp | 8 +++----- dbms/src/Storages/KVStore/KVStore.h | 3 +-- dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp | 2 +- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index bf441847783..3dffa898655 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -643,7 +643,7 @@ std::tuple MockRaftStoreProxy::snapshot( // The new entry is committed on Proxy's side. region->updateCommitIndex(index); // Would set `appleid_index` in genRegionPtr. - auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term, tmt, true); + auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term, tmt.getRegionTable()); std::vector ssts; for (auto & cf : cfs) diff --git a/dbms/src/Debug/dbgTools.cpp b/dbms/src/Debug/dbgTools.cpp index f0ca1dac7be..653868622d1 100644 --- a/dbms/src/Debug/dbgTools.cpp +++ b/dbms/src/Debug/dbgTools.cpp @@ -784,7 +784,7 @@ void handleApplySnapshot( std::optional deadline_index, TMTContext & tmt) { - auto new_region = kvstore.genRegionPtr(std::move(region), peer_id, index, term, tmt, true); + auto new_region = kvstore.genRegionPtr(std::move(region), peer_id, index, term, tmt.getRegionTable()); auto prehandle_result = kvstore.preHandleSnapshotToFiles(new_region, snaps, index, term, deadline_index, tmt); kvstore.applyPreHandledSnapshot( RegionPtrWithSnapshotFiles{new_region, std::move(prehandle_result.ingest_ids)}, diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 2429f3886e3..f96a9e83800 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -79,9 +79,8 @@ class RegionTable : private boost::noncopyable { explicit Table(const TableID table_id_) : table_id(table_id_) - { - ctx = createRegionTableCtx(); - } + , ctx(createRegionTableCtx()) + {} TableID table_id; InternalRegions internal_regions; RegionTableCtx ctx; @@ -92,9 +91,10 @@ class RegionTable : private boost::noncopyable // Iterate over all regions in KVStore, and add them to RegionTable. void restore(); - // When a region is added to region table, happens when split ans restore. + // When a region is added to region table, happens when split and restore. void addRegion(const Region & region); + // Most of the regions are scheduled to TiFlash by a raft snapshot. void addPrehandlingRegion(const Region & region); // When a reigon is removed out of TiFlash. diff --git a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp index 5a64ad7758a..a301599fa75 100644 --- a/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp +++ b/dbms/src/Storages/KVStore/FFI/ProxyFFI.cpp @@ -680,7 +680,7 @@ RawCppPtr PreHandleSnapshot( CHECK_PARSE_PB_BUFF(region, region_buff.data, region_buff.len); auto & tmt = *server->tmt; auto & kvstore = tmt.getKVStore(); - auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term, tmt, true); + auto new_region = kvstore->genRegionPtr(std::move(region), peer_id, index, term, tmt.getRegionTable()); #ifndef NDEBUG { diff --git a/dbms/src/Storages/KVStore/KVStore.cpp b/dbms/src/Storages/KVStore/KVStore.cpp index 212c33b035b..1eb2f934117 100644 --- a/dbms/src/Storages/KVStore/KVStore.cpp +++ b/dbms/src/Storages/KVStore/KVStore.cpp @@ -490,8 +490,7 @@ RegionPtr KVStore::genRegionPtr( UInt64 peer_id, UInt64 index, UInt64 term, - TMTContext & tmt, - bool register_to_table) + std::optional> region_table) { auto meta = ({ auto peer = findPeer(region, peer_id); @@ -504,10 +503,9 @@ RegionPtr KVStore::genRegionPtr( RegionMeta(std::move(peer), std::move(region), std::move(apply_state)); }); auto new_region = std::make_shared(std::move(meta), proxy_helper); - if (register_to_table) + if (region_table) { - auto & region_table = tmt.getRegionTable(); - region_table.addPrehandlingRegion(*new_region); + region_table.value().get().addPrehandlingRegion(*new_region); } return new_region; } diff --git a/dbms/src/Storages/KVStore/KVStore.h b/dbms/src/Storages/KVStore/KVStore.h index e35dc0626be..09463d4c771 100644 --- a/dbms/src/Storages/KVStore/KVStore.h +++ b/dbms/src/Storages/KVStore/KVStore.h @@ -161,8 +161,7 @@ class KVStore final : private boost::noncopyable UInt64 peer_id, UInt64 index, UInt64 term, - TMTContext & tmt, - bool register_to_table); + std::optional> region_table); void handleDestroy(UInt64 region_id, TMTContext & tmt); void setKVStoreMemoryLimit(size_t s) { maximum_kvstore_memory = s; } size_t getKVStoreMemoryLimit() const { return maximum_kvstore_memory; } diff --git a/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp b/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp index 22a0b302ce4..e496ad2c679 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp @@ -113,7 +113,7 @@ RegionPtr KVStore::handleIngestSSTByDTFile( auto meta_region = region->cloneMetaRegion(); auto meta_snap = region->dumpRegionMetaSnapshot(); auto peer_id = meta_snap.peer.id(); - tmp_region = genRegionPtr(std::move(meta_region), peer_id, index, term, tmt, false); + tmp_region = genRegionPtr(std::move(meta_region), peer_id, index, term, std::nullopt); } // Decode the KV pairs in ingesting SST into DTFiles From 8ec442a0825384c17dfae65844e3ae3fcf653e8c Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 13:12:19 +0800 Subject: [PATCH 23/46] picked Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/KVStore.cpp | 29 +------------------ .../Storages/KVStore/MultiRaft/RegionMeta.cpp | 29 +++++++++++++++++++ .../Storages/KVStore/MultiRaft/RegionMeta.h | 2 ++ .../KVStore/MultiRaft/RegionRangeKeys.cpp | 10 ------- .../KVStore/MultiRaft/RegionRangeKeys.h | 5 ++-- 5 files changed, 35 insertions(+), 40 deletions(-) diff --git a/dbms/src/Storages/KVStore/KVStore.cpp b/dbms/src/Storages/KVStore/KVStore.cpp index 1eb2f934117..6782175fd03 100644 --- a/dbms/src/Storages/KVStore/KVStore.cpp +++ b/dbms/src/Storages/KVStore/KVStore.cpp @@ -466,24 +466,6 @@ size_t KVStore::getOngoingPrehandleSubtaskCount() const return std::max(0, prehandling_trace.ongoing_prehandle_subtask_count.load()); } -static const metapb::Peer & findPeer(const metapb::Region & region, UInt64 peer_id) -{ - for (const auto & peer : region.peers()) - { - if (peer.id() == peer_id) - { - return peer; - } - } - - throw Exception( - ErrorCodes::LOGICAL_ERROR, - "{}: peer not found in region, peer_id={} region_id={}", - __PRETTY_FUNCTION__, - peer_id, - region.id()); -} - // The only way that to create a region associated to a piece of data, even if it is not going to be inserted in to KVStore. RegionPtr KVStore::genRegionPtr( metapb::Region && region, @@ -492,16 +474,7 @@ RegionPtr KVStore::genRegionPtr( UInt64 term, std::optional> region_table) { - auto meta = ({ - auto peer = findPeer(region, peer_id); - raft_serverpb::RaftApplyState apply_state; - { - apply_state.set_applied_index(index); - apply_state.mutable_truncated_state()->set_index(index); - apply_state.mutable_truncated_state()->set_term(term); - } - RegionMeta(std::move(peer), std::move(region), std::move(apply_state)); - }); + auto meta = RegionMeta::genFromMetaRegion(std::move(region), peer_id, index, term); auto new_region = std::make_shared(std::move(meta), proxy_helper); if (region_table) { diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp index a820a16cb1c..42c24c5d6ed 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp @@ -495,6 +495,35 @@ RegionMeta::RegionMeta(metapb::Peer peer_, metapb::Region region, raft_serverpb: region_state.setRegion(std::move(region)); } +static const metapb::Peer & findPeer(const metapb::Region & region, UInt64 peer_id) +{ + for (const auto & peer : region.peers()) + { + if (peer.id() == peer_id) + { + return peer; + } + } + + throw Exception( + ErrorCodes::LOGICAL_ERROR, + "{}: peer not found in region, peer_id={} region_id={}", + __PRETTY_FUNCTION__, + peer_id, + region.id()); +} + +RegionMeta RegionMeta::genFromMetaRegion(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term) { + auto peer = findPeer(region, peer_id); + raft_serverpb::RaftApplyState apply_state; + { + apply_state.set_applied_index(index); + apply_state.mutable_truncated_state()->set_index(index); + apply_state.mutable_truncated_state()->set_term(term); + } + return RegionMeta(std::move(peer), std::move(region), std::move(apply_state)); +} + metapb::Region RegionMeta::cloneMetaRegion() const { std::lock_guard lock(mutex); diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.h b/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.h index 04c147d2b88..36997b5a8ee 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.h @@ -72,6 +72,8 @@ class RegionMeta RegionMeta(RegionMeta && rhs); + static RegionMeta genFromMetaRegion(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term); + RegionID regionId() const; UInt64 peerId() const; UInt64 storeId() const; diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.cpp index 357b7312dfa..7bf9e9857a4 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.cpp @@ -35,16 +35,6 @@ RegionRangeKeys::RegionRangeKeys(TiKVKey && start_key, TiKVKey && end_key) } } -TableID RegionRangeKeys::getMappedTableID() const -{ - return mapped_table_id; -} - -KeyspaceID RegionRangeKeys::getKeyspaceID() const -{ - return keyspace_id; -} - const std::pair & RegionRangeKeys::rawKeys() const { return raw; diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.h b/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.h index 8c8beac1f33..b6c9cbf7511 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionRangeKeys.h @@ -60,8 +60,9 @@ class RegionRangeKeys : boost::noncopyable explicit RegionRangeKeys(RegionRange && range) : RegionRangeKeys(std::move(range.first.key), std::move(range.second.key)) {} - TableID getMappedTableID() const; - KeyspaceID getKeyspaceID() const; + TableID getMappedTableID() const { return mapped_table_id; } + KeyspaceID getKeyspaceID() const { return keyspace_id; } + KeyspaceTableID getKeyspaceTableID() const { return KeyspaceTableID(keyspace_id, mapped_table_id); } std::string toDebugString() const; static bool isRangeOverlapped(const RegionRange & a, const RegionRange & b) From 888ce9d3f8f0a3ecbaddd2cc2bbd577098ad79d1 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 13:15:15 +0800 Subject: [PATCH 24/46] Update dbms/src/Storages/KVStore/Decode/RegionTable.cpp Co-authored-by: JaySon --- dbms/src/Storages/KVStore/Decode/RegionTable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index 07e5492e011..5004ec00110 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -117,7 +117,7 @@ void RegionTable::clear() { region_infos.clear(); tables.clear(); - safe_ts_mgr.safe_ts_map.clear(); + safe_ts_mgr.clear(); } void RegionTable::restore() From cb02a8e8f247518d56b556c9b946b0bd5457ab2a Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 13:15:22 +0800 Subject: [PATCH 25/46] Update dbms/src/Storages/KVStore/Decode/SafeTsMgr.h Co-authored-by: JaySon --- dbms/src/Storages/KVStore/Decode/SafeTsMgr.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h b/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h index 40fe9078321..fa09f84b140 100644 --- a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h +++ b/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h @@ -70,7 +70,13 @@ struct SafeTsMgr std::unique_lock write_lock(rw_lock); safe_ts_map.erase(region_id); } + void clear() + { + std::unique_lock write_lock(rw_lock); + safe_ts_map.clear(); + } +private: SafeTsMap safe_ts_map; mutable std::shared_mutex rw_lock; }; From 540ab2cfe29de89fe77333a1181f95628f1fc29d Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 13:25:44 +0800 Subject: [PATCH 26/46] format Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp index 42c24c5d6ed..c1f39557938 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionMeta.cpp @@ -513,7 +513,8 @@ static const metapb::Peer & findPeer(const metapb::Region & region, UInt64 peer_ region.id()); } -RegionMeta RegionMeta::genFromMetaRegion(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term) { +RegionMeta RegionMeta::genFromMetaRegion(metapb::Region && region, UInt64 peer_id, UInt64 index, UInt64 term) +{ auto peer = findPeer(region, peer_id); raft_serverpb::RaftApplyState apply_state; { From 458274d07a3c33519182a8f6c19dcbc33bf6b330 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 14:57:00 +0800 Subject: [PATCH 27/46] Update dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp Co-authored-by: jinhelin --- dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp index 3dffa898655..12c69e1a977 100644 --- a/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp +++ b/dbms/src/Debug/MockKVStore/MockRaftStoreProxy.cpp @@ -642,7 +642,7 @@ std::tuple MockRaftStoreProxy::snapshot( // The new entry is committed on Proxy's side. region->updateCommitIndex(index); - // Would set `appleid_index` in genRegionPtr. + // Would set `applied_index` in genRegionPtr. auto new_kv_region = kvs.genRegionPtr(std::move(region_meta), peer_id, index, term, tmt.getRegionTable()); std::vector ssts; From 2f1afc9b8c06a868bd713a2c5ae12eb3642c1c22 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 15:04:01 +0800 Subject: [PATCH 28/46] Update dbms/src/Storages/KVStore/Region.cpp Co-authored-by: JaySon --- dbms/src/Storages/KVStore/Region.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 2e0fa704ea0..2c77d4b7a0c 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -428,7 +428,7 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) #endif LOG_INFO( log, - "Memory limit exeeded, current={} limit={} table_id={} keyspace_id={} region_id={} from={}", + "Memory limit exceeded, current={} limit={} table_id={} keyspace_id={} region_id={} from={}", current, limit, mapped_table_id, From 5680b5daaaa1e7f94e194327629b7652952f29b7 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 15:11:53 +0800 Subject: [PATCH 29/46] fixprob Signed-off-by: Calvin Neo --- .../Storages/KVStore/Decode/RegionTable.cpp | 13 ++---- .../src/Storages/KVStore/Decode/RegionTable.h | 1 - .../Storages/KVStore/MultiRaft/IngestSST.cpp | 2 +- dbms/src/Storages/KVStore/Region.h | 2 +- .../KVStore/tests/gtest_region_persister.cpp | 44 ++++++++----------- 5 files changed, 23 insertions(+), 39 deletions(-) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp index 5004ec00110..03f4ef535e0 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.cpp +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.cpp @@ -60,12 +60,6 @@ RegionTable::Table & RegionTable::getOrCreateTable(const KeyspaceID keyspace_id, return it->second; } -RegionTable::InternalRegion & RegionTable::insertRegion(Table & table, const Region & region) -{ - const auto range = region.getRange(); - return insertRegion(table, *range, region); -} - RegionTable::InternalRegion & RegionTable::insertRegion( Table & table, const RegionRangeKeys & region_range_keys, @@ -105,7 +99,7 @@ RegionTable::InternalRegion & RegionTable::getOrInsertRegion(const Region & regi if (auto it = table_regions.find(region.id()); it != table_regions.end()) return it->second; - return insertRegion(table, region); + return insertRegion(table, *region.getRange(), region); } RegionTable::RegionTable(Context & context_) @@ -143,9 +137,7 @@ void RegionTable::removeTable(KeyspaceID keyspace_id, TableID table_id) for (const auto & region_info : table.internal_regions) { region_infos.erase(region_info.first); - { - safe_ts_mgr.remove(region_info.first); - } + safe_ts_mgr.remove(region_info.first); } // Remove from table map. @@ -436,6 +428,7 @@ void RegionTable::replaceRegion(const RegionPtr & old_region, const RegionPtr & extendRegionRange(*new_region, *region_range_keys); if (old_region) { + std::scoped_lock lock(mutex); // `old_region` will no longer contribute to the memory of the table. auto keyspace_id = region_range_keys->getKeyspaceID(); auto table_id = region_range_keys->getMappedTableID(); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index f96a9e83800..39510e7681b 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -166,7 +166,6 @@ class RegionTable : private boost::noncopyable void removeTable(KeyspaceID keyspace_id, TableID table_id); InternalRegion & getOrInsertRegion(const Region & region); InternalRegion & insertRegion(Table & table, const RegionRangeKeys & region_range_keys, const Region & region); - InternalRegion & insertRegion(Table & table, const Region & region); InternalRegion & doGetInternalRegion(KeyspaceTableID ks_table_id, RegionID region_id); void addTableToIndex(KeyspaceID keyspace_id, TableID table_id); void removeTableFromIndex(KeyspaceID keyspace_id, TableID table_id); diff --git a/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp b/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp index e496ad2c679..ede8a961308 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/IngestSST.cpp @@ -107,7 +107,7 @@ RegionPtr KVStore::handleIngestSSTByDTFile( if (index <= region->appliedIndex()) return nullptr; - // Create a tmp region to store uncommitted data + // Create a tmp region to store uncommitted data, the uncommitted data will be merged from `tmp_region` to the existing region. So here ignore the region_table. RegionPtr tmp_region; { auto meta_region = region->cloneMetaRegion(); diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index 64b17e6dc4d..6a0958e23a1 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -243,7 +243,7 @@ class Region : public std::enable_shared_from_this const RegionData::OrphanKeysInfo & orphanKeysInfo() const { return data.orphan_keys_info; } // Bind a region to a RegionTable. It could not be bound to another table any more. - // All memory changes to this region would relect to the binded table. + // All memory changes to this region would reflect to the binded table. void setRegionTableCtx(RegionTableCtx size) const; RegionTableCtx getRegionTableCtx() const { return data.getRegionTableCtx(); } RegionTableCtx resetRegionTableCtx() const { return data.resetRegionTableCtx(); } diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index 1b6453ba160..5f845e13b26 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -543,7 +543,6 @@ TEST_P(RegionPersisterTest, Concurrency) try { auto ctx = TiFlashTestEnv::getGlobalContext(); - auto & tmt = ctx.getTMTContext(); RegionManager region_manager; RegionMap regions; @@ -567,15 +566,13 @@ try auto region = makeRegion(createRegionMeta(region_100, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_100, diff++); - region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap( - tmt, - ColumnFamilyType::Write, + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertDebug( + "write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap( - tmt, - ColumnFamilyType::Lock, + region->insertDebug( + "lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -592,15 +589,13 @@ try auto region = makeRegion(createRegionMeta(region_101, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_101, diff++); - region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap( - tmt, - ColumnFamilyType::Write, + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertDebug( + "write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap( - tmt, - ColumnFamilyType::Lock, + region->insertDebug( + "lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -623,7 +618,6 @@ try RegionManager region_manager; auto ctx = TiFlashTestEnv::getGlobalContext(); - auto & tmt = ctx.getTMTContext(); size_t region_num = 100; RegionMap regions; @@ -643,15 +637,13 @@ try auto region = makeRegion(createRegionMeta(i, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, i, diff++); - region->insertFromSnap(tmt, ColumnFamilyType::Default, TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertFromSnap( - tmt, - ColumnFamilyType::Write, + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); + region->insertDebug( + "write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap( - tmt, - ColumnFamilyType::Lock, + region->insertDebug( + "lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); @@ -743,17 +735,17 @@ try TiKVKey key = RecordKVFormat::genKey(table_id, handle_id, tso++); region->insertFromSnap( tmt, - ColumnFamilyType::Default, + "default", TiKVKey::copyFrom(key), TiKVValue(large_value.data())); region->insertFromSnap( tmt, - ColumnFamilyType::Write, + "write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( tmt, - ColumnFamilyType::Lock, + "lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); handle_id += 1; From e1c62c22c978ff35c10c3eb78e34de17c1fe175f Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 15:14:10 +0800 Subject: [PATCH 30/46] rename to ptr Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Decode/RegionTable.h | 2 +- dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h | 8 ++++---- dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp | 6 +++--- dbms/src/Storages/KVStore/MultiRaft/RegionData.h | 8 ++++---- dbms/src/Storages/KVStore/Region.cpp | 4 ++-- dbms/src/Storages/KVStore/Region.h | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 39510e7681b..5b40efd9431 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -83,7 +83,7 @@ class RegionTable : private boost::noncopyable {} TableID table_id; InternalRegions internal_regions; - RegionTableCtx ctx; + RegionTableCtxPtr ctx; }; explicit RegionTable(Context & context_); diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h index b06a3df0097..cf520025665 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable_fwd.h @@ -19,16 +19,16 @@ namespace DB { -struct RegionTableCtxInner +struct RegionTableCtx { // KVStore size of all regions of this table, including the prehandling one. // So, this size may be larger than the table's real size. std::atomic_int64_t table_size; std::atomic_bool warned; }; -using RegionTableCtx = std::shared_ptr; -inline RegionTableCtx createRegionTableCtx() +using RegionTableCtxPtr = std::shared_ptr; +inline RegionTableCtxPtr createRegionTableCtx() { - return std::make_shared(0, false); + return std::make_shared(0, false); } } // namespace DB diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp index ac619cd712a..9f57c0d7c95 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.cpp @@ -411,7 +411,7 @@ size_t RegionData::tryCompactionFilter(Timestamp safe_point) return del_write; } -void RegionData::setRegionTableCtx(RegionTableCtx ctx) const +void RegionData::setRegionTableCtx(RegionTableCtxPtr ctx) const { region_table_ctx = ctx; if (region_table_ctx) @@ -420,12 +420,12 @@ void RegionData::setRegionTableCtx(RegionTableCtx ctx) const } } -RegionTableCtx RegionData::getRegionTableCtx() const +RegionTableCtxPtr RegionData::getRegionTableCtx() const { return region_table_ctx; } -RegionTableCtx RegionData::resetRegionTableCtx() const +RegionTableCtxPtr RegionData::resetRegionTableCtx() const { if (region_table_ctx) { diff --git a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h index 4221d8462f5..2ae3810520d 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/RegionData.h +++ b/dbms/src/Storages/KVStore/MultiRaft/RegionData.h @@ -85,9 +85,9 @@ class RegionData String summary() const; size_t tryCompactionFilter(Timestamp safe_point); - void setRegionTableCtx(RegionTableCtx) const; - RegionTableCtx getRegionTableCtx() const; - RegionTableCtx resetRegionTableCtx() const; + void setRegionTableCtx(RegionTableCtxPtr) const; + RegionTableCtxPtr getRegionTableCtx() const; + RegionTableCtxPtr resetRegionTableCtx() const; size_t getRegionTableSize() const; bool getRegionTableWarned() const; bool setRegionTableWarned(bool) const; @@ -146,7 +146,7 @@ class RegionData std::atomic cf_data_size = 0; // Size of decoded structures for convenient access, considered as amplification in memory. std::atomic decoded_data_size = 0; - mutable RegionTableCtx region_table_ctx; + mutable RegionTableCtxPtr region_table_ctx; }; } // namespace DB diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 2e0fa704ea0..dde727cd4b3 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -401,9 +401,9 @@ Timestamp Region::getLastObservedReadTso() const return last_observed_read_tso.load(); } -void Region::setRegionTableCtx(RegionTableCtx size) const +void Region::setRegionTableCtx(RegionTableCtxPtr ctx) const { - data.setRegionTableCtx(size); + data.setRegionTableCtx(ctx); } void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index 6a0958e23a1..fc1786fca6c 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -244,9 +244,9 @@ class Region : public std::enable_shared_from_this // Bind a region to a RegionTable. It could not be bound to another table any more. // All memory changes to this region would reflect to the binded table. - void setRegionTableCtx(RegionTableCtx size) const; - RegionTableCtx getRegionTableCtx() const { return data.getRegionTableCtx(); } - RegionTableCtx resetRegionTableCtx() const { return data.resetRegionTableCtx(); } + void setRegionTableCtx(RegionTableCtxPtr size) const; + RegionTableCtxPtr getRegionTableCtx() const { return data.getRegionTableCtx(); } + RegionTableCtxPtr resetRegionTableCtx() const { return data.resetRegionTableCtx(); } size_t getRegionTableSize() const { return data.getRegionTableSize(); } bool getRegionTableWarned() const { return data.getRegionTableWarned(); } bool setRegionTableWarned(bool desired) const { return data.setRegionTableWarned(desired); } From 8a1e7a47d4dd7d9b4debe918e9e1a9bac3f7188e Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Wed, 12 Feb 2025 16:35:52 +0800 Subject: [PATCH 31/46] f Signed-off-by: Calvin Neo --- .../KVStore/tests/gtest_region_persister.cpp | 43 ++++--------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index 5f845e13b26..7f9abd23043 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -567,14 +567,8 @@ try auto region = makeRegion(createRegionMeta(region_100, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_100, diff++); region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertDebug( - "write", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertDebug( - "lock", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); persister.persist(*region, region_task_lock); regions.emplace(region->id(), region); @@ -590,14 +584,8 @@ try auto region = makeRegion(createRegionMeta(region_101, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, region_101, diff++); region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertDebug( - "write", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertDebug( - "lock", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); persister.persist(*region, region_task_lock); @@ -638,14 +626,8 @@ try auto region = makeRegion(createRegionMeta(i, table_id)); TiKVKey key = RecordKVFormat::genKey(table_id, i, diff++); region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue("value1")); - region->insertDebug( - "write", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertDebug( - "lock", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); persister.persist(*region, region_task_lock); @@ -733,16 +715,9 @@ try break; } TiKVKey key = RecordKVFormat::genKey(table_id, handle_id, tso++); - region->insertFromSnap( - tmt, - "default", - TiKVKey::copyFrom(key), - TiKVValue(large_value.data())); - region->insertFromSnap( - tmt, - "write", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(key), TiKVValue(large_value.data())); + region + ->insertFromSnap(tmt, "write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); region->insertFromSnap( tmt, "lock", From 1707ae55c9841dc18e4aa7c4d5bccbf2deea0896 Mon Sep 17 00:00:00 2001 From: JaySon-Huang Date: Fri, 14 Feb 2025 15:38:36 +0800 Subject: [PATCH 32/46] Fix CI lint; rename SafeTsMgr -> SafeTsManager Signed-off-by: JaySon-Huang --- .../src/Storages/KVStore/Decode/RegionTable.h | 8 +++---- .../{SafeTsMgr.cpp => SafeTsManager.cpp} | 8 +++---- .../Decode/{SafeTsMgr.h => SafeTsManager.h} | 22 +++++++++---------- dbms/src/Storages/KVStore/Region.h | 2 +- .../KVStore/tests/gtest_region_persister.cpp | 12 +++------- 5 files changed, 22 insertions(+), 30 deletions(-) rename dbms/src/Storages/KVStore/Decode/{SafeTsMgr.cpp => SafeTsManager.cpp} (89%) rename dbms/src/Storages/KVStore/Decode/{SafeTsMgr.h => SafeTsManager.h} (74%) diff --git a/dbms/src/Storages/KVStore/Decode/RegionTable.h b/dbms/src/Storages/KVStore/Decode/RegionTable.h index 764ee297d31..22f554752ce 100644 --- a/dbms/src/Storages/KVStore/Decode/RegionTable.h +++ b/dbms/src/Storages/KVStore/Decode/RegionTable.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -154,8 +154,8 @@ class RegionTable : private boost::noncopyable size_t getTableRegionSize(KeyspaceID keyspace_id, TableID table_id) const; void debugClearTableRegionSize(KeyspaceID keyspace_id, TableID table_id); - SafeTsMgr & safeTsMgr() { return safe_ts_mgr; } - const SafeTsMgr & safeTsMgr() const { return safe_ts_mgr; } + SafeTsManager & safeTsMgr() { return safe_ts_mgr; } + const SafeTsManager & safeTsMgr() const { return safe_ts_mgr; } private: @@ -182,7 +182,7 @@ class RegionTable : private boost::noncopyable Context * const context; - SafeTsMgr safe_ts_mgr; + SafeTsManager safe_ts_mgr; mutable std::mutex mutex; diff --git a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp b/dbms/src/Storages/KVStore/Decode/SafeTsManager.cpp similarity index 89% rename from dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp rename to dbms/src/Storages/KVStore/Decode/SafeTsManager.cpp index 2ec9b58ada2..76490d06eaa 100644 --- a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.cpp +++ b/dbms/src/Storages/KVStore/Decode/SafeTsManager.cpp @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include namespace DB { -bool SafeTsMgr::isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * self_safe_ts) +bool SafeTsManager::isSafeTSLag(RegionID region_id, SafeTS * leader_safe_ts, SafeTS * self_safe_ts) { { std::shared_lock lock(rw_lock); @@ -38,7 +38,7 @@ bool SafeTsMgr::isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * && ((*leader_safe_ts >> TsoPhysicalShiftBits) - (*self_safe_ts >> TsoPhysicalShiftBits) > SafeTsDiffThreshold); } -UInt64 SafeTsMgr::getSelfSafeTS(UInt64 region_id) const +UInt64 SafeTsManager::getSelfSafeTS(RegionID region_id) const { std::shared_lock lock(rw_lock); auto it = safe_ts_map.find(region_id); @@ -49,7 +49,7 @@ UInt64 SafeTsMgr::getSelfSafeTS(UInt64 region_id) const return it->second->self_safe_ts.load(std::memory_order_relaxed); } -void SafeTsMgr::updateSafeTS(UInt64 region_id, UInt64 leader_safe_ts, UInt64 self_safe_ts) +void SafeTsManager::updateSafeTS(RegionID region_id, SafeTS leader_safe_ts, SafeTS self_safe_ts) { { std::shared_lock lock(rw_lock); diff --git a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h b/dbms/src/Storages/KVStore/Decode/SafeTsManager.h similarity index 74% rename from dbms/src/Storages/KVStore/Decode/SafeTsMgr.h rename to dbms/src/Storages/KVStore/Decode/SafeTsManager.h index fa09f84b140..2fb77aa6a22 100644 --- a/dbms/src/Storages/KVStore/Decode/SafeTsMgr.h +++ b/dbms/src/Storages/KVStore/Decode/SafeTsManager.h @@ -21,9 +21,7 @@ #include #include -#include #include -#include namespace DB { @@ -40,32 +38,32 @@ enum : TsoShiftBits TsoPhysicalShiftBits = 18, }; -struct SafeTsMgr +struct SafeTsManager { // safe ts is maintained by check_leader RPC (https://github.com/tikv/tikv/blob/1ea26a2ac8761af356cc5c0825eb89a0b8fc9749/components/resolved_ts/src/advance.rs#L262), // leader_safe_ts is the safe_ts in leader, leader will send to learner to advance safe_ts of learner, and TiFlash will record the safe_ts into safe_ts_map in check_leader RPC. - // self_safe_ts is the safe_ts in TiFlah learner. When TiFlash proxy receive from leader, TiFlash will update safe_ts_map when TiFlash has applied the raft log to applied_index. + // self_safe_ts is the safe_ts in TiFlash learner. When TiFlash proxy receive from leader, TiFlash will update safe_ts_map when TiFlash has applied the raft log to applied_index. struct SafeTsEntry { - explicit SafeTsEntry(UInt64 leader_safe_ts, UInt64 self_safe_ts) + explicit SafeTsEntry(SafeTS leader_safe_ts, SafeTS self_safe_ts) : leader_safe_ts(leader_safe_ts) , self_safe_ts(self_safe_ts) {} - std::atomic leader_safe_ts; - std::atomic self_safe_ts; + std::atomic leader_safe_ts; + std::atomic self_safe_ts; }; using SafeTsEntryPtr = std::unique_ptr; using SafeTsMap = std::unordered_map; - void updateSafeTS(UInt64 region_id, UInt64 leader_safe_ts, UInt64 self_safe_ts); + void updateSafeTS(RegionID region_id, SafeTS leader_safe_ts, SafeTS self_safe_ts); // unit: ms. If safe_ts diff is larger than 2min, we think the data synchronization progress is far behind the leader. - static const UInt64 SafeTsDiffThreshold = 2 * 60 * 1000; - bool isSafeTSLag(UInt64 region_id, UInt64 * leader_safe_ts, UInt64 * self_safe_ts); + static const SafeTS SafeTsDiffThreshold = 2 * 60 * 1000; + bool isSafeTSLag(RegionID region_id, SafeTS * leader_safe_ts, SafeTS * self_safe_ts); - UInt64 getSelfSafeTS(UInt64 region_id) const; + UInt64 getSelfSafeTS(RegionID region_id) const; - void remove(UInt64 region_id) + void remove(RegionID region_id) { std::unique_lock write_lock(rw_lock); safe_ts_map.erase(region_id); diff --git a/dbms/src/Storages/KVStore/Region.h b/dbms/src/Storages/KVStore/Region.h index fc1786fca6c..0fa0dbd478f 100644 --- a/dbms/src/Storages/KVStore/Region.h +++ b/dbms/src/Storages/KVStore/Region.h @@ -244,7 +244,7 @@ class Region : public std::enable_shared_from_this // Bind a region to a RegionTable. It could not be bound to another table any more. // All memory changes to this region would reflect to the binded table. - void setRegionTableCtx(RegionTableCtxPtr size) const; + void setRegionTableCtx(RegionTableCtxPtr ctx) const; RegionTableCtxPtr getRegionTableCtx() const { return data.getRegionTableCtx(); } RegionTableCtxPtr resetRegionTableCtx() const { return data.resetRegionTableCtx(); } size_t getRegionTableSize() const { return data.getRegionTableSize(); } diff --git a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp index 7f9abd23043..ace2d3c5bcf 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_region_persister.cpp @@ -688,7 +688,6 @@ TEST_P(RegionPersisterTest, LargeRegion) try { auto ctx = TiFlashTestEnv::getGlobalContext(); - auto & tmt = ctx.getTMTContext(); RegionManager region_manager; const TableID table_id = 100; @@ -715,14 +714,9 @@ try break; } TiKVKey key = RecordKVFormat::genKey(table_id, handle_id, tso++); - region->insertFromSnap(tmt, "default", TiKVKey::copyFrom(key), TiKVValue(large_value.data())); - region - ->insertFromSnap(tmt, "write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); - region->insertFromSnap( - tmt, - "lock", - TiKVKey::copyFrom(key), - RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); + region->insertDebug("default", TiKVKey::copyFrom(key), TiKVValue(large_value.data())); + region->insertDebug("write", TiKVKey::copyFrom(key), RecordKVFormat::encodeWriteCfValue('P', 0)); + region->insertDebug("lock", TiKVKey::copyFrom(key), RecordKVFormat::encodeLockCfValue('P', "", 0, 0)); handle_id += 1; } return region; From 5c70111645a2d30562f60c5c166055392b16c970 Mon Sep 17 00:00:00 2001 From: JaySon-Huang Date: Fri, 14 Feb 2025 16:07:19 +0800 Subject: [PATCH 33/46] Fix CI Signed-off-by: JaySon-Huang --- dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp b/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp index babe922e675..62f11abc2f8 100644 --- a/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp +++ b/dbms/src/Storages/KVStore/tests/gtest_sync_status.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -195,7 +196,7 @@ void makeRegionsLag(size_t lag_num) { tmt.getRegionTable().safeTsMgr().updateSafeTS( i, - (SafeTsMgr::SafeTsDiffThreshold + 1) << TsoPhysicalShiftBits, + (SafeTsManager::SafeTsDiffThreshold + 1) << TsoPhysicalShiftBits, 0); } } From 4d587429aea1ff6ab39763866047fcd5d6496974 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Fri, 14 Feb 2025 18:50:40 +0800 Subject: [PATCH 34/46] ab Signed-off-by: Calvin Neo --- dbms/src/Common/BackgroundTask.cpp | 40 +---------------- dbms/src/Common/MemoryAllocTrace.cpp | 43 +++++++++++++++++++ dbms/src/Common/MemoryAllocTrace.h | 6 ++- dbms/src/Server/Server.cpp | 25 +++++++++-- .../KVStore/MultiRaft/Persistence.cpp | 7 ++- dbms/src/Storages/KVStore/ProxyStateMachine.h | 5 ++- dbms/src/Storages/KVStore/Region.cpp | 15 +++++-- 7 files changed, 90 insertions(+), 51 deletions(-) diff --git a/dbms/src/Common/BackgroundTask.cpp b/dbms/src/Common/BackgroundTask.cpp index 81786c05f5b..18874f08053 100644 --- a/dbms/src/Common/BackgroundTask.cpp +++ b/dbms/src/Common/BackgroundTask.cpp @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include @@ -20,36 +21,6 @@ namespace DB { namespace { -bool process_mem_usage(double & resident_set, Int64 & cur_proc_num_threads, UInt64 & cur_virt_size) -{ - resident_set = 0.0; - - // 'file' stat seems to give the most reliable results - std::ifstream stat_stream("/proc/self/stat", std::ios_base::in); - // if "/proc/self/stat" is not supported - if (!stat_stream.is_open()) - return false; - - // dummy vars for leading entries in stat that we don't care about - std::string pid, comm, state, ppid, pgrp, session, tty_nr; - std::string tpgid, flags, minflt, cminflt, majflt, cmajflt; - std::string utime, stime, cutime, cstime, priority, nice; - std::string itrealvalue, starttime; - - // the field we want - Int64 rss; - - stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >> tpgid >> flags >> minflt >> cminflt - >> majflt >> cmajflt >> utime >> stime >> cutime >> cstime >> priority >> nice >> cur_proc_num_threads - >> itrealvalue >> starttime >> cur_virt_size >> rss; // don't care about the rest - - stat_stream.close(); - - Int64 page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages - resident_set = rss * page_size_kb; - return true; -} - bool isProcStatSupported() { std::ifstream stat_stream("/proc/self/stat", std::ios_base::in); @@ -90,16 +61,9 @@ void CollectProcInfoBackgroundTask::memCheckJob() { try { - double resident_set; - Int64 cur_proc_num_threads = 1; - UInt64 cur_virt_size = 0; while (!end_syn) { - process_mem_usage(resident_set, cur_proc_num_threads, cur_virt_size); - resident_set *= 1024; // unit: byte - real_rss = static_cast(resident_set); - proc_num_threads = cur_proc_num_threads; - proc_virt_size = cur_virt_size; + std::tie(real_rss, proc_num_threads, proc_virt_size) = process_mem_usage(); baseline_of_query_mem_tracker = root_of_query_mem_trackers->get(); usleep(100000); // sleep 100ms } diff --git a/dbms/src/Common/MemoryAllocTrace.cpp b/dbms/src/Common/MemoryAllocTrace.cpp index 35d5ebc67f4..517a9863b7d 100644 --- a/dbms/src/Common/MemoryAllocTrace.cpp +++ b/dbms/src/Common/MemoryAllocTrace.cpp @@ -15,6 +15,8 @@ #include #include // Included for `USE_JEMALLOC` +#include + #if USE_JEMALLOC #include #endif @@ -35,4 +37,45 @@ std::tuple getAllocDeallocPtr() return std::make_tuple(nullptr, nullptr); #endif } + +bool process_mem_usage(double & resident_set, Int64 & cur_proc_num_threads, UInt64 & cur_virt_size) +{ + resident_set = 0.0; + + // 'file' stat seems to give the most reliable results + std::ifstream stat_stream("/proc/self/stat", std::ios_base::in); + // if "/proc/self/stat" is not supported + if (!stat_stream.is_open()) + return false; + + // dummy vars for leading entries in stat that we don't care about + std::string pid, comm, state, ppid, pgrp, session, tty_nr; + std::string tpgid, flags, minflt, cminflt, majflt, cmajflt; + std::string utime, stime, cutime, cstime, priority, nice; + std::string itrealvalue, starttime; + + // the field we want + Int64 rss; + + stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >> tpgid >> flags >> minflt >> cminflt + >> majflt >> cmajflt >> utime >> stime >> cutime >> cstime >> priority >> nice >> cur_proc_num_threads + >> itrealvalue >> starttime >> cur_virt_size >> rss; // don't care about the rest + + stat_stream.close(); + + Int64 page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages + resident_set = rss * page_size_kb; + return true; +} + +std::tuple process_mem_usage() +{ + double resident_set; + Int64 cur_proc_num_threads = 1; + UInt64 cur_virt_size = 0; + process_mem_usage(resident_set, cur_proc_num_threads, cur_virt_size); + resident_set *= 1024; // unit: byte + return std::make_tuple(resident_set, cur_proc_num_threads, cur_virt_size); +} + } // namespace DB diff --git a/dbms/src/Common/MemoryAllocTrace.h b/dbms/src/Common/MemoryAllocTrace.h index fc6303ac3b5..8f3685bc421 100644 --- a/dbms/src/Common/MemoryAllocTrace.h +++ b/dbms/src/Common/MemoryAllocTrace.h @@ -14,9 +14,13 @@ #pragma once +#include + #include namespace DB { std::tuple getAllocDeallocPtr(); -} // namespace DB \ No newline at end of file +bool process_mem_usage(double & resident_set, Int64 & cur_proc_num_threads, UInt64 & cur_virt_size); +std::tuple process_mem_usage(); +} // namespace DB diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index 5e32ad0f925..7bd8cf2f261 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,7 @@ #include #endif +std::atomic tranquil_time_rss; namespace CurrentMetrics { @@ -955,10 +957,25 @@ int Server::main(const std::vector & /*args*/) /// Create TMTContext auto cluster_config = getClusterConfig(global_context->getSecurityConfig(), storage_config.api_version, log); global_context->createTMTContext(raft_config, std::move(cluster_config)); - proxy_machine.initKVStore( - global_context->getTMTContext(), - store_ident, - settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity)); + + // Must be executed before restore data. + // Get the memory usage of tranquil time. + auto [resident_set, cur_proc_num_threads, cur_virt_size] = process_mem_usage(); + UNUSED(cur_proc_num_threads); + UNUSED(cur_virt_size); + tranquil_time_rss = static_cast(resident_set); + + auto limit = settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity); + LOG_INFO( + log, + "Global memory status: computed_limit {} tranquil_time_rss {}, cur_virt_size {}, capacity {}", + limit, + tranquil_time_rss, + cur_virt_size, + server_info.memory_info.capacity); + if (limit == 0) + limit = server_info.memory_info.capacity * 0.8; + proxy_machine.initKVStore(global_context->getTMTContext(), store_ident, limit); global_context->getTMTContext().reloadConfig(config()); // setup the kv cluster for disagg compute node fetching config diff --git a/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp b/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp index 79884e34beb..a3441493664 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp @@ -222,14 +222,17 @@ bool KVStore::canFlushRegionDataImpl( LOG_INFO( log, "{} flush region due to tryFlushRegionData, index {} term {} truncated_index {} truncated_term {}" - " gap {}/{}", + " gap {}/{} table_size {} table_id={} keyspace_id={}", curr_region.toString(false), index, term, truncated_index, truncated_term, current_applied_gap, - gap_threshold); + gap_threshold, + curr_region_ptr->getRegionTableSize(), + curr_region_ptr->getMappedTableID(), + curr_region_ptr->getKeyspaceID()); GET_METRIC(tiflash_raft_region_flush_bytes, type_flushed).Observe(size_bytes); return forceFlushRegionDataImpl(curr_region, try_until_succeed, tmt, region_task_lock, index, term); } diff --git a/dbms/src/Storages/KVStore/ProxyStateMachine.h b/dbms/src/Storages/KVStore/ProxyStateMachine.h index 49ede3b9440..157a1e6e44c 100644 --- a/dbms/src/Storages/KVStore/ProxyStateMachine.h +++ b/dbms/src/Storages/KVStore/ProxyStateMachine.h @@ -281,18 +281,19 @@ struct ProxyStateMachine std::optional & store_ident, size_t memory_limit) { + auto kvstore = tmt_context.getKVStore(); if (store_ident) { // Many service would depends on `store_id` when disagg is enabled. // setup the store_id restored from store_ident ASAP // FIXME: (bootstrap) we should bootstrap the tiflash node more early! - auto kvstore = tmt_context.getKVStore(); metapb::Store store_meta; store_meta.set_id(store_ident->store_id()); store_meta.set_node_state(metapb::NodeState::Preparing); kvstore->setStore(store_meta); - kvstore->setKVStoreMemoryLimit(memory_limit); } + kvstore->setKVStoreMemoryLimit(memory_limit); + LOG_INFO(log, "Set KVStore memory limit {}", memory_limit); } /// Restore TMTContext, including KVStore and RegionTable. diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index f4c124586ad..a52ed33b1e9 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -29,6 +29,7 @@ #include extern std::atomic real_rss; +extern std::atomic tranquil_time_rss; namespace DB { @@ -410,15 +411,18 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { // If there are data flow in, we will check if the memory is exhaused. auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); - auto current = real_rss.load(); + size_t current = real_rss.load() > 0 ? real_rss.load() : 0; + if likely (limit == 0 || current == 0) + return; /// Region management such as split/merge doesn't change the memory consumed by a table in KVStore. /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. /// The only cases memory is increased in a table is inserting kv pairs and applying snaps. /// So, we only print once for a table, until one memory reduce event will happen. - if unlikely (limit > 0 && current > 0 && static_cast(current) >= limit) + if unlikely (current >= limit * 0.9) { auto table_size = getRegionTableSize(); - if (table_size > 0.5 * current) + auto grown_memory = current > tranquil_time_rss ? current - tranquil_time_rss : 0; + if (grown_memory && table_size > grown_memory * 0.3) { if (!setRegionTableWarned(true)) { @@ -428,9 +432,12 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) #endif LOG_INFO( log, - "Memory limit exceeded, current={} limit={} table_id={} keyspace_id={} region_id={} from={}", + "Memory limit exceeded, current={} limit={} limit_size={} table_size={} table_id={} keyspace_id={} " + "region_id={} from={}", current, limit, + grown_memory * 0.3, + table_size, mapped_table_id, keyspace_id, id(), From 9e4cc5f90b715a581aa7dcb558d634956663da43 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 11:01:55 +0800 Subject: [PATCH 35/46] reduce Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Region.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index a52ed33b1e9..cf10a6a0e58 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -422,7 +422,7 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { auto table_size = getRegionTableSize(); auto grown_memory = current > tranquil_time_rss ? current - tranquil_time_rss : 0; - if (grown_memory && table_size > grown_memory * 0.3) + if (grown_memory && table_size > grown_memory * 0.15) { if (!setRegionTableWarned(true)) { From e6ef28f627f9fa7b93b540cf8c218ab8301cb728 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 11:43:18 +0800 Subject: [PATCH 36/46] fix typo Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Region.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index cf10a6a0e58..ebe1fed6a94 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -436,7 +436,7 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) "region_id={} from={}", current, limit, - grown_memory * 0.3, + grown_memory * 0.15, table_size, mapped_table_id, keyspace_id, From 1cbc1e527383a276ce631220e83efefe20757d83 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 11:45:42 +0800 Subject: [PATCH 37/46] limit for 10GiB Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Region.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index ebe1fed6a94..ae5225a05df 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -422,7 +422,9 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) { auto table_size = getRegionTableSize(); auto grown_memory = current > tranquil_time_rss ? current - tranquil_time_rss : 0; - if (grown_memory && table_size > grown_memory * 0.15) + // 15% of the total non-tranquil-time memory, but not exceed 10GB. + auto table_memory_limit = std::min(grown_memory * 0.15, 10 * 1024 * 1024 * 1024); + if (grown_memory && table_size > table_memory_limit) { if (!setRegionTableWarned(true)) { @@ -432,11 +434,11 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) #endif LOG_INFO( log, - "Memory limit exceeded, current={} limit={} limit_size={} table_size={} table_id={} keyspace_id={} " + "Memory limit exceeded, current={} limit={} table_limit={} table_size={} table_id={} keyspace_id={} " "region_id={} from={}", current, limit, - grown_memory * 0.15, + table_memory_limit, table_size, mapped_table_id, keyspace_id, From 9a828fa1bcd215d27584000648c1036cac143027 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 11:58:14 +0800 Subject: [PATCH 38/46] fmt Signed-off-by: Calvin Neo --- dbms/src/Storages/KVStore/Region.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index ae5225a05df..34f8b04cf9c 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -434,7 +434,8 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) #endif LOG_INFO( log, - "Memory limit exceeded, current={} limit={} table_limit={} table_size={} table_id={} keyspace_id={} " + "Memory limit exceeded, current={} limit={} table_limit={} table_size={} table_id={} " + "keyspace_id={} " "region_id={} from={}", current, limit, From f390c33a8863da9142615059170f17f581310e45 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 14:13:43 +0800 Subject: [PATCH 39/46] Update dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp Co-authored-by: JaySon --- dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp b/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp index a3441493664..0aaefb8aab4 100644 --- a/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp +++ b/dbms/src/Storages/KVStore/MultiRaft/Persistence.cpp @@ -222,7 +222,7 @@ bool KVStore::canFlushRegionDataImpl( LOG_INFO( log, "{} flush region due to tryFlushRegionData, index {} term {} truncated_index {} truncated_term {}" - " gap {}/{} table_size {} table_id={} keyspace_id={}", + " gap {}/{} table_in_mem_size={} table_id={} keyspace={}", curr_region.toString(false), index, term, From aa9fc0e78a8277fa828772307bb603af4e22f454 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 14:13:54 +0800 Subject: [PATCH 40/46] Update dbms/src/Storages/KVStore/Region.cpp Co-authored-by: JaySon --- dbms/src/Storages/KVStore/Region.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 34f8b04cf9c..12c4af0dcd8 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -434,8 +434,8 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) #endif LOG_INFO( log, - "Memory limit exceeded, current={} limit={} table_limit={} table_size={} table_id={} " - "keyspace_id={} " + "Memory limit exceeded, current={} limit={} table_limit={} table_in_mem_size={} table_id={} " + "keyspace={} " "region_id={} from={}", current, limit, From 83ad2de08bcb65dfbf15206f5036c9d0cc8ce2b5 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 14:15:10 +0800 Subject: [PATCH 41/46] Update dbms/src/Server/Server.cpp Co-authored-by: JaySon --- dbms/src/Server/Server.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index 7bd8cf2f261..4872c8c0b32 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -965,17 +965,18 @@ int Server::main(const std::vector & /*args*/) UNUSED(cur_virt_size); tranquil_time_rss = static_cast(resident_set); - auto limit = settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity); + auto kvs_watermark = settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity); + if (kvs_watermark == 0) + kvs_watermark = server_info.memory_info.capacity * 0.8; LOG_INFO( log, - "Global memory status: computed_limit {} tranquil_time_rss {}, cur_virt_size {}, capacity {}", + "Global memory status: kvstore_high_watermark={} tranquil_time_rss={} cur_virt_size={} capacity={}", limit, tranquil_time_rss, cur_virt_size, server_info.memory_info.capacity); - if (limit == 0) - limit = server_info.memory_info.capacity * 0.8; - proxy_machine.initKVStore(global_context->getTMTContext(), store_ident, limit); + + proxy_machine.initKVStore(global_context->getTMTContext(), store_ident, kvs_watermark); global_context->getTMTContext().reloadConfig(config()); // setup the kv cluster for disagg compute node fetching config From c98f611990cdce393c3442de1c5fbf1cb2121fc7 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 14:15:19 +0800 Subject: [PATCH 42/46] Update dbms/src/Storages/KVStore/Region.cpp Co-authored-by: JaySon --- dbms/src/Storages/KVStore/Region.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 12c4af0dcd8..d786635ac99 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -423,7 +423,7 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) auto table_size = getRegionTableSize(); auto grown_memory = current > tranquil_time_rss ? current - tranquil_time_rss : 0; // 15% of the total non-tranquil-time memory, but not exceed 10GB. - auto table_memory_limit = std::min(grown_memory * 0.15, 10 * 1024 * 1024 * 1024); + auto table_memory_limit = std::min(grown_memory * 0.15, 10 * 1024ULL * 1024 * 1024); if (grown_memory && table_size > table_memory_limit) { if (!setRegionTableWarned(true)) From 50a93c66b0ef84e8858df5893d73064a6ed9c276 Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 14:15:29 +0800 Subject: [PATCH 43/46] Update dbms/src/Storages/KVStore/Region.cpp Co-authored-by: JaySon --- dbms/src/Storages/KVStore/Region.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index d786635ac99..43b611f282f 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -412,7 +412,7 @@ void Region::maybeWarnMemoryLimitByTable(TMTContext & tmt, const char * from) // If there are data flow in, we will check if the memory is exhaused. auto limit = tmt.getKVStore()->getKVStoreMemoryLimit(); size_t current = real_rss.load() > 0 ? real_rss.load() : 0; - if likely (limit == 0 || current == 0) + if unlikely (limit == 0 || current == 0) return; /// Region management such as split/merge doesn't change the memory consumed by a table in KVStore. /// The only cases memory is reduced in a table is removing regions, applying snaps and commiting txns. From 44021e7d65bc36641fc1b23ab2a3516fb7c30f7c Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 15:40:55 +0800 Subject: [PATCH 44/46] Update dbms/src/Server/Server.cpp Co-authored-by: jinhelin --- dbms/src/Server/Server.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index 4872c8c0b32..507cfb6be5b 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -960,9 +960,7 @@ int Server::main(const std::vector & /*args*/) // Must be executed before restore data. // Get the memory usage of tranquil time. - auto [resident_set, cur_proc_num_threads, cur_virt_size] = process_mem_usage(); - UNUSED(cur_proc_num_threads); - UNUSED(cur_virt_size); + auto resident_set = std::get<0>(process_mem_usage()); tranquil_time_rss = static_cast(resident_set); auto kvs_watermark = settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity); From 11a46bf0c1985b7b4c9b78798567bfc21e778eae Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 16:20:11 +0800 Subject: [PATCH 45/46] fix cling Signed-off-by: Calvin Neo --- dbms/src/Server/Server.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index 507cfb6be5b..a5e52eb551b 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -960,7 +960,8 @@ int Server::main(const std::vector & /*args*/) // Must be executed before restore data. // Get the memory usage of tranquil time. - auto resident_set = std::get<0>(process_mem_usage()); + auto [resident_set, cur_proc_num_threads, cur_virt_size] = process_mem_usage(); + UNUSED(cur_proc_num_threads); tranquil_time_rss = static_cast(resident_set); auto kvs_watermark = settings.max_memory_usage_for_all_queries.getActualBytes(server_info.memory_info.capacity); @@ -969,7 +970,7 @@ int Server::main(const std::vector & /*args*/) LOG_INFO( log, "Global memory status: kvstore_high_watermark={} tranquil_time_rss={} cur_virt_size={} capacity={}", - limit, + kvs_watermark, tranquil_time_rss, cur_virt_size, server_info.memory_info.capacity); From d5ba72a29d1406a930a867e514bc3e21e2de18ac Mon Sep 17 00:00:00 2001 From: Calvin Neo Date: Mon, 17 Feb 2025 16:56:29 +0800 Subject: [PATCH 46/46] fix Signed-off-by: Calvin Neo --- dbms/src/Server/Server.cpp | 2 +- dbms/src/Storages/KVStore/Region.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dbms/src/Server/Server.cpp b/dbms/src/Server/Server.cpp index a5e52eb551b..0833b89465b 100644 --- a/dbms/src/Server/Server.cpp +++ b/dbms/src/Server/Server.cpp @@ -108,7 +108,7 @@ #include #endif -std::atomic tranquil_time_rss; +extern std::atomic tranquil_time_rss; namespace CurrentMetrics { diff --git a/dbms/src/Storages/KVStore/Region.cpp b/dbms/src/Storages/KVStore/Region.cpp index 43b611f282f..41dddfd2ed5 100644 --- a/dbms/src/Storages/KVStore/Region.cpp +++ b/dbms/src/Storages/KVStore/Region.cpp @@ -29,7 +29,7 @@ #include extern std::atomic real_rss; -extern std::atomic tranquil_time_rss; +std::atomic tranquil_time_rss; namespace DB {