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]

Reply via email to