diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index 1748e84776..cdbdfe2c8b 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -13360,8 +13360,8 @@ int ObLogPlan::create_for_update_plan(ObLogicalOperator *&top, skip_locked, lock_rownum))) { LOG_WARN("failed to allocate delete as top", K(ret)); - } else { - optimizer_context_.set_for_update(); + } else if (!skip_locked) { + optimizer_context_.set_no_skip_for_update(); } return ret; } diff --git a/src/sql/optimizer/ob_optimizer_context.h b/src/sql/optimizer/ob_optimizer_context.h index adf3a84428..4d6436e416 100644 --- a/src/sql/optimizer/ob_optimizer_context.h +++ b/src/sql/optimizer/ob_optimizer_context.h @@ -224,7 +224,7 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, aggregation_optimization_settings_(0), query_ctx_(query_ctx), nested_sql_flags_(0), - has_for_update_(false), + has_no_skip_for_update_(false), has_var_assign_(false), is_var_assign_only_in_root_stmt_(false), failed_ds_tab_list_(), @@ -582,8 +582,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, bool contain_nested_sql() const { return nested_sql_flags_ > 0; } //use nested sql can't in online DDL session bool contain_user_nested_sql() const { return nested_sql_flags_ > 0 && !is_online_ddl_; } - void set_for_update() { has_for_update_ = true; } - bool has_for_update() { return has_for_update_;}; + inline void set_no_skip_for_update() { has_no_skip_for_update_ = true; } + inline bool has_no_skip_for_update() const { return has_no_skip_for_update_; } inline bool has_var_assign() { return has_var_assign_; } inline void set_has_var_assign(bool v) { has_var_assign_ = v; } inline bool is_var_assign_only_in_root_stmt() { return is_var_assign_only_in_root_stmt_; } @@ -672,7 +672,7 @@ private: int8_t has_cursor_expression_ : 1; //this sql has cursor expression }; }; - bool has_for_update_; + bool has_no_skip_for_update_; bool has_var_assign_; bool is_var_assign_only_in_root_stmt_; //record the dynamic sampling falied table list, avoid repeated dynamic sampling. diff --git a/src/sql/optimizer/ob_select_log_plan.cpp b/src/sql/optimizer/ob_select_log_plan.cpp index a40007bffc..f241018f1c 100644 --- a/src/sql/optimizer/ob_select_log_plan.cpp +++ b/src/sql/optimizer/ob_select_log_plan.cpp @@ -4545,8 +4545,11 @@ int ObSelectLogPlan::allocate_plan_top() // allocate root exchange if (OB_SUCC(ret) && is_final_root_plan()) { - // allocate material if there is for update. - if (optimizer_context_.has_for_update() && OB_FAIL(candi_allocate_for_update_material())) { + // allocate material if there is for update without skip locked. + // FOR UPDATE SKIP LOCKED does not need SQL-level retry, hence we don't need a MATERIAL to + // block the output. + if (optimizer_context_.has_no_skip_for_update() + && OB_FAIL(candi_allocate_for_update_material())) { LOG_WARN("failed to allocate material", K(ret)); //allocate temp-table transformation if needed. } else if (!get_optimizer_context().get_temp_table_infos().empty() &&