This is an automated email from the ASF dual-hosted git repository.

eldenmoon pushed a commit to branch cs_opt_version-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/cs_opt_version-3.1 by this 
push:
     new 795dc83b0db fix dead lock (#58617)
795dc83b0db is described below

commit 795dc83b0dbf57e82a7b0e28821193edf05e8eeb
Author: lihangyu <[email protected]>
AuthorDate: Tue Dec 2 16:01:03 2025 +0800

    fix dead lock (#58617)
---
 .../segment_v2/variant/variant_column_reader.cpp   | 58 +++++++++++++---------
 .../segment_v2/variant/variant_column_reader.h     |  5 ++
 2 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/be/src/olap/rowset/segment_v2/variant/variant_column_reader.cpp 
b/be/src/olap/rowset/segment_v2/variant/variant_column_reader.cpp
index f225a34834f..a124a77def1 100644
--- a/be/src/olap/rowset/segment_v2/variant/variant_column_reader.cpp
+++ b/be/src/olap/rowset/segment_v2/variant/variant_column_reader.cpp
@@ -80,6 +80,10 @@ bool VariantColumnReader::exist_in_sparse_column(
 
 bool VariantColumnReader::is_exceeded_sparse_column_limit() const {
     std::shared_lock<std::shared_mutex> lock(_subcolumns_meta_mutex);
+    return _is_exceeded_sparse_column_limit_unlocked();
+}
+
+bool VariantColumnReader::_is_exceeded_sparse_column_limit_unlocked() const {
     bool exceeded_sparse_column_limit = 
!_statistics->sparse_column_non_null_size.empty() &&
                                         
_statistics->sparse_column_non_null_size.size() >=
                                                 
_variant_sparse_column_statistics_size;
@@ -275,7 +279,7 @@ Status 
VariantColumnReader::_build_read_plan_flat_leaves(ReadPlan* plan,
     bool existed_in_sparse_column =
             !_statistics->sparse_column_non_null_size.empty() &&
             
_statistics->sparse_column_non_null_size.contains(relative_path.get_path());
-    bool exceeded_sparse_column_limit = is_exceeded_sparse_column_limit();
+    bool exceeded_sparse_column_limit = 
_is_exceeded_sparse_column_limit_unlocked();
 
     const auto* node = plan->node;
     if (!node) {
@@ -331,6 +335,11 @@ Status 
VariantColumnReader::_build_read_plan_flat_leaves(ReadPlan* plan,
 
 bool VariantColumnReader::has_prefix_path(const vectorized::PathInData& 
relative_path) const {
     std::shared_lock<std::shared_mutex> lock(_subcolumns_meta_mutex);
+    return _has_prefix_path_unlocked(relative_path);
+}
+
+bool VariantColumnReader::_has_prefix_path_unlocked(
+        const vectorized::PathInData& relative_path) const {
     if (relative_path.empty()) {
         return true;
     }
@@ -386,11 +395,32 @@ Status 
VariantColumnReader::new_iterator(ColumnIteratorUPtr* iterator,
 Status VariantColumnReader::_build_read_plan(ReadPlan* plan, const 
TabletColumn& target_col,
                                              const StorageReadOptions* opt,
                                              ColumnReaderCache* 
column_reader_cache) {
-    std::shared_lock<std::shared_mutex> lock(_subcolumns_meta_mutex);
     // root column use unique id, leaf column use parent_unique_id
     int32_t col_uid =
             target_col.unique_id() >= 0 ? target_col.unique_id() : 
target_col.parent_unique_id();
     auto relative_path = target_col.path_info_ptr()->copy_pop_front();
+
+    // If the variant column has extracted columns and is a compaction reader, 
then read flat leaves
+    // Otherwise read hierarchical data, since the variant subcolumns are 
flattened in
+    // schema_util::get_compaction_schema. For checksum reader, we need to 
read flat leaves to
+    // get the correct data if has extracted columns.
+    auto need_read_flat_leaves = [](const StorageReadOptions* opts) {
+        return opts != nullptr && opts->tablet_schema != nullptr &&
+               std::ranges::any_of(
+                       opts->tablet_schema->columns(),
+                       [](const auto& column) { return 
column->is_extracted_column(); }) &&
+               (is_compaction_reader_type(opts->io_ctx.reader_type) ||
+                opts->io_ctx.reader_type == ReaderType::READER_CHECKSUM);
+    };
+
+    // Flat-leaf compaction/checksum mode: delegate to dedicated planner which 
handles locking
+    // and external meta loading internally.
+    // english only in comments
+    if (need_read_flat_leaves(opt)) {
+        return _build_read_plan_flat_leaves(plan, target_col, opt, 
column_reader_cache);
+    }
+
+    std::shared_lock<std::shared_mutex> lock(_subcolumns_meta_mutex);
     const auto* root = _subcolumns_meta_info->get_root();
     const auto* node =
             target_col.has_path_info() ? 
_subcolumns_meta_info->find_exact(relative_path) : nullptr;
@@ -409,33 +439,15 @@ Status VariantColumnReader::_build_read_plan(ReadPlan* 
plan, const TabletColumn&
 
     // Otherwise the prefix is not exist and the sparse column size is reached 
limit
     // which means the path maybe exist in sparse_column
-    bool exceeded_sparse_column_limit = is_exceeded_sparse_column_limit();
-
-    // If the variant column has extracted columns and is a compaction reader, 
then read flat leaves
-    // Otherwise read hierarchical data, since the variant subcolumns are 
flattened in
-    // schema_util::get_compaction_schema. For checksum reader, we need to 
read flat leaves to
-    // get the correct data if has extracted columns.
-    auto need_read_flat_leaves = [](const StorageReadOptions* opts) {
-        return opts != nullptr && opts->tablet_schema != nullptr &&
-               std::ranges::any_of(
-                       opts->tablet_schema->columns(),
-                       [](const auto& column) { return 
column->is_extracted_column(); }) &&
-               (is_compaction_reader_type(opts->io_ctx.reader_type) ||
-                opts->io_ctx.reader_type == ReaderType::READER_CHECKSUM);
-    };
+    bool exceeded_sparse_column_limit = 
_is_exceeded_sparse_column_limit_unlocked();
 
     plan->relative_path = relative_path;
     plan->node = node;
     plan->root = root;
 
-    if (need_read_flat_leaves(opt)) {
-        // original path, compaction with wide schema
-        return _build_read_plan_flat_leaves(plan, target_col, opt, 
column_reader_cache);
-    }
-
     // Check if path is prefix, example sparse columns path: a.b.c, a.b.e, 
access prefix: a.b.
     // Or access root path
-    if (has_prefix_path(relative_path)) {
+    if (_has_prefix_path_unlocked(relative_path)) {
         // Example {"b" : {"c":456,"e":7.111}}
         // b.c is sparse column, b.e is subcolumn, so b is both the prefix of 
sparse column and
         // subcolumn
@@ -477,7 +489,7 @@ Status VariantColumnReader::_build_read_plan(ReadPlan* 
plan, const TabletColumn&
             std::shared_ptr<ColumnReader> leaf_column_reader;
             Status st = column_reader_cache->get_path_column_reader(
                     col_uid, relative_path, &leaf_column_reader, opt->stats, 
nullptr);
-            DCHECK(!has_prefix_path(relative_path));
+            DCHECK(!_has_prefix_path_unlocked(relative_path));
             if (st.ok()) {
                 // Try external meta fallback: build a leaf reader on demand 
from externalized meta
                 plan->kind = ReadKind::LEAF;
diff --git a/be/src/olap/rowset/segment_v2/variant/variant_column_reader.h 
b/be/src/olap/rowset/segment_v2/variant/variant_column_reader.h
index b8a98c9ac02..63f32198477 100644
--- a/be/src/olap/rowset/segment_v2/variant/variant_column_reader.h
+++ b/be/src/olap/rowset/segment_v2/variant/variant_column_reader.h
@@ -135,6 +135,11 @@ public:
     bool has_prefix_path(const vectorized::PathInData& relative_path) const;
 
 private:
+    // Internal unlocked helpers. Caller must hold `_subcolumns_meta_mutex` 
when using them.
+    // english only in comments
+    bool _is_exceeded_sparse_column_limit_unlocked() const;
+    bool _has_prefix_path_unlocked(const vectorized::PathInData& 
relative_path) const;
+
     // Describe how a variant sub-path should be read. This is a logical plan 
only and
     // does not create any concrete ColumnIterator.
     enum class ReadKind {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to