diff --git a/deps/oblib/src/common/ob_common_types.h b/deps/oblib/src/common/ob_common_types.h index 988c131be4..a638e759cf 100644 --- a/deps/oblib/src/common/ob_common_types.h +++ b/deps/oblib/src/common/ob_common_types.h @@ -49,7 +49,7 @@ struct ObQueryFlag #define OBSF_BIT_IS_SSTABLE_CUT 1 #define OBSF_BIT_IS_SHOW_SEED 1 #define OBSF_BIT_SKIP_READ_LOB 1 -#define OBSF_BIT_IS_LOOKUP 1 +#define OBSF_BIT_IS_LOOKUP_FOR_4377 1 #define OBSF_BIT_RESERVED 31 static const uint64_t OBSF_MASK_SCAN_ORDER = (0x1UL << OBSF_BIT_SCAN_ORDER) - 1; @@ -133,7 +133,7 @@ struct ObQueryFlag uint64_t is_sstable_cut_ : OBSF_BIT_IS_SSTABLE_CUT; //0:sstable no need cut, 1: sstable need cut uint64_t is_show_seed_ : OBSF_BIT_IS_SHOW_SEED; uint64_t skip_read_lob_ : OBSF_BIT_SKIP_READ_LOB; - uint64_t is_lookup_ : OBSF_BIT_IS_LOOKUP; + uint64_t is_lookup_for_4377_ : OBSF_BIT_IS_LOOKUP_FOR_4377; uint64_t reserved_ : OBSF_BIT_RESERVED; }; }; @@ -185,7 +185,7 @@ struct ObQueryFlag inline bool is_query_stat() const { return query_stat_; } inline bool is_mysql_mode() const { return sql_mode_ == MysqlMode; } inline bool is_read_latest() const { return read_latest_; } - inline bool is_lookup() const { return is_lookup_; } + inline bool is_lookup_for_4377() const { return is_lookup_for_4377_; } inline bool is_prewarm() const { return prewarm_; } inline bool is_index_invalid() const { return index_invalid_; } inline bool is_use_row_cache() const { return !is_whole_macro_scan() && use_row_cache_ == UseCache; } @@ -249,7 +249,7 @@ struct ObQueryFlag "is_large_query", is_large_query_, "is_sstable_cut", is_sstable_cut_, "skip_read_lob", skip_read_lob_, - "is_lookup", is_lookup_, + "is_lookup_for_4377", is_lookup_for_4377_, "reserved", reserved_); OB_UNIS_VERSION(1); }; diff --git a/src/sql/engine/table/ob_table_scan_op.cpp b/src/sql/engine/table/ob_table_scan_op.cpp index 51c0d0f3dc..8cc4bc3b91 100644 --- a/src/sql/engine/table/ob_table_scan_op.cpp +++ b/src/sql/engine/table/ob_table_scan_op.cpp @@ -880,7 +880,7 @@ OB_INLINE int ObTableScanOp::init_das_scan_rtdef(const ObDASScanCtDef &das_ctdef if (MY_SPEC.batch_scan_flag_ || is_lookup) { das_rtdef.scan_flag_.scan_order_ = ObQueryFlag::KeepOrder; } - das_rtdef.scan_flag_.is_lookup_ = is_lookup; + das_rtdef.scan_flag_.is_lookup_for_4377_ = is_lookup; das_rtdef.need_check_output_datum_ = MY_SPEC.need_check_output_datum_; das_rtdef.sql_mode_ = my_session->get_sql_mode(); das_rtdef.stmt_allocator_.set_alloc(&das_ref_.get_das_alloc()); diff --git a/src/storage/access/ob_multiple_get_merge.cpp b/src/storage/access/ob_multiple_get_merge.cpp index 83f055b0a3..6ab0fdad84 100644 --- a/src/storage/access/ob_multiple_get_merge.cpp +++ b/src/storage/access/ob_multiple_get_merge.cpp @@ -227,6 +227,23 @@ int ObMultipleGetMerge::inner_get_next_row(ObDatumRow &row) STORAGE_LOG(DEBUG, "Success to merge get row, ", KP(this), K(fuse_row), K(get_row_range_idx_), K(fuse_row.group_idx_)); } break; + } else { + // When the index lookups the rowkeys from the main table, it should exists + // and if we find that it does not exist, there must be an anomaly + if (GCONF.enable_defensive_check() + && access_ctx_->query_flag_.is_lookup_for_4377()) { + ret = OB_ERR_DEFENSIVE_CHECK; + ObString func_name = ObString::make_string("[index lookup]ObMultipleGetMerge::inner_get_next_row"); + LOG_USER_ERROR(OB_ERR_DEFENSIVE_CHECK, func_name.length(), func_name.ptr()); + LOG_DBA_ERROR(OB_ERR_DEFENSIVE_CHECK, "msg", "Fatal Error!!! Catch a defensive error!", K(ret), + K(rowkeys_), + K(get_row_range_idx_ - 1), + K(rowkeys_->at(get_row_range_idx_ - 1)), + K(fuse_row), + KPC(access_ctx_->store_ctx_)); + dump_table_statistic_for_4377(); + dump_tx_statistic_for_4377(access_ctx_->store_ctx_); + } } } } diff --git a/src/storage/access/ob_multiple_merge.cpp b/src/storage/access/ob_multiple_merge.cpp index 93e26e329b..ceff87dda9 100644 --- a/src/storage/access/ob_multiple_merge.cpp +++ b/src/storage/access/ob_multiple_merge.cpp @@ -29,6 +29,7 @@ #include "sql/engine/expr/ob_expr_lob_utils.h" #include "storage/ob_tenant_tablet_stat_mgr.h" #include "storage/tablet/ob_tablet.h" +#include "storage/tx/ob_trans_part_ctx.h" namespace oceanbase { @@ -1388,5 +1389,40 @@ void ObMultipleMerge::reuse_lob_locator() lob_reader_.reuse(); } +void ObMultipleMerge::dump_tx_statistic_for_4377(ObStoreCtx *store_ctx) +{ + int ret = OB_SUCCESS; + LOG_ERROR("==================== Start trx info ===================="); + + if (NULL != store_ctx) { + store_ctx->force_print_trace_log(); + if (NULL != store_ctx->mvcc_acc_ctx_.tx_ctx_) { + LOG_ERROR("Dump trx info", K(ret), KPC(store_ctx->mvcc_acc_ctx_.tx_ctx_)); + if (NULL != store_ctx->mvcc_acc_ctx_.mem_ctx_) { + // TODO(handora.qc): Shall we dump the row? + store_ctx->mvcc_acc_ctx_.mem_ctx_->print_callbacks(); + } + } else { + LOG_ERROR("no some of the trx info", K(ret), KPC(store_ctx)); + } + } else { + LOG_ERROR("no trx info completely", K(ret)); + } + + LOG_ERROR("==================== End trx info ===================="); +} + +void ObMultipleMerge::dump_table_statistic_for_4377() +{ + int ret = OB_SUCCESS; + int64_t table_idx = -1; + + LOG_ERROR("==================== Start table info ===================="); + for (table_idx = tables_.count() - 1; table_idx >= 0; --table_idx) { + ObITable *table = tables_.at(table_idx); + LOG_ERROR("Dump table info", K(ret), KPC(table)); + } + LOG_ERROR("==================== End table info ===================="); +} } } diff --git a/src/storage/access/ob_multiple_merge.h b/src/storage/access/ob_multiple_merge.h index 795cde559a..ea03180e0e 100644 --- a/src/storage/access/ob_multiple_merge.h +++ b/src/storage/access/ob_multiple_merge.h @@ -82,6 +82,9 @@ protected: blocksstable::ObDatumRow &projected_row); void reset_iter_array(); void reuse_iter_array(); + void dump_tx_statistic_for_4377(ObStoreCtx *store_ctx); + void dump_table_statistic_for_4377(); + private: int get_next_normal_row(blocksstable::ObDatumRow *&row); int get_next_normal_rows(int64_t &count, int64_t capacity); diff --git a/src/storage/access/ob_single_merge.cpp b/src/storage/access/ob_single_merge.cpp index 11477b170b..7773927521 100644 --- a/src/storage/access/ob_single_merge.cpp +++ b/src/storage/access/ob_single_merge.cpp @@ -352,6 +352,26 @@ int ObSingleMerge::inner_get_next_row(ObDatumRow &row) access_ctx_->defensive_check_record_.reset(); */ #endif + + // When the index lookups the rowkeys from the main table, it should exists + // and if we find that it does not exist, there must be an anomaly + if (GCONF.enable_defensive_check() + && access_ctx_->query_flag_.is_lookup_for_4377() + && OB_ITER_END == ret) { + ret = OB_ERR_DEFENSIVE_CHECK; + ObString func_name = ObString::make_string("[index lookup]ObSingleMerge::inner_get_next_row"); + LOG_USER_ERROR(OB_ERR_DEFENSIVE_CHECK, func_name.length(), func_name.ptr()); + LOG_DBA_ERROR(OB_ERR_DEFENSIVE_CHECK, "msg", "Fatal Error!!! Catch a defensive error!", K(ret), + K(have_uncommited_row), + K(enable_fuse_row_cache), + K(read_snapshot_version), + KPC(read_info), + KPC(access_ctx_->store_ctx_), + K(tables_)); + dump_table_statistic_for_4377(); + dump_tx_statistic_for_4377(access_ctx_->store_ctx_); + } + rowkey_ = NULL; } else { ret = OB_ITER_END;