This is an automated email from the ASF dual-hosted git repository.
liaoxin01 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7dc90d1a1d5 [fix](cloud) Respect recycle type when deleting partial
update rowsets (#68594)
7dc90d1a1d5 is described below
commit 7dc90d1a1d504e893fa4ea81ca7c939ca3e70b9e
Author: Yixuan Wang <[email protected]>
AuthorDate: Wed Sep 30 09:49:54 2026 +0800
[fix](cloud) Respect recycle type when deleting partial update rowsets
(#68594)
### What problem does this PR solve?
Problem Summary:
BEGIN_PARTIAL_UPDATE rowsets use prefix deletion without considering
their recycle type or packed slice locations.
This causes unnecessary listing for completed rowsets, while packed
PREPARE rowsets bypass packed file reference-count cleanup.
Pass RecycleRowsetPB::Type directly to delete_rowset_data and group
recycle batches by type. Restrict partial-update prefix deletion to
unpacked PREPARE rowsets. Recycle packed PREPARE rowsets through
reference-count cleanup, including after transaction or job abort.
Preserve existing behavior for temporary rowsets and other callers.
### Release note
Avoid unnecessary prefix listing when recycling completed or packed
partial-update rowsets, and correctly reclaim packed PREPARE rowsets.
### Check List (For Author)
- Test: Unit Test — added PREPARE/COMPACT, packed/unpacked, and
abort-before-delete coverage. Current run fails because the PREPARE
condition is missing; restore it and rerun before submission.
- Behavior changed: Yes, partial-update recycle rowsets use prefix
deletion only for unpacked PREPARE rowsets.
- Does this need documentation: N
---
cloud/src/recycler/recycler.cpp | 2 +-
cloud/test/recycler_test.cpp | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/cloud/src/recycler/recycler.cpp b/cloud/src/recycler/recycler.cpp
index 803812e2c95..d1faf2acf6b 100644
--- a/cloud/src/recycler/recycler.cpp
+++ b/cloud/src/recycler/recycler.cpp
@@ -4653,7 +4653,7 @@ int InstanceRecycler::delete_rowset_data(
continue;
}
}
- if (rs.rowset_state() == RowsetStatePB::BEGIN_PARTIAL_UPDATE) {
+ if (rs.rowset_state() == RowsetStatePB::BEGIN_PARTIAL_UPDATE &&
!is_formal_rowset) {
// if rowset state is RowsetStatePB::BEGIN_PARTIAL_UPDATE, the
number of segments data
// may be larger than num_segments field in RowsetMeta, so we need
to delete the rowset's data by prefix
rowsets_delete_by_prefix.emplace_back(rs.resource_id(), tablet_id,
rs.rowset_id_v2());
diff --git a/cloud/test/recycler_test.cpp b/cloud/test/recycler_test.cpp
index 3946f9bc07c..467c4b57bb2 100644
--- a/cloud/test/recycler_test.cpp
+++ b/cloud/test/recycler_test.cpp
@@ -7352,6 +7352,40 @@ TEST(RecyclerTest, delete_rowset_data) {
}
}
+TEST(RecyclerTest, delete_partial_update_rowset_data_by_recycling_state) {
+ auto txn_kv = std::make_shared<MemTxnKv>();
+ ASSERT_EQ(txn_kv->init(), 0);
+
+ constexpr auto resource_id = "partial_update_delete";
+ InstanceInfoPB instance;
+ instance.set_instance_id(instance_id);
+ instance.add_obj_info()->set_id(resource_id);
+ InstanceRecycler recycler(txn_kv, instance, thread_group,
+ std::make_shared<TxnLazyCommitter>(txn_kv));
+ ASSERT_EQ(recycler.init(), 0);
+ auto accessor = recycler.accessor_map_.at(resource_id);
+
+ doris::TabletSchemaCloudPB schema;
+ schema.set_schema_version(1);
+ auto rowset = create_rowset(resource_id, 10001, 10002, 1, schema,
+ RowsetStatePB::BEGIN_PARTIAL_UPDATE);
+ const auto segment = segment_path(rowset.tablet_id(),
rowset.rowset_id_v2(), 0);
+ const auto extra_segment = segment_path(rowset.tablet_id(),
rowset.rowset_id_v2(), 1);
+ std::map<std::string, doris::RowsetMetaCloudPB> rowsets
{{rowset.rowset_id_v2(), rowset}};
+
+ for (auto type : {RowsetRecyclingState::FORMAL_ROWSET,
RowsetRecyclingState::TMP_ROWSET}) {
+ SCOPED_TRACE(static_cast<int>(type));
+ ASSERT_EQ(accessor->put_file(segment, ""), 0);
+ ASSERT_EQ(accessor->put_file(extra_segment, ""), 0);
+
+ RecyclerMetricsContext metrics_context;
+ ASSERT_EQ(recycler.delete_rowset_data(rowsets, type, metrics_context),
0);
+ EXPECT_EQ(accessor->exists(segment), 1);
+ EXPECT_EQ(accessor->exists(extra_segment),
+ type == RowsetRecyclingState::FORMAL_ROWSET ? 0 : 1);
+ }
+}
+
TEST(RecyclerTest, delete_v2_inverted_index_with_segment_list) {
auto txn_kv = std::make_shared<MemTxnKv>();
ASSERT_EQ(txn_kv->init(), 0);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]