742 lines
36 KiB
C++
742 lines
36 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#ifndef OCEANBASE_STORAGE_OB_PARTITION_STORAGE
|
|
#define OCEANBASE_STORAGE_OB_PARTITION_STORAGE
|
|
|
|
#include "ob_partition_store.h"
|
|
#include "ob_relative_table.h"
|
|
|
|
namespace oceanbase {
|
|
namespace common {
|
|
class ObRowStore;
|
|
}
|
|
namespace share {
|
|
class ObPartitionReplica;
|
|
}
|
|
namespace blocksstable {
|
|
class ObBaseStorageLogger;
|
|
struct ObPartitionMeta;
|
|
struct ObStorageCacheSuite;
|
|
struct MacroBlockId;
|
|
class ObBuildIndexMacroBlockReader;
|
|
class ObBuildIndexMacroBlockWriter;
|
|
} // namespace blocksstable
|
|
namespace memtable {
|
|
class ObMemtable;
|
|
}
|
|
namespace compaction {
|
|
class ObIStoreRowProcessor;
|
|
class ObSStableMergeEstimator;
|
|
class ObBuildIndexParam;
|
|
class ObBuildIndexContext;
|
|
} // namespace compaction
|
|
namespace storageperf {
|
|
template <typename T>
|
|
class ObMultiBlockBench;
|
|
}
|
|
namespace storage {
|
|
class ObIPartitionGroupGuard;
|
|
class ObSSStore;
|
|
class ObBatch;
|
|
class ObPartitionMergeDag;
|
|
class ObMultipleMerge;
|
|
class ObSSTableCtx;
|
|
class ObSSTableSplitCtx;
|
|
class ObSSTableMergeCtx;
|
|
class ObTableScanIterIterator;
|
|
class ObPGMemtableMgr;
|
|
class ObPGStorage;
|
|
class ObTableScanIterator;
|
|
|
|
class ObStoreRowkeyHashFunc {
|
|
public:
|
|
uint64_t operator()(const common::ObStoreRowkey& rowkey, const uint64_t hash)
|
|
{
|
|
return rowkey.murmurhash(hash);
|
|
}
|
|
};
|
|
|
|
struct ObColumnChecksumEntry {
|
|
ObColumnChecksumEntry() : checksum_(0), table_id_(0)
|
|
{}
|
|
ObColumnChecksumEntry(int64_t checksum, int64_t table_id) : checksum_(checksum), table_id_(table_id)
|
|
{}
|
|
int64_t checksum_;
|
|
int64_t table_id_;
|
|
};
|
|
|
|
class ObStorageWriterGuard {
|
|
public:
|
|
int refresh_and_protect_table(ObRelativeTable& relative_table);
|
|
int refresh_and_protect_pg_memtable(ObPGStorage& pg_storage, ObTablesHandle& tables_handle);
|
|
|
|
// called when writing to a specific partition
|
|
ObStorageWriterGuard(
|
|
ObPartitionStore& store, const ObStoreCtx& store_ctx, const bool need_control_mem, const bool is_replay = false)
|
|
: need_control_mem_(need_control_mem),
|
|
is_replay_(is_replay),
|
|
store_(&store),
|
|
store_ctx_(store_ctx),
|
|
memtable_(NULL),
|
|
pg_memtable_mgr_(NULL),
|
|
retry_count_(0),
|
|
last_ts_(0)
|
|
{
|
|
get_writing_throttling_sleep_interval() = 0;
|
|
}
|
|
// called when replay clog of pg
|
|
ObStorageWriterGuard(const ObStoreCtx& store_ctx, ObPGMemtableMgr* pg_memtable_mgr, const bool need_control_mem,
|
|
const bool is_replay = false)
|
|
: need_control_mem_(need_control_mem),
|
|
is_replay_(is_replay),
|
|
store_(NULL),
|
|
store_ctx_(store_ctx),
|
|
memtable_(NULL),
|
|
pg_memtable_mgr_(pg_memtable_mgr),
|
|
retry_count_(0),
|
|
last_ts_(0)
|
|
{
|
|
get_writing_throttling_sleep_interval() = 0;
|
|
}
|
|
~ObStorageWriterGuard();
|
|
ObStorageWriterGuard(const ObStorageWriterGuard&) = delete;
|
|
ObStorageWriterGuard& operator=(const ObStorageWriterGuard&) = delete;
|
|
|
|
private:
|
|
bool need_to_refresh_table(ObTablesHandle& tables_handle);
|
|
bool check_if_need_log();
|
|
void reset();
|
|
|
|
private:
|
|
static const int64_t LOG_INTERVAL_US = 30 * 1000 * 1000;
|
|
static const int64_t GET_TS_INTERVAL = 10 * 1000;
|
|
|
|
private:
|
|
const bool need_control_mem_;
|
|
const bool is_replay_;
|
|
ObPartitionStore* store_;
|
|
const ObStoreCtx& store_ctx_;
|
|
memtable::ObMemtable* memtable_;
|
|
ObPGMemtableMgr* pg_memtable_mgr_;
|
|
int64_t retry_count_;
|
|
int64_t last_ts_;
|
|
};
|
|
|
|
struct ObPartitionPrefixAccessStat {
|
|
struct AccessStat {
|
|
AccessStat()
|
|
{
|
|
reset();
|
|
}
|
|
~AccessStat() = default;
|
|
void reset()
|
|
{
|
|
memset(this, 0x00, sizeof(AccessStat));
|
|
}
|
|
bool is_valid() const;
|
|
AccessStat& operator=(const AccessStat& other)
|
|
{
|
|
if (this != &other) {
|
|
MEMCPY(this, &other, sizeof(AccessStat));
|
|
}
|
|
return *this;
|
|
}
|
|
TO_STRING_KV(K_(bf_filter_cnt), K_(bf_access_cnt), K_(empty_read_cnt));
|
|
int64_t bf_filter_cnt_;
|
|
int64_t bf_access_cnt_;
|
|
int64_t empty_read_cnt_;
|
|
};
|
|
ObPartitionPrefixAccessStat()
|
|
{
|
|
reset();
|
|
}
|
|
~ObPartitionPrefixAccessStat() = default;
|
|
ObPartitionPrefixAccessStat& operator=(const ObPartitionPrefixAccessStat& other);
|
|
void reset()
|
|
{
|
|
memset(this, 0x00, sizeof(ObPartitionPrefixAccessStat));
|
|
}
|
|
int add_stat(const ObTableAccessStat& stat);
|
|
int add_stat(const ObTableScanStatistic& stat);
|
|
int get_optimal_prefix(int64_t& prefix);
|
|
int64_t to_string(char* buf, const int64_t buf_len) const;
|
|
const static int64_t MAX_ROWKEY_PREFIX_NUM = 7; // avoid consuming too much space for statistics, only count first 7
|
|
AccessStat rowkey_prefix_[MAX_ROWKEY_PREFIX_NUM + 1];
|
|
};
|
|
|
|
class ObSingleRowGetter;
|
|
class ObPartitionStorage : public ObIPartitionStorage {
|
|
template <typename T>
|
|
friend class oceanbase::storageperf::ObMultiBlockBench;
|
|
friend class ObPGStorage;
|
|
friend class ObSingleRowGetter;
|
|
|
|
public:
|
|
ObPartitionStorage();
|
|
virtual ~ObPartitionStorage();
|
|
|
|
inline virtual const share::schema::ObMultiVersionSchemaService* get_schema_service() const override
|
|
{
|
|
return schema_service_;
|
|
}
|
|
virtual int init(const common::ObPartitionKey& pkey, ObIPartitionComponentFactory* cp_fty,
|
|
share::schema::ObMultiVersionSchemaService* schema_service, transaction::ObTransService* txs,
|
|
ObPGMemtableMgr& pg_memtable_mgr) override;
|
|
|
|
virtual void destroy() override;
|
|
virtual const common::ObPartitionKey& get_partition_key() const override
|
|
{
|
|
return pkey_;
|
|
}
|
|
bool is_inited() const;
|
|
|
|
TO_STRING_KV(K_(pkey), K_(store));
|
|
//
|
|
// scan table partition
|
|
//
|
|
// @param ctx [in] transaction context
|
|
// @param param [in] query param
|
|
// @param result [out] iterator to get the result set
|
|
//
|
|
// @return result iterator
|
|
//
|
|
virtual int table_scan(
|
|
ObTableScanParam& param, const int64_t data_max_schema_version, common::ObNewRowIterator*& result) override;
|
|
virtual int table_scan(
|
|
ObTableScanParam& param, const int64_t data_max_schema_version, common::ObNewIterIterator*& result) override;
|
|
virtual int join_mv_scan(ObTableScanParam& left_param, ObTableScanParam& right_param,
|
|
const int64_t left_data_max_schema_version, const int64_t right_data_max_schema_version,
|
|
ObIPartitionStorage& right_storage, common::ObNewRowIterator*& result) override;
|
|
virtual int revert_scan_iter(common::ObNewRowIterator* iter) override;
|
|
//
|
|
// delete rows
|
|
// delete table rows and index rows
|
|
//
|
|
// @param trans_desc [in] transaction handle
|
|
// @param timeout [in] process timeout
|
|
// @param table_id [in] table
|
|
// @param index_included [in] need to delete index too
|
|
// @param column_ids [in] all column referenced, rowkey first
|
|
// @param row_iter [in] primary keys to be deleted
|
|
// @param affected_rows [out]
|
|
//
|
|
// @retval OB_TRANSACTION_SET_VIOLATION
|
|
// @retval OB_SNAPSHOT_DISCARDED
|
|
// @retval OB_TRANS_NOT_FOUND
|
|
// @retval OB_TRANS_ROLLBACKED
|
|
// @retval OB_TRANS_IS_READONLY
|
|
// @retval OB_ERR_EXCLUSIVE_LOCK_CONFLICT
|
|
//
|
|
virtual int delete_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, common::ObNewRowIterator* row_iter,
|
|
int64_t& affected_rows) override;
|
|
|
|
virtual int delete_row(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, const common::ObNewRow& row) override;
|
|
|
|
virtual int put_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, common::ObNewRowIterator* row_iter,
|
|
int64_t& affected_rows) override;
|
|
|
|
//
|
|
// insert rows
|
|
// insert table rows and index rows
|
|
//
|
|
// @param trans_desc [in] transaction handle
|
|
// @param timeout [in] process timeout
|
|
// @param table_id [in] table
|
|
// @param column_ids [in] insert columns
|
|
// @param row_iter [in] insert values
|
|
// @param affected_rows [out]
|
|
//
|
|
// @retval OB_TRANS_NOT_FOUND
|
|
// @retval OB_TRANS_ROLLBACKED
|
|
// @retval OB_TRANS_IS_READONLY
|
|
// @retval OB_ERR_EXCLUSIVE_LOCK_CONFLICT
|
|
// @retval OB_ERR_PRIMARY_KEY_DUPLICATE
|
|
//
|
|
virtual int insert_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, common::ObNewRowIterator* row_iter,
|
|
int64_t& affected_rows) override;
|
|
//
|
|
// insert row
|
|
// insert table row or return conflict row(s)
|
|
//
|
|
// @param trans_desc [in] transaction handle
|
|
// @param timeout [in] process timeout
|
|
// @param column_ids [in] insert columns
|
|
// @param duplicated_column_ids [in] output columns when conflict met
|
|
// @param row [in] row to be inserted
|
|
// @param flag [in] return all conflict rows or the first one
|
|
// @param affected_rows [out] successfully insert row number
|
|
// @param duplicated_rows [out] the iterator of the rowkey(s) of conflict row(s)
|
|
//
|
|
virtual int insert_row(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, const common::ObNewRow& row);
|
|
|
|
virtual int insert_row(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, const common::ObIArray<uint64_t>& duplicated_column_ids,
|
|
const common::ObNewRow& row, const ObInsertFlag flag, int64_t& affected_rows,
|
|
common::ObNewRowIterator*& duplicated_rows) override;
|
|
// check whether row has conflict in storage
|
|
// in_column_ids describe columns of the row, begin with rowey, must include local unique index
|
|
// out_column_ids describe column of conflict row
|
|
// check_row_iter is the iterator of rows that will be checked
|
|
// dup_row_iters are iterators of conflict rows, the number of iterators is same with number of checked rows
|
|
virtual int fetch_conflict_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& in_column_ids, const common::ObIArray<uint64_t>& out_column_ids,
|
|
common::ObNewRowIterator& check_row_iter, common::ObIArray<common::ObNewRowIterator*>& dup_row_iters) override;
|
|
virtual int revert_insert_iter(common::ObNewRowIterator* iter) override;
|
|
//
|
|
// update rows
|
|
// update table rows and index rows
|
|
//
|
|
// @param trans_desc [in] transaction handle
|
|
// @param timeout [in] process timeout
|
|
// @param table_id [in] table
|
|
// @param index_included [in] if index need to be updated
|
|
// @param column_ids [in] all columns related
|
|
// @param column_ids [in] updated columns
|
|
// @param row_iter [in] odd rows are old and even rows are new ones
|
|
// @param affected_rows [out]
|
|
//
|
|
// @retval OB_TRANSACTION_SET_VIOLATION
|
|
// @retval OB_SNAPSHOT_DISCARDED
|
|
// @retval OB_TRANS_NOT_FOUND
|
|
// @retval OB_TRANS_ROLLBACKED
|
|
// @retval OB_TRANS_IS_READONLY
|
|
// @retval OB_ERR_EXCLUSIVE_LOCK_CONFLICT
|
|
// @retval OB_ERR_PRIMARY_KEY_DUPLICATE
|
|
//
|
|
virtual int update_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, const common::ObIArray<uint64_t>& updated_column_ids,
|
|
common::ObNewRowIterator* row_iter, int64_t& affected_rows) override;
|
|
virtual int update_row(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param,
|
|
const common::ObIArray<uint64_t>& column_ids, const common::ObIArray<uint64_t>& updated_column_ids,
|
|
const common::ObNewRow& old_row, const common::ObNewRow& new_row) override;
|
|
|
|
//
|
|
// lock rows
|
|
// lock table rows
|
|
//
|
|
// @param trans_desc [in] transaction handle
|
|
// @param timeout [in] process timeout
|
|
// @param table_id [in] table id
|
|
// @param row_iter [in] rowkey iterator
|
|
// @param lock_flag [in] lock flags: LF_WRITE or LF_NONE
|
|
// @param affected_rows [out]
|
|
//
|
|
// @retval OB_TRANSACTION_SET_VIOLATION
|
|
// @retval OB_SNAPSHOT_DISCARDED
|
|
// @retval OB_TRANS_NOT_FOUND
|
|
// @retval OB_TRANS_ROLLBACKED
|
|
// @retval OB_TRANS_IS_READONLY
|
|
// @retval OB_ERR_EXCLUSIVE_LOCK_CONFLICT
|
|
//
|
|
virtual int lock_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param, const int64_t abs_lock_timeout,
|
|
common::ObNewRowIterator* row_iter, ObLockFlag lock_flag, int64_t& affected_rows) override;
|
|
virtual int lock_rows(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param, const int64_t abs_lock_timeout,
|
|
const common::ObNewRow& row, ObLockFlag lock_flag) override;
|
|
|
|
virtual int get_concurrent_cnt(uint64_t table_id, int64_t schema_version, int64_t& concurrent_cnt) override;
|
|
|
|
virtual int get_batch_rows(const ObTableScanParam& param, const storage::ObBatch& batch, int64_t& logical_row_count,
|
|
int64_t& physical_row_count, common::ObIArray<common::ObEstRowCountRecord>& est_records) override;
|
|
|
|
virtual int get_table_stat(const uint64_t table_id, common::ObTableStat& stat) override;
|
|
|
|
virtual int lock(const ObStoreCtx& ctx) override;
|
|
|
|
virtual void set_merge_status(bool merge_success) override;
|
|
virtual bool can_schedule_merge() override;
|
|
|
|
// write ssstore objects @version tree to data file, used by write_check_point
|
|
virtual int serialize(ObArenaAllocator& allocator, char*& new_buf, int64_t& serialize_size);
|
|
// read ssstore objects from data file to construct partition storage's version tree.
|
|
virtual int deserialize(const ObReplicaType replica_type, const char* buf, const int64_t buf_len,
|
|
ObIPartitionGroup* pg, int64_t& pos, bool& is_old_meta, ObPartitionStoreMeta& old_meta);
|
|
|
|
virtual bool has_memstore() override;
|
|
|
|
// freeze actions
|
|
virtual int get_replayed_table_version(int64_t& table_version) override;
|
|
virtual int get_partition_ss_store_info(common::ObArray<PartitionSSStoreInfo>& partition_ss_store_info_list) override;
|
|
virtual int get_all_tables(ObTablesHandle& tables_handle) override;
|
|
virtual int retire_warmup_store(const bool is_disk_full) override;
|
|
virtual int halt_prewarm() override;
|
|
|
|
virtual common::ObReplicaType get_replica_type() override
|
|
{
|
|
return store_.get_replica_type();
|
|
}
|
|
virtual int query_range_to_macros(common::ObIAllocator& allocator,
|
|
const common::ObIArray<common::ObStoreRange>& ranges, const int64_t type, uint64_t* macros_count,
|
|
const int64_t* total_task_count, common::ObIArray<common::ObStoreRange>* splitted_ranges,
|
|
common::ObIArray<int64_t>* split_index) override;
|
|
virtual int get_multi_ranges_cost(const common::ObIArray<common::ObStoreRange>& ranges, int64_t& total_size) override;
|
|
virtual int split_multi_ranges(const common::ObIArray<common::ObStoreRange>& ranges,
|
|
const int64_t expected_task_count, common::ObIAllocator& allocator,
|
|
common::ObArrayArray<common::ObStoreRange>& multi_range_split_array) override;
|
|
virtual int append_local_sort_data(const share::ObBuildIndexAppendLocalDataParam& param,
|
|
const common::ObPGKey& pg_key, const blocksstable::ObStorageFileHandle& file_handle,
|
|
common::ObNewRowIterator& iter) override;
|
|
|
|
int get_schemas_to_split(storage::ObSSTableSplitCtx& ctx);
|
|
int get_schemas_to_merge(storage::ObSSTableMergeCtx& ctx);
|
|
int check_is_schema_changed(const int64_t column_checksum_method,
|
|
const share::schema::ObTableSchema& base_table_schema, const share::schema::ObTableSchema& main_table_schema,
|
|
bool& is_schema_changed, bool& is_column_changed, bool& is_progressive_merge_num_changed);
|
|
int cal_major_merge_param(ObSSTableMergeCtx& ctx);
|
|
int cal_minor_merge_param(ObSSTableMergeCtx& ctx);
|
|
int build_merge_ctx(storage::ObSSTableMergeCtx& ctx);
|
|
int get_concurrent_cnt(ObTablesHandle& tables_handle, const share::schema::ObTableSchema& table_schema,
|
|
const ObMergeType& merge_type, int64_t& concurrent_cnt);
|
|
|
|
int init_split_context(storage::ObSSTableSplitCtx& ctx);
|
|
int init_merge_context(storage::ObSSTableMergeCtx& ctx);
|
|
|
|
// TODO(): following methods need to be moved to merge_task.cpp later
|
|
static void check_data_checksum(const common::ObReplicaType& replica_type, const ObPartitionKey& pkey,
|
|
const share::schema::ObTableSchema& schema, const ObSSTable& data_sstable,
|
|
common::ObIArray<storage::ObITable*>& base_tables, ObIPartitionReport& report);
|
|
static void dump2text(const share::schema::ObTableSchema& schema, common::ObIArray<storage::ObITable*>& base_tables,
|
|
const ObPartitionKey& pkey);
|
|
static int update_estimator(const share::schema::ObTableSchema* base_schema, const bool is_full,
|
|
const ObIArray<ObColumnStat*>& column_stats, ObSSTable* sstable, const common::ObPartitionKey& pkey);
|
|
int create_partition_store(const common::ObReplicaType& replica_type, const int64_t multi_version_start,
|
|
const uint64_t data_table_id, const int64_t create_schema_version, const int64_t create_timestamp,
|
|
ObIPartitionGroup* pg, ObTablesHandle& sstables_handle);
|
|
ObPartitionStore& get_partition_store()
|
|
{
|
|
return store_;
|
|
}
|
|
int do_warm_up_request(const ObIWarmUpRequest* request) override;
|
|
int check_index_need_build(const share::schema::ObTableSchema& index_schema, bool& need_build) override;
|
|
int get_build_index_context(const compaction::ObBuildIndexParam& param, compaction::ObBuildIndexContext& context) override;
|
|
|
|
int local_sort_index_by_range(
|
|
const int64_t idx, const compaction::ObBuildIndexParam& param, const compaction::ObBuildIndexContext& context) override;
|
|
|
|
int get_build_index_param(const uint64_t index_id, const int64_t schema_version, ObIPartitionReport* report,
|
|
compaction::ObBuildIndexParam& param) override;
|
|
int save_split_state(const int64_t state, const bool write_slog);
|
|
int get_split_state(int64_t& state) const;
|
|
int save_split_info(const ObPartitionSplitInfo& split_info, const bool write_slog);
|
|
int check_table_continuity(const uint64_t table_id, const int64_t version, bool& is_continual);
|
|
template <typename T>
|
|
static int get_merge_opt(const int64_t merge_version, const int64_t storage_version, const int64_t work_version,
|
|
const int64_t born_version, const T& old_val, const T& new_val, T& opt);
|
|
int update_multi_version_start(const int64_t multi_version_start) override;
|
|
int validate_sstables(const ObIArray<share::schema::ObIndexTableStat>& index_stats, bool& is_all_checked);
|
|
bool need_check_index_(const uint64_t index_id, const ObIArray<share::schema::ObIndexTableStat>& index_stats);
|
|
static int generate_index_output_param(const share::schema::ObTableSchema& data_table_schema,
|
|
const share::schema::ObTableSchema& index_schema, common::ObArray<share::schema::ObColDesc>& col_ids,
|
|
common::ObArray<share::schema::ObColDesc>& org_col_ids, common::ObArray<int32_t>& output_projector,
|
|
int64_t& unique_key_cnt);
|
|
int fill_checksum(const uint64_t index_id, const int sstable_type, share::ObSSTableChecksumItem& checksum_item);
|
|
ObPartitionPrefixAccessStat& get_prefix_access_stat()
|
|
{
|
|
return prefix_access_stat_;
|
|
}
|
|
int feedback_scan_access_stat(const ObTableScanParam& param);
|
|
|
|
int erase_stat_cache();
|
|
|
|
public:
|
|
typedef common::hash::ObHashMap<int64_t, ObColumnChecksumEntry, common::hash::NoPthreadDefendMode> ColumnChecksumMap;
|
|
|
|
private:
|
|
struct RowReshape {
|
|
RowReshape()
|
|
: row_reshape_cells_(NULL),
|
|
char_only_(false),
|
|
binary_buffer_len_(0),
|
|
binary_buffer_ptr_(NULL),
|
|
binary_len_array_()
|
|
{}
|
|
common::ObObj* row_reshape_cells_;
|
|
bool char_only_;
|
|
int64_t binary_buffer_len_;
|
|
char* binary_buffer_ptr_;
|
|
// pair: binary column idx in row, binary column len
|
|
common::ObSEArray<std::pair<int32_t, int32_t>, common::OB_ROW_MAX_COLUMNS_COUNT> binary_len_array_;
|
|
};
|
|
|
|
enum ChangeType {
|
|
NO_CHANGE,
|
|
ROWKEY_CHANGE,
|
|
ND_ROWKEY_CHANGE, // null dependent rowkey change
|
|
OTHER_CHANGE,
|
|
};
|
|
|
|
struct ObDMLRunningCtx {
|
|
public:
|
|
ObDMLRunningCtx(const ObStoreCtx& store_ctx, const ObDMLBaseParam& dml_param, common::ObIAllocator& allocator,
|
|
const ObRowDml dml_type)
|
|
: store_ctx_(store_ctx),
|
|
dml_param_(dml_param),
|
|
allocator_(allocator),
|
|
dml_type_(dml_type),
|
|
relative_tables_(allocator),
|
|
col_map_(nullptr),
|
|
col_descs_(nullptr),
|
|
column_ids_(nullptr),
|
|
idx_col_descs_(),
|
|
tbl_row_(),
|
|
idx_row_(NULL),
|
|
is_inited_(false)
|
|
{}
|
|
~ObDMLRunningCtx()
|
|
{
|
|
free_work_members();
|
|
}
|
|
|
|
int init(const common::ObIArray<uint64_t>* column_ids, const common::ObIArray<uint64_t>* upd_col_ids,
|
|
const bool use_table_param, share::schema::ObMultiVersionSchemaService* schema_service,
|
|
ObPartitionStore& store);
|
|
static int prepare_column_desc(
|
|
const common::ObIArray<uint64_t>& column_ids, const ObRelativeTable& table, ObColDescIArray& col_descs);
|
|
|
|
private:
|
|
void free_work_members();
|
|
int prepare_index_row();
|
|
int prepare_column_info(const common::ObIArray<uint64_t>& column_ids);
|
|
|
|
public:
|
|
const ObStoreCtx& store_ctx_;
|
|
const ObDMLBaseParam& dml_param_;
|
|
common::ObIAllocator& allocator_;
|
|
const ObRowDml dml_type_;
|
|
ObRelativeTables relative_tables_;
|
|
const share::schema::ColumnMap *col_map_;
|
|
const ObColDescIArray *col_descs_;
|
|
const common::ObIArray<uint64_t> *column_ids_;
|
|
ObColDescArray idx_col_descs_;
|
|
ObStoreRow tbl_row_;
|
|
ObStoreRow* idx_row_; // not a must, allocate dynamically
|
|
|
|
private:
|
|
bool is_inited_;
|
|
};
|
|
|
|
static const int32_t LOCK_WAIT_INTERVAL = 5; // 5us
|
|
|
|
private:
|
|
int write_index_row(ObRelativeTable& relative_table, const ObStoreCtx& ctx, const ObColDescIArray& idx_columns,
|
|
ObStoreRow& index_row);
|
|
int check_other_columns_in_column_ids(const ObRelativeTables& rel_schema, const share::schema::ColumnMap* col_map,
|
|
const common::ObIArray<uint64_t>& column_ids, const ObRowDml dml_type, const ChangeType change_type,
|
|
const bool is_total_quantity_log);
|
|
int construct_column_ids_map(const common::ObIArray<uint64_t>& column_ids, const int64_t total_column_count,
|
|
common::ObIAllocator& work_allocator, share::schema::ColumnMap*& col_map);
|
|
void deconstruct_column_ids_map(common::ObIAllocator& work_allocator, share::schema::ColumnMap*& col_map);
|
|
int check_column_ids_valid(common::ObIAllocator& work_allocator, const ObRelativeTables& relative_tables,
|
|
const share::schema::ColumnMap* col_map, const common::ObIArray<uint64_t>& column_ids, const ObRowDml dml_type,
|
|
const common::ObIArray<uint64_t>& upd_column_ids, const ChangeType change_type, const bool is_total_quantity_log);
|
|
int insert_table_row(
|
|
ObDMLRunningCtx &run_ctx, ObRelativeTable &relative_table, const ObColDescIArray &col_descs, ObStoreRow &row);
|
|
int insert_table_rows(ObDMLRunningCtx &run_ctx, ObRelativeTable &relative_table, const ObColDescIArray &col_descs,
|
|
ObRowsInfo &rows_info);
|
|
int insert_index_rows(ObDMLRunningCtx &run_ctx, ObStoreRow *rows, int64_t row_count);
|
|
int direct_insert_row_and_index(ObDMLRunningCtx &run_ctx, const ObStoreRow &tbl_row);
|
|
int convert_row_to_rowkey(ObSingleRowGetter &index_row_getter, ObStoreRowkey &rowkey);
|
|
int get_conflict_row(ObDMLRunningCtx &run_ctx, const common::ObIArray<uint64_t> &out_col_ids,
|
|
ObRelativeTable &relative_table, const ObStoreRowkey &rowkey, common::ObNewRowIterator *&duplicated_rows);
|
|
int get_index_conflict_row(ObDMLRunningCtx &run_ctx, const common::ObIArray<uint64_t> &out_col_ids,
|
|
ObRelativeTable &relative_table, bool need_index_back, const common::ObNewRow &row,
|
|
common::ObNewRowIterator *&duplicated_rows);
|
|
int single_get_row(ObSingleRowGetter &row_getter,
|
|
const ObStoreRowkey &rowkey,
|
|
common::ObNewRowIterator *&duplicated_rows,
|
|
int64_t data_table_rowkey_cnt);
|
|
int get_conflict_rows(ObDMLRunningCtx &run_ctx, const ObInsertFlag flag,
|
|
const common::ObIArray<uint64_t> &dup_col_ids, const common::ObNewRow &row,
|
|
common::ObNewRowIterator *&duplicated_rows);
|
|
int get_change_type(
|
|
const common::ObIArray<uint64_t>& update_ids, const ObRelativeTable& table, ChangeType& change_type);
|
|
int check_rowkey_change(const common::ObIArray<uint64_t>& update_ids, const ObRelativeTables& relative_tables,
|
|
common::ObIArray<ChangeType>& changes, bool& delay_new);
|
|
int check_rowkey_value_change(const common::ObNewRow& old_row, const common::ObNewRow& new_row,
|
|
const int64_t rowkey_len, bool& rowkey_change) const;
|
|
int process_old_row(ObDMLRunningCtx& ctx, const bool data_tbl_rowkey_change,
|
|
const common::ObIArray<ChangeType>& change_flags, const ObStoreRow& tbl_row);
|
|
int process_row_of_data_table(ObDMLRunningCtx& run_ctx, const common::ObIArray<int64_t>& update_idx,
|
|
const ObStoreRow& old_tbl_row, const ObStoreRow& new_tbl_row, const bool rowkey_change);
|
|
int process_row_of_index_tables(
|
|
ObDMLRunningCtx& run_ctx, const common::ObIArray<ChangeType>& change_flags, const ObStoreRow& new_tbl_row);
|
|
int process_new_row(ObDMLRunningCtx& run_ctx, const common::ObIArray<ChangeType>& change_flags,
|
|
const common::ObIArray<int64_t>& update_idx, const ObStoreRow& old_tbl_row, const ObStoreRow& new_tbl_row,
|
|
const bool rowkey_change);
|
|
int reshape_delete_row(
|
|
ObDMLRunningCtx& run_ctx, RowReshape*& row_reshape, ObStoreRow& tbl_row, ObStoreRow& new_tbl_row);
|
|
int delete_row(ObDMLRunningCtx& run_ctx, RowReshape*& row_reshape, const common::ObNewRow& row);
|
|
int update_row(ObDMLRunningCtx& run_ctx, const common::ObIArray<ChangeType>& changes,
|
|
const common::ObIArray<int64_t>& update_idx, const bool delay_new, RowReshape*& old_row_reshape_ins,
|
|
RowReshape*& row_reshape_ins, ObStoreRow& old_tbl_row, ObStoreRow& new_tbl_row, ObRowStore* row_store,
|
|
bool& duplicate);
|
|
bool illegal_filter(const ObTableScanParam& param) const;
|
|
|
|
// $lta_param && $lta_ctx are inited
|
|
int join_mv_init_merge_param(const share::schema::ObTableSchema& ltable, const share::schema::ObTableSchema& rtable,
|
|
const ObTableAccessParam& lta_param, const ObTableAccessContext& lta_ctx, share::schema::ObTableParam& rt_param,
|
|
ObTableAccessParam& rta_param, ObTableAccessContext& rta_ctx, ObStoreCtx& rctx);
|
|
|
|
int prepare_merge_mv_depend_sstable(const common::ObVersion& frozen_version,
|
|
const share::schema::ObTableSchema* schema, const share::schema::ObTableSchema* dep_schema,
|
|
ObTablesHandle& mv_dep_tables_handle);
|
|
|
|
int estimate_row_count(const storage::ObTableScanParam& param, const storage::ObBatch& batch,
|
|
const common::ObIArray<ObITable*>& stores, ObPartitionEst& cost_estimate,
|
|
common::ObIArray<common::ObEstRowCountRecord>& est_records);
|
|
// In sql static engine cell is projected to ObExpr directly in ObMultipleMerge.
|
|
// We need to project back to ObNewRow when for row locking (lock_row() need ObNewRow).
|
|
//
|
|
// Why not project to ObNewRow directly in static engine for lock? Because the filter
|
|
// need the ObExpr interface.
|
|
int prepare_lock_row(const ObTableScanParam& scan_param, const common::ObNewRow& row);
|
|
int lock_scan_rows(const ObStoreCtx& ctx, const ObTableScanParam& scan_param, ObTableScanIterator& iter);
|
|
int lock_scan_rows(const ObStoreCtx& ctx, const ObTableScanParam& scan_param, ObTableScanIterIterator& iter);
|
|
int64_t get_lock_wait_timeout(const int64_t abs_lock_timeout, const int64_t stmt_timeout) const;
|
|
int get_next_row_from_iter(common::ObNewRowIterator* iter, ObStoreRow& store_row, const bool need_copy_cells);
|
|
int construct_update_idx(const share::schema::ColumnMap* col_map, const common::ObIArray<uint64_t>& upd_col_ids,
|
|
common::ObIArray<int64_t>& update_idx);
|
|
int malloc_rows_reshape_if_need(common::ObIAllocator& work_allocator, const ObColDescIArray& col_descs,
|
|
const int64_t row_count, const ObRelativeTable& table, const ObSQLMode sql_mode, RowReshape*& row_reshape_ins);
|
|
int malloc_rows_reshape(common::ObIAllocator& work_allocator, const ObColDescIArray& col_descs,
|
|
const int64_t row_count, const ObRelativeTable& table, RowReshape*& row_reshape_ins);
|
|
void free_row_reshape(common::ObIAllocator& work_allocator, RowReshape*& row_reshape_ins, int64_t row_count);
|
|
int need_reshape_table_row(const common::ObNewRow& row, RowReshape* row_reshape_ins, int64_t row_reshape_cells_count,
|
|
ObSQLMode sql_mode, bool& need_reshape) const;
|
|
int need_reshape_table_row(
|
|
const common::ObNewRow& row, const int64_t column_cnt, ObSQLMode sql_mode, bool& need_reshape) const;
|
|
int reshape_row(const common::ObNewRow& row, const int64_t column_cnt, RowReshape* row_reshape_ins,
|
|
ObStoreRow& tbl_row, bool need_reshape, ObSQLMode sql_mode) const;
|
|
int reshape_table_rows(const common::ObNewRow* rows, RowReshape* row_reshape_ins, int64_t row_reshape_cells_count,
|
|
ObStoreRow* tbl_rows, int64_t row_count, ObSQLMode sql_mode) const;
|
|
|
|
virtual int extract_rowkey(const ObRelativeTable& table, const common::ObStoreRowkey& rowkey, char* buffer,
|
|
const int64_t buffer_len, const common::ObTimeZoneInfo* tz_info = NULL);
|
|
|
|
private:
|
|
int get_depend_table_schema(const share::schema::ObTableSchema* table_schema,
|
|
share::schema::ObSchemaGetterGuard& schema_guard, const share::schema::ObTableSchema*& dep_table_schema);
|
|
int report_checksum(const uint64_t execution_id, const uint64_t task_id,
|
|
const share::schema::ObTableSchema& index_schema, const int64_t checksum_method, int64_t* column_checkum);
|
|
|
|
int get_build_index_stores(const share::schema::ObTenantSchema& tenant_schema, compaction::ObBuildIndexParam& param);
|
|
int check_need_update_estimator(
|
|
const share::schema::ObTableSchema& table_schema, int64_t data_version, int64_t& stat_sampling_ratio);
|
|
int do_rowkey_exists(const ObStoreCtx& store_ctx, const common::ObIArray<ObITable*>& read_tables,
|
|
const int64_t table_id, const common::ObStoreRowkey& rowkey, const common::ObQueryFlag& query_flag,
|
|
const ObColDescIArray& col_descs, bool& exists);
|
|
int rowkey_exists(ObRelativeTable& relative_table, const ObStoreCtx& store_ctx, const ObColDescIArray& col_descs,
|
|
const common::ObNewRow& row, bool& exists);
|
|
int do_rowkeys_prefix_exist(const common::ObIArray<ObITable*>& read_stores, ObRowsInfo& rows_info, bool& may_exist);
|
|
int do_rowkeys_exists(const common::ObIArray<ObITable*>& read_stores, ObRowsInfo& rows_info, bool& exists);
|
|
int rowkeys_exists(const ObStoreCtx& store_ctx, ObRelativeTable& relative_table, ObRowsInfo& rows_info, bool& exists);
|
|
int write_row(ObRelativeTable& relative_table, const ObStoreCtx& store_ctx, const int64_t rowkey_len,
|
|
const common::ObIArray<share::schema::ObColDesc>& col_descs, const storage::ObStoreRow& row);
|
|
int write_row(ObRelativeTable& relative_table, const storage::ObStoreCtx& ctx, const int64_t rowkey_len,
|
|
const common::ObIArray<share::schema::ObColDesc>& col_descs, const common::ObIArray<int64_t>& update_idx,
|
|
const storage::ObStoreRow& old_row, const storage::ObStoreRow& new_row);
|
|
int lock_row(ObRelativeTable& relative_table, const storage::ObStoreCtx& store_ctx,
|
|
const common::ObIArray<share::schema::ObColDesc>& col_descs, const common::ObNewRow& row,
|
|
const ObSQLMode sql_mode, ObIAllocator& allocator, RowReshape*& row_reshape_ins);
|
|
int lock_row(ObRelativeTable& relative_table, const storage::ObStoreCtx& store_ctx,
|
|
const common::ObIArray<share::schema::ObColDesc>& col_descs, const common::ObStoreRowkey& rowkey);
|
|
int check_row_locked_by_myself(ObRelativeTable& relative_table, const storage::ObStoreCtx& store_ctx,
|
|
const common::ObIArray<share::schema::ObColDesc>& col_descs, const common::ObStoreRowkey& rowkey, bool& locked);
|
|
|
|
int insert_rows_(ObDMLRunningCtx& run_ctx, const common::ObNewRow* const rows, const int64_t row_count,
|
|
ObRowsInfo& rows_info, storage::ObStoreRow* tbl_rows, RowReshape* row_reshape_ins, int64_t& afct_num,
|
|
int64_t& dup_num);
|
|
|
|
bool is_expired_version(
|
|
const common::ObVersion& base_version, const common::ObVersion& version, const int64_t max_kept_number);
|
|
|
|
int get_merge_level(const int64_t merge_version, const ObSSTableMergeCtx& ctx, ObMergeLevel& merge_level);
|
|
|
|
int get_store_column_checksum_in_micro(
|
|
const int64_t merge_version, const ObSSTableMergeCtx& ctx, bool& store_column_checksum);
|
|
|
|
int get_local_index_column_ids_and_projector(const share::schema::ObTableSchema& table_schema,
|
|
const share::schema::ObTableSchema& index_schema, ObArray<share::schema::ObColDesc>& org_col_ids,
|
|
ObArray<share::schema::ObColDesc>& col_ids, ObArray<int32_t>& output_projector);
|
|
|
|
int init_partition_meta(const common::ObReplicaType& replica_type, int64_t data_version,
|
|
const int64_t multi_version_start, const uint64_t data_table_id, const int64_t create_schema_version,
|
|
const int64_t create_timestamp, const int64_t snapshot_version, ObPGPartitionStoreMeta& partition_meta);
|
|
int replay_old_ssstore(ObSSStore& store, int64_t& last_publish_version, ObArray<ObITable::TableKey>& add_tables);
|
|
int deep_copy_build_index_schemas(const share::schema::ObTableSchema* data_table_schema,
|
|
const share::schema::ObTableSchema* index_schema, const share::schema::ObTableSchema* dep_table_schema,
|
|
compaction::ObBuildIndexParam& param);
|
|
int validate_sstable(const int64_t row_count, const ObSSTable* sstable, ColumnChecksumMap& cc_map);
|
|
void handle_error_index_table(
|
|
const ObSSTable& index_table, const ObIArray<share::schema::ObIndexTableStat>& index_stats, int& result);
|
|
int try_update_report_status(const common::ObVersion& version, bool& finished, bool& need_report);
|
|
int check_schema_version_for_bounded_staleness_read_(
|
|
const int64_t table_version_for_read, const int64_t data_max_schema_version, const uint64_t table_id);
|
|
int lock_rows_(const ObStoreCtx& ctx, const ObDMLBaseParam& dml_param, const int64_t abs_lock_timeout,
|
|
const common::ObNewRow& row, ObLockFlag lock_flag, RowReshape*& row_reshape);
|
|
int lock_rows_(
|
|
const ObStoreCtx& ctx, const ObTableScanParam& scan_param, const common::ObNewRow& row, RowReshape*& row_reshape);
|
|
int check_useless_index_mini_merge(const storage::ObSSTableMergeCtx &ctx);
|
|
void check_leader_changed_for_sql_recheck_(ObDMLRunningCtx &run_ctx, int &ret);
|
|
|
|
int dump_error_info(ObSSTable &main_sstable, ObSSTable &index_sstable);
|
|
//////////////////
|
|
/// do write row strict check
|
|
int check_old_row_legitimacy(ObDMLRunningCtx &run_ctx, const common::ObNewRow &row);
|
|
int check_delete_index_legitimacy(
|
|
ObDMLRunningCtx &run_ctx, ObRelativeTable &index_table, const common::ObNewRow &row);
|
|
int check_new_row_legitimacy(ObDMLRunningCtx &run_ctx, const common::ObNewRow &row);
|
|
int check_new_row_nullable_value(
|
|
const common::ObIArray<uint64_t> &column_ids, ObRelativeTable &data_table, const common::ObNewRow &new_row);
|
|
int check_new_row_nullable_value(const common::ObIArray<share::schema::ObColDesc> &col_descs,
|
|
ObRelativeTable &relative_table, const common::ObNewRow &new_row);
|
|
int check_new_row_shadow_pk(
|
|
const common::ObIArray<uint64_t> &column_ids, ObRelativeTable &data_table, const common::ObNewRow &new_row);
|
|
// disallow copy;
|
|
DISALLOW_COPY_AND_ASSIGN(ObPartitionStorage);
|
|
|
|
protected:
|
|
// data members
|
|
static const int64_t DELAY_SCHEDULE_TIME_UNIT = 1000 * 1000 * 1; // 1s
|
|
static const int64_t MAGIC_NUM_BEFORE_1461 = -0xABCD;
|
|
static const int64_t MAGIC_NUM_1_4_61 = -0xABCE;
|
|
uint64_t cluster_version_;
|
|
common::ObPartitionKey pkey_;
|
|
share::schema::ObMultiVersionSchemaService* schema_service_;
|
|
ObIPartitionComponentFactory* cp_fty_;
|
|
transaction::ObTransService* txs_;
|
|
ObPGMemtableMgr* pg_memtable_mgr_;
|
|
bool is_inited_;
|
|
bool merge_successed_;
|
|
int64_t merge_timestamp_;
|
|
int64_t merge_failed_cnt_;
|
|
ObPartitionStore store_;
|
|
common::ObReplicaType replay_replica_type_; // only for compatibility of 1.4, used in replaying slog
|
|
ObPartitionPrefixAccessStat prefix_access_stat_;
|
|
};
|
|
|
|
inline int64_t ObPartitionStorage::get_lock_wait_timeout(
|
|
const int64_t abs_lock_timeout, const int64_t stmt_timeout) const
|
|
{
|
|
return (abs_lock_timeout < 0 ? stmt_timeout : (abs_lock_timeout > stmt_timeout ? stmt_timeout : abs_lock_timeout));
|
|
}
|
|
|
|
} // namespace storage
|
|
} // end namespace oceanbase
|
|
|
|
#endif // OCEANBASE_STORAGE_OB_PARTITION_STORAGE
|