From 9de65fb1d780e9ec845068e9c8a1318bc8195b9a Mon Sep 17 00:00:00 2001 From: coolfishchen Date: Mon, 22 Apr 2024 09:23:47 +0000 Subject: [PATCH] [FEAT MERGE] incremental direct load phase I Co-authored-by: Monk-Liu <1152761042@qq.com> Co-authored-by: suz-yang Co-authored-by: ZenoWang --- deps/init/oceanbase.el7.aarch64.deps | 2 +- deps/init/oceanbase.el7.x86_64.deps | 2 +- deps/init/oceanbase.el8.aarch64.deps | 2 +- deps/init/oceanbase.el8.x86_64.deps | 2 +- deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h | 2 +- deps/oblib/src/rpc/obrpc/ob_rpc_proxy.h | 2 +- ...test_ob_simple_log_single_replica_func.cpp | 4 +- .../checkpoint/test_checkpoint_executor.cpp | 7 +- .../checkpoint/test_data_checkpoint.cpp | 5 +- mittest/mtlenv/storage/test_co_merge.cpp | 1 - .../mtlenv/storage/test_ls_tablet_service.cpp | 2 +- mittest/mtlenv/storage/test_memtable_v2.cpp | 10 +- .../test_multi_version_merge_recycle.cpp | 1 - .../test_multi_version_sstable_merge.cpp | 1 - .../test_tablet_create_delete_helper.cpp | 4 +- .../storage/test_tenant_meta_mem_mgr.cpp | 42 +- mittest/mtlenv/test_tx_data_table.cpp | 15 +- mittest/multi_replica/CMakeLists.txt | 1 + .../test_ob_direct_load_inc_log.cpp | 191 ++++ mittest/simple_server/CMakeLists.txt | 1 + .../test_memtable_new_safe_to_destroy.cpp | 6 +- .../simple_server/test_ob_minor_freeze.cpp | 35 +- .../test_tablet_memtable_mit.cpp | 360 +++++++ .../test_transfer_in_after_abort.cpp | 2 +- .../simple_server/test_tx_data_table_mit.cpp | 3 +- .../libobcdc/src/ob_cdc_lob_ctx.cpp | 8 +- src/logservice/libobcdc/src/ob_cdc_lob_ctx.h | 18 +- .../src/ob_cdc_part_trans_resolver.cpp | 72 +- .../libobcdc/src/ob_cdc_part_trans_resolver.h | 15 +- src/logservice/libobcdc/src/ob_log_config.h | 3 + .../libobcdc/src/ob_log_entry_task_pool.cpp | 3 +- .../libobcdc/src/ob_log_entry_task_pool.h | 2 + .../libobcdc/src/ob_log_fetcher.cpp | 6 +- src/logservice/libobcdc/src/ob_log_fetcher.h | 2 + .../libobcdc/src/ob_log_formatter.cpp | 105 +- .../libobcdc/src/ob_log_formatter.h | 9 +- .../libobcdc/src/ob_log_instance.cpp | 15 +- .../libobcdc/src/ob_log_ls_fetch_mgr.cpp | 3 +- .../libobcdc/src/ob_log_ls_fetch_mgr.h | 2 + .../libobcdc/src/ob_log_meta_data_fetcher.cpp | 5 +- .../libobcdc/src/ob_log_meta_data_fetcher.h | 3 +- .../libobcdc/src/ob_log_meta_data_service.cpp | 5 +- .../libobcdc/src/ob_log_meta_data_service.h | 3 +- .../libobcdc/src/ob_log_part_trans_parser.cpp | 361 +++++-- .../libobcdc/src/ob_log_part_trans_parser.h | 53 +- .../libobcdc/src/ob_log_part_trans_task.cpp | 844 ++++++++++----- .../libobcdc/src/ob_log_part_trans_task.h | 226 ++-- .../src/ob_log_resource_collector.cpp | 1 - .../libobcdc/src/ob_log_trans_log.h | 6 + .../src/ob_log_trans_redo_dispatcher.cpp | 6 +- .../src/ob_log_trans_redo_dispatcher.h | 5 +- src/logservice/libobcdc/src/ob_log_utils.cpp | 67 +- src/logservice/libobcdc/src/ob_log_utils.h | 4 +- .../tests/ob_binlog_record_printer.cpp | 4 +- src/observer/ob_rpc_processor_simple.cpp | 42 +- src/observer/ob_rpc_processor_simple.h | 1 + src/observer/ob_server.cpp | 1 - src/observer/ob_server.h | 3 - src/observer/ob_service.cpp | 1 - src/observer/ob_srv_xlator_storage.cpp | 1 + .../ob_table_load_control_rpc_executor.cpp | 4 +- .../ob_table_load_control_rpc_struct.cpp | 1 + .../ob_table_load_control_rpc_struct.h | 1 - .../table_load/ob_table_load_client_task.cpp | 6 +- .../table_load/ob_table_load_coordinator.cpp | 249 ++--- .../table_load/ob_table_load_coordinator.h | 10 +- .../ob_table_load_index_long_wait.h | 52 + .../table_load/ob_table_load_instance.cpp | 728 +++++++++---- .../table_load/ob_table_load_instance.h | 106 +- .../table_load/ob_table_load_merger.cpp | 120 +-- .../table_load/ob_table_load_merger.h | 2 - .../table_load/ob_table_load_schema.cpp | 26 + .../table_load/ob_table_load_schema.h | 4 + .../table_load/ob_table_load_service.cpp | 34 +- .../table_load/ob_table_load_store.cpp | 59 +- src/observer/table_load/ob_table_load_store.h | 11 +- .../table_load/ob_table_load_store_ctx.cpp | 75 +- .../table_load/ob_table_load_store_ctx.h | 2 + .../table_load/ob_table_load_struct.cpp | 2 +- .../table_load/ob_table_load_struct.h | 3 + .../ob_table_load_trans_bucket_writer.cpp | 5 +- .../table_load/ob_table_load_trans_store.cpp | 39 +- .../table_load/ob_table_load_trans_store.h | 6 +- .../ob_all_virtual_memstore_info.cpp | 26 +- .../ob_all_virtual_memstore_info.h | 2 +- .../ob_all_virtual_table_mgr.cpp | 4 +- ...virtual_tenant_memstore_allocator_info.cpp | 2 +- .../ob_inner_table_schema.21101_21150.cpp | 2 +- .../ob_inner_table_schema.28051_28100.cpp | 2 +- .../inner_table/ob_inner_table_schema_def.py | 4 +- src/share/ob_ddl_common.h | 1 + src/share/ob_rpc_struct.cpp | 102 +- src/share/ob_rpc_struct.h | 47 +- src/share/ob_srv_rpc_proxy.h | 1 + src/share/table/ob_table_load_define.cpp | 2 +- .../table/ob_table_load_sql_statistics.cpp | 235 +++-- .../table/ob_table_load_sql_statistics.h | 25 +- .../throttle/ob_share_throttle_define.cpp | 1 - .../code_generator/ob_static_engine_cg.cpp | 5 +- .../engine/cmd/ob_load_data_direct_impl.cpp | 97 +- src/sql/engine/cmd/ob_load_data_direct_impl.h | 24 +- src/sql/engine/cmd/ob_load_data_executor.cpp | 21 +- .../engine/cmd/ob_table_direct_insert_ctx.cpp | 33 +- .../engine/cmd/ob_table_direct_insert_ctx.h | 6 +- .../cmd/ob_table_direct_insert_service.cpp | 25 +- .../cmd/ob_table_direct_insert_service.h | 2 +- src/sql/ob_result_set.cpp | 29 +- src/sql/ob_sql_trans_control.cpp | 10 + src/sql/optimizer/ob_insert_log_plan.cpp | 21 +- src/sql/parser/sql_parser_mysql_mode.y | 6 +- .../resolver/cmd/ob_load_data_resolver.cpp | 44 +- src/sql/resolver/cmd/ob_load_data_stmt.h | 12 +- src/sql/resolver/dml/ob_dml_resolver.cpp | 50 + src/sql/resolver/dml/ob_dml_resolver.h | 4 +- src/sql/resolver/dml/ob_hint.cpp | 52 +- src/sql/resolver/dml/ob_hint.h | 62 +- src/sql/resolver/dml/ob_insert_resolver.cpp | 2 +- src/storage/CMakeLists.txt | 8 +- src/storage/access/ob_multiple_merge.cpp | 20 +- src/storage/access/ob_multiple_merge.h | 2 + .../blocksstable/ob_block_sstable_struct.cpp | 31 - .../blocksstable/ob_block_sstable_struct.h | 28 - src/storage/blocksstable/ob_datum_row.h | 12 +- .../ob_macro_block_bare_iterator.cpp | 9 +- .../ob_macro_block_bare_iterator.h | 5 +- .../blocksstable/ob_macro_block_reader.cpp | 4 +- .../blocksstable/ob_macro_block_reader.h | 3 +- src/storage/blocksstable/ob_sstable_meta.cpp | 15 + src/storage/blocksstable/ob_sstable_meta.h | 6 +- src/storage/checkpoint/ob_data_checkpoint.cpp | 37 +- src/storage/checkpoint/ob_freeze_checkpoint.h | 4 +- .../compaction/ob_basic_tablet_merge_ctx.cpp | 2 + .../compaction/ob_basic_tablet_merge_ctx.h | 1 + .../compaction/ob_compaction_diagnose.cpp | 2 +- .../compaction/ob_partition_merge_iter.cpp | 14 +- .../compaction/ob_partition_merge_iter.h | 5 +- .../compaction/ob_partition_merge_policy.cpp | 10 +- .../ob_partition_merge_progress.cpp | 2 +- .../ob_partition_parallel_merge_ctx.cpp | 2 +- .../compaction/ob_partition_rows_merger.cpp | 18 +- .../compaction/ob_tablet_merge_ctx.cpp | 67 ++ src/storage/compaction/ob_tablet_merge_ctx.h | 2 + .../compaction/ob_tenant_tablet_scheduler.cpp | 8 +- .../compaction/ob_tenant_tablet_scheduler.h | 7 +- src/storage/ddl/ob_complement_data_task.cpp | 10 +- src/storage/ddl/ob_ddl_clog.cpp | 6 +- src/storage/ddl/ob_ddl_clog.h | 10 +- src/storage/ddl/ob_ddl_inc_clog.cpp | 104 ++ src/storage/ddl/ob_ddl_inc_clog.h | 79 ++ src/storage/ddl/ob_ddl_inc_clog_callback.cpp | 241 +++++ src/storage/ddl/ob_ddl_inc_clog_callback.h | 100 ++ .../ddl/ob_ddl_inc_redo_log_writer.cpp | 747 +++++++++++++ src/storage/ddl/ob_ddl_inc_redo_log_writer.h | 152 +++ src/storage/ddl/ob_ddl_merge_task.cpp | 261 ++++- src/storage/ddl/ob_ddl_merge_task.h | 11 +- src/storage/ddl/ob_ddl_redo_log_replayer.cpp | 35 + src/storage/ddl/ob_ddl_redo_log_replayer.h | 3 + .../ddl/ob_ddl_redo_log_row_iterator.cpp | 119 +++ .../ddl/ob_ddl_redo_log_row_iterator.h | 49 + src/storage/ddl/ob_ddl_redo_log_writer.cpp | 72 +- src/storage/ddl/ob_ddl_redo_log_writer.h | 55 +- src/storage/ddl/ob_ddl_replay_executor.cpp | 339 +++++- src/storage/ddl/ob_ddl_replay_executor.h | 61 +- src/storage/ddl/ob_ddl_struct.cpp | 120 ++- src/storage/ddl/ob_ddl_struct.h | 63 +- .../ddl/ob_direct_insert_sstable_ctx_new.cpp | 413 ++++++-- .../ddl/ob_direct_insert_sstable_ctx_new.h | 65 +- src/storage/ddl/ob_direct_load_struct.cpp | 119 ++- src/storage/ddl/ob_direct_load_struct.h | 30 +- src/storage/ddl/ob_tablet_ddl_kv.cpp | 634 ++++++++++- src/storage/ddl/ob_tablet_ddl_kv.h | 153 ++- .../ob_direct_load_fast_heap_table.cpp | 46 +- .../ob_direct_load_fast_heap_table.h | 11 - ...ob_direct_load_fast_heap_table_builder.cpp | 182 +--- .../ob_direct_load_fast_heap_table_builder.h | 64 +- .../ob_direct_load_insert_table_ctx.cpp | 788 ++++++++++---- .../ob_direct_load_insert_table_ctx.h | 226 +++- ..._direct_load_insert_table_row_iterator.cpp | 148 +-- ...ob_direct_load_insert_table_row_iterator.h | 46 +- .../ob_direct_load_lob_builder.cpp | 58 +- .../direct_load/ob_direct_load_lob_builder.h | 29 +- .../direct_load/ob_direct_load_merge_ctx.cpp | 135 +-- .../direct_load/ob_direct_load_merge_ctx.h | 38 +- .../ob_direct_load_partition_merge_task.cpp | 334 ++---- .../ob_direct_load_partition_merge_task.h | 48 +- .../ob_direct_load_table_store.cpp | 18 +- .../direct_load/ob_direct_load_table_store.h | 19 +- .../ob_tablet_backfill_tx.cpp | 4 +- src/storage/ls/ob_freezer.cpp | 875 ++++++++-------- src/storage/ls/ob_freezer.h | 53 +- src/storage/ls/ob_ls.cpp | 88 +- src/storage/ls/ob_ls.h | 11 +- src/storage/ls/ob_ls_ddl_log_handler.h | 2 + src/storage/ls/ob_ls_tablet_service.cpp | 4 +- src/storage/ls/ob_ls_tablet_service.h | 4 +- src/storage/memtable/mvcc/ob_mvcc.h | 14 +- src/storage/memtable/mvcc/ob_mvcc_engine.cpp | 3 - src/storage/memtable/mvcc/ob_mvcc_engine.h | 22 +- src/storage/memtable/mvcc/ob_mvcc_trans_ctx.h | 12 +- src/storage/memtable/mvcc/ob_query_engine.h | 1 - src/storage/memtable/ob_memtable.cpp | 982 +++++------------- src/storage/memtable/ob_memtable.h | 347 ++----- .../memtable/ob_memtable_interface.cpp | 60 +- src/storage/memtable/ob_memtable_interface.h | 154 +-- .../meta_mem/ob_tenant_meta_mem_mgr.cpp | 38 +- src/storage/meta_mem/ob_tenant_meta_mem_mgr.h | 7 +- src/storage/ob_direct_load_table_guard.cpp | 245 +++++ src/storage/ob_direct_load_table_guard.h | 66 ++ src/storage/ob_i_memtable_mgr.cpp | 28 +- src/storage/ob_i_memtable_mgr.h | 55 +- .../ob_i_partition_component_factory.h | 55 - src/storage/ob_i_table.cpp | 81 +- src/storage/ob_i_table.h | 46 +- src/storage/ob_i_tablet_memtable.cpp | 341 ++++++ src/storage/ob_i_tablet_memtable.h | 380 +++++++ .../ob_partition_component_factory.cpp | 76 -- src/storage/ob_partition_component_factory.h | 58 -- .../ob_protected_memtable_mgr_handle.h | 31 +- src/storage/ob_storage_table_guard.cpp | 185 ++-- src/storage/ob_storage_table_guard.h | 34 +- src/storage/tablelock/ob_lock_memtable.cpp | 4 +- src/storage/tablelock/ob_lock_memtable.h | 6 +- .../tablelock/ob_lock_memtable_mgr.cpp | 13 +- src/storage/tablelock/ob_lock_memtable_mgr.h | 9 +- src/storage/tablelock/ob_lock_table.cpp | 6 +- .../tablelock/ob_table_lock_callback.cpp | 4 +- .../tablelock/ob_table_lock_callback.h | 4 +- src/storage/tablet/ob_table_store_util.cpp | 14 +- src/storage/tablet/ob_table_store_util.h | 4 +- src/storage/tablet/ob_tablet.cpp | 122 +-- src/storage/tablet/ob_tablet.h | 45 +- .../tablet/ob_tablet_create_sstable_param.cpp | 8 +- .../tablet/ob_tablet_create_sstable_param.h | 4 +- src/storage/tablet/ob_tablet_memtable_mgr.cpp | 757 ++++++++------ src/storage/tablet/ob_tablet_memtable_mgr.h | 120 +-- src/storage/tablet/ob_tablet_persister.cpp | 2 +- src/storage/tablet/ob_tablet_persister.h | 2 +- .../tx/ob_direct_load_tx_ctx_define.cpp | 337 ++++++ src/storage/tx/ob_direct_load_tx_ctx_define.h | 141 +++ src/storage/tx/ob_trans_ctx_mgr_v4.h | 2 +- src/storage/tx/ob_trans_define.cpp | 7 +- src/storage/tx/ob_trans_define.h | 5 +- src/storage/tx/ob_trans_part_ctx.cpp | 205 +++- src/storage/tx/ob_trans_part_ctx.h | 28 + src/storage/tx/ob_trans_service.h | 18 +- src/storage/tx/ob_trans_submit_log_cb.cpp | 14 +- src/storage/tx/ob_trans_submit_log_cb.h | 20 +- src/storage/tx/ob_tx_log.cpp | 103 ++ src/storage/tx/ob_tx_log.h | 271 ++++- src/storage/tx/ob_tx_log_operator.h | 784 ++++++++++++++ src/storage/tx/ob_tx_replay_executor.cpp | 13 + src/storage/tx/ob_tx_replay_executor.h | 2 +- src/storage/tx_storage/ob_tenant_freezer.cpp | 2 +- src/storage/tx_table/ob_tx_ctx_memtable.cpp | 4 +- src/storage/tx_table/ob_tx_ctx_memtable.h | 6 +- .../tx_table/ob_tx_ctx_memtable_mgr.cpp | 15 +- src/storage/tx_table/ob_tx_ctx_memtable_mgr.h | 7 +- src/storage/tx_table/ob_tx_data_memtable.h | 6 +- .../tx_table/ob_tx_data_memtable_mgr.cpp | 20 +- .../tx_table/ob_tx_data_memtable_mgr.h | 16 +- src/storage/tx_table/ob_tx_data_table.cpp | 3 +- src/storage/tx_table/ob_tx_table.cpp | 3 +- .../data/misc/load_data_inc0.csv | 2 + .../data/misc/load_data_inc1.csv | 2 + .../data/misc/load_data_inc2.csv | 2 + .../test_ob_cdc_part_trans_resolver.cpp | 2 +- .../storage_perf/ob_storage_perf_data.h | 1 - .../storage_perf/ob_storage_perf_read.h | 2 - .../mock_ob_partition_component_factory.h | 69 -- .../mockcontainer/mock_ob_partition_service.h | 4 +- .../storage/mockcontainer/mock_ob_server.h | 2 - unittest/storage/perf_external_sort.cpp | 1 - unittest/storage/test_compaction_policy.cpp | 6 +- .../test_multi_version_sorted_stores.cpp | 794 -------------- .../storage/test_partition_range_splite.cpp | 1 - .../test_protected_memtable_mgr_handle.cpp | 6 +- unittest/storage/tx/it/tx_node.cpp | 1 - .../storage/tx_table/test_tx_ctx_table.cpp | 4 +- 278 files changed, 13417 insertions(+), 6679 deletions(-) create mode 100644 mittest/multi_replica/test_ob_direct_load_inc_log.cpp create mode 100644 mittest/simple_server/test_tablet_memtable_mit.cpp create mode 100644 src/observer/table_load/ob_table_load_index_long_wait.h create mode 100644 src/storage/ddl/ob_ddl_inc_clog.cpp create mode 100644 src/storage/ddl/ob_ddl_inc_clog.h create mode 100644 src/storage/ddl/ob_ddl_inc_clog_callback.cpp create mode 100644 src/storage/ddl/ob_ddl_inc_clog_callback.h create mode 100644 src/storage/ddl/ob_ddl_inc_redo_log_writer.cpp create mode 100644 src/storage/ddl/ob_ddl_inc_redo_log_writer.h create mode 100644 src/storage/ddl/ob_ddl_redo_log_row_iterator.cpp create mode 100644 src/storage/ddl/ob_ddl_redo_log_row_iterator.h create mode 100644 src/storage/ob_direct_load_table_guard.cpp create mode 100644 src/storage/ob_direct_load_table_guard.h delete mode 100644 src/storage/ob_i_partition_component_factory.h create mode 100644 src/storage/ob_i_tablet_memtable.cpp create mode 100644 src/storage/ob_i_tablet_memtable.h delete mode 100644 src/storage/ob_partition_component_factory.cpp delete mode 100644 src/storage/ob_partition_component_factory.h create mode 100644 src/storage/tx/ob_direct_load_tx_ctx_define.cpp create mode 100644 src/storage/tx/ob_direct_load_tx_ctx_define.h create mode 100644 src/storage/tx/ob_tx_log_operator.h create mode 100644 tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc0.csv create mode 100644 tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc1.csv create mode 100644 tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc2.csv delete mode 100644 unittest/storage/mock_ob_partition_component_factory.h delete mode 100644 unittest/storage/test_multi_version_sorted_stores.cpp diff --git a/deps/init/oceanbase.el7.aarch64.deps b/deps/init/oceanbase.el7.aarch64.deps index f32950451..76fce84fb 100644 --- a/deps/init/oceanbase.el7.aarch64.deps +++ b/deps/init/oceanbase.el7.aarch64.deps @@ -42,7 +42,7 @@ obdevtools-gcc9-9.3.0-52022092914.el7.aarch64.rpm obdevtools-llvm-11.0.1-312022092921.el7.aarch64.rpm [tools-deps] -devdeps-oblogmsg-1.0-182024030421.el7.aarch64.rpm +devdeps-oblogmsg-1.0-192024032014.el7.aarch64.rpm devdeps-rocksdb-6.22.1.1-52022100420.el7.aarch64.rpm obshell-4.2.3.0-102024031414.el7.aarch64.rpm target=community diff --git a/deps/init/oceanbase.el7.x86_64.deps b/deps/init/oceanbase.el7.x86_64.deps index f68e560f9..ecea0734e 100644 --- a/deps/init/oceanbase.el7.x86_64.deps +++ b/deps/init/oceanbase.el7.x86_64.deps @@ -45,7 +45,7 @@ obdevtools-gcc9-9.3.0-52022092914.el7.x86_64.rpm obdevtools-llvm-11.0.1-312022092921.el7.x86_64.rpm [tools-deps] -devdeps-oblogmsg-1.0-182024030421.el7.x86_64.rpm +devdeps-oblogmsg-1.0-192024032014.el7.x86_64.rpm devdeps-rocksdb-6.22.1.1-52022100420.el7.x86_64.rpm obshell-4.2.3.0-102024031414.el7.x86_64.rpm target=community diff --git a/deps/init/oceanbase.el8.aarch64.deps b/deps/init/oceanbase.el8.aarch64.deps index 5b2ab60a2..6a0b77f2c 100644 --- a/deps/init/oceanbase.el8.aarch64.deps +++ b/deps/init/oceanbase.el8.aarch64.deps @@ -42,7 +42,7 @@ obdevtools-gcc9-9.3.0-52022092914.el8.aarch64.rpm obdevtools-llvm-11.0.1-312022092921.el8.aarch64.rpm [tools-deps] -devdeps-oblogmsg-1.0-182024030421.el8.aarch64.rpm +devdeps-oblogmsg-1.0-192024032014.el8.aarch64.rpm devdeps-rocksdb-6.22.1.1-52022100420.el8.aarch64.rpm obshell-4.2.3.0-102024031414.el8.aarch64.rpm target=community diff --git a/deps/init/oceanbase.el8.x86_64.deps b/deps/init/oceanbase.el8.x86_64.deps index 9a0d4d606..5ade0fc9e 100644 --- a/deps/init/oceanbase.el8.x86_64.deps +++ b/deps/init/oceanbase.el8.x86_64.deps @@ -44,7 +44,7 @@ obdevtools-gcc9-9.3.0-52022092914.el8.x86_64.rpm obdevtools-llvm-11.0.1-312022092921.el8.x86_64.rpm [tools-deps] -devdeps-oblogmsg-1.0-182024030421.el8.x86_64.rpm +devdeps-oblogmsg-1.0-192024032014.el8.x86_64.rpm devdeps-rocksdb-6.22.1.1-52022100420.el8.x86_64.rpm obshell-4.2.3.0-102024031414.el8.x86_64.rpm target=community diff --git a/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h b/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h index d4a2ed4fb..618c313ad 100644 --- a/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h +++ b/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h @@ -845,7 +845,7 @@ PCODE_DEF(OB_CLEAR_TABLET_AUTOINC_SEQ_CACHE, 0x962) PCODE_DEF(OB_CHECK_AND_CANCEL_DDL_COMPLEMENT_DAG, 0x964) //PCODE_DEF(OB_CLEAN_SPLITTED_TABLET, 0x965) //PCODE_DEF(OB_REMOTE_WRITE_DDL_FINISH_LOG, 0x966) -//PCODE_DEF(OB_REMOTE_WRITE_DDL_INC_COMMIT_LOG, 0x967) +PCODE_DEF(OB_REMOTE_WRITE_DDL_INC_COMMIT_LOG, 0x967) //PCODE_DEF(OB_REMOTE_WRITE_DDL_INC_REDO_LOG, 0x968) // Depedency Detector diff --git a/deps/oblib/src/rpc/obrpc/ob_rpc_proxy.h b/deps/oblib/src/rpc/obrpc/ob_rpc_proxy.h index 696e93477..2d1982e00 100644 --- a/deps/oblib/src/rpc/obrpc/ob_rpc_proxy.h +++ b/deps/oblib/src/rpc/obrpc/ob_rpc_proxy.h @@ -166,7 +166,7 @@ public: || pcode == OB_CLEAN_SEQUENCE_CACHE || pcode == OB_FETCH_TABLET_AUTOINC_SEQ_CACHE || pcode == OB_BATCH_GET_TABLET_AUTOINC_SEQ || pcode == OB_BATCH_SET_TABLET_AUTOINC_SEQ || pcode == OB_CALC_COLUMN_CHECKSUM_REQUEST || pcode == OB_REMOTE_WRITE_DDL_REDO_LOG - || pcode == OB_REMOTE_WRITE_DDL_COMMIT_LOG); + || pcode == OB_REMOTE_WRITE_DDL_COMMIT_LOG || pcode == OB_REMOTE_WRITE_DDL_INC_COMMIT_LOG); } // when active is set as false, all RPC calls will simply return OB_INACTIVE_RPC_PROXY. diff --git a/mittest/logservice/test_ob_simple_log_single_replica_func.cpp b/mittest/logservice/test_ob_simple_log_single_replica_func.cpp index 145b6533d..3d5f6f2cc 100644 --- a/mittest/logservice/test_ob_simple_log_single_replica_func.cpp +++ b/mittest/logservice/test_ob_simple_log_single_replica_func.cpp @@ -348,7 +348,7 @@ TEST_F(TestObSimpleLogClusterSingleReplica, single_replica_flashback) EXPECT_GT(leader.palf_handle_impl_->sw_.get_max_scn(), flashback_scn); leader.palf_handle_impl_->state_mgr_.role_ = FOLLOWER; - leader.palf_handle_impl_->state_mgr_.state_ = ACTIVE; + leader.palf_handle_impl_->state_mgr_.state_ = ObReplicaState::ACTIVE; EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->flashback(mode_version, max_scn, timeout_ts_us)); EXPECT_LT(leader.palf_handle_impl_->sw_.get_max_scn(), flashback_scn); @@ -356,7 +356,7 @@ TEST_F(TestObSimpleLogClusterSingleReplica, single_replica_flashback) EXPECT_EQ(new_log_tail, leader.palf_handle_impl_->get_end_lsn()); EXPECT_EQ(OB_ITER_END, read_log(leader)); leader.palf_handle_impl_->state_mgr_.role_ = LEADER; - leader.palf_handle_impl_->state_mgr_.state_ = ACTIVE; + leader.palf_handle_impl_->state_mgr_.state_ = ObReplicaState::ACTIVE; dynamic_cast(get_cluster()[0]->get_palf_env())->log_loop_thread_.start(); switch_flashback_to_append(leader, mode_version); diff --git a/mittest/mtlenv/storage/checkpoint/test_checkpoint_executor.cpp b/mittest/mtlenv/storage/checkpoint/test_checkpoint_executor.cpp index 977861498..5de91ad62 100644 --- a/mittest/mtlenv/storage/checkpoint/test_checkpoint_executor.cpp +++ b/mittest/mtlenv/storage/checkpoint/test_checkpoint_executor.cpp @@ -71,6 +71,7 @@ void ObTableHandleV2::reset() } table_ = nullptr; t3m_ = nullptr; + table_type_ = ObITable::TableType::MAX_TABLE_TYPE; } } } @@ -120,9 +121,9 @@ public: bool ready_for_flush() { return ready_for_flush_; } - bool is_frozen_checkpoint() const { return true; } + bool is_frozen_checkpoint() { return true; } - bool is_active_checkpoint() const { return false; } + bool is_active_checkpoint() { return false; } void set_ready_for_flush(bool ready) { ready_for_flush_ = ready; } @@ -151,7 +152,7 @@ public: return rec_scn_; } - int flush(share::SCN recycle_scn, bool need_freeze = true) override { + int flush(share::SCN recycle_scn, const int64_t trace_id, bool need_freeze) override { share::SCN tmp; tmp.val_ = rec_scn_.val_ + 20; rec_scn_ = tmp; diff --git a/mittest/mtlenv/storage/checkpoint/test_data_checkpoint.cpp b/mittest/mtlenv/storage/checkpoint/test_data_checkpoint.cpp index 15e84e917..82d789b9f 100644 --- a/mittest/mtlenv/storage/checkpoint/test_data_checkpoint.cpp +++ b/mittest/mtlenv/storage/checkpoint/test_data_checkpoint.cpp @@ -67,6 +67,7 @@ void ObTableHandleV2::reset() } table_ = nullptr; t3m_ = nullptr; + table_type_ = ObITable::TableType::MAX_TABLE_TYPE; } } } @@ -107,9 +108,9 @@ public: bool ready_for_flush() { return ready_for_flush_; } - bool is_frozen_checkpoint() const { return is_frozen_; } + bool is_frozen_checkpoint() { return is_frozen_; } - bool is_active_checkpoint() const { return !is_frozen_; } + bool is_active_checkpoint() { return !is_frozen_; } ObTabletID get_tablet_id() const { return ObTabletID(111111111111); } diff --git a/mittest/mtlenv/storage/test_co_merge.cpp b/mittest/mtlenv/storage/test_co_merge.cpp index a1c39421a..b83df01f9 100644 --- a/mittest/mtlenv/storage/test_co_merge.cpp +++ b/mittest/mtlenv/storage/test_co_merge.cpp @@ -16,7 +16,6 @@ #include "lib/container/ob_iarray.h" #include "storage/column_store/ob_column_oriented_sstable.h" #include "storage/memtable/ob_memtable_interface.h" -#include "storage/ob_partition_component_factory.h" #include "storage/blocksstable/ob_data_file_prepare.h" #include "storage/blocksstable/ob_row_generate.h" #include "observer/ob_service.h" diff --git a/mittest/mtlenv/storage/test_ls_tablet_service.cpp b/mittest/mtlenv/storage/test_ls_tablet_service.cpp index 922288491..57bd721f7 100644 --- a/mittest/mtlenv/storage/test_ls_tablet_service.cpp +++ b/mittest/mtlenv/storage/test_ls_tablet_service.cpp @@ -1048,7 +1048,7 @@ TEST_F(TestLSTabletService, update_tablet_release_memtable_for_offline) ObTabletHandle tablet_handle; ASSERT_EQ(OB_SUCCESS, ls_handle.get_ls()->get_tablet_svr()->get_tablet(data_tablet_id, tablet_handle)); ASSERT_EQ(0, tablet_handle.get_obj()->memtable_count_); - ASSERT_EQ(OB_SUCCESS, ls_handle.get_ls()->get_tablet_svr()->create_memtable(data_tablet_id, 100)); + ASSERT_EQ(OB_SUCCESS, ls_handle.get_ls()->get_tablet_svr()->create_memtable(data_tablet_id, 100, false, false)); ASSERT_EQ(1, tablet_handle.get_obj()->memtable_count_); ASSERT_EQ(OB_SUCCESS, ls_handle.get_ls()->get_tablet_svr()->update_tablet_release_memtable_for_offline(data_tablet_id, SCN::max_scn())); diff --git a/mittest/mtlenv/storage/test_memtable_v2.cpp b/mittest/mtlenv/storage/test_memtable_v2.cpp index c6f04be5a..ea66ef08a 100644 --- a/mittest/mtlenv/storage/test_memtable_v2.cpp +++ b/mittest/mtlenv/storage/test_memtable_v2.cpp @@ -3580,10 +3580,13 @@ int ObTxCtxTable::release_ref_() return ret; } +void ObITabletMemtable::unset_logging_blocked_for_active_memtable_() +{ +} } // namespace storage -namespace memtable -{ +namespace memtable{ + int ObMemtable::lock_row_on_frozen_stores_( const storage::ObTableIterParam &, const ObTxNodeArg &, @@ -3599,9 +3602,6 @@ int ObMemtable::lock_row_on_frozen_stores_( return OB_SUCCESS; } } -void ObMemtable::unset_logging_blocked_for_active_memtable() -{ -} } namespace transaction diff --git a/mittest/mtlenv/storage/test_multi_version_merge_recycle.cpp b/mittest/mtlenv/storage/test_multi_version_merge_recycle.cpp index 9959fd84d..d531d5bc4 100644 --- a/mittest/mtlenv/storage/test_multi_version_merge_recycle.cpp +++ b/mittest/mtlenv/storage/test_multi_version_merge_recycle.cpp @@ -14,7 +14,6 @@ #define protected public #include "lib/container/ob_iarray.h" #include "storage/memtable/ob_memtable_interface.h" -#include "storage/ob_partition_component_factory.h" #include "storage/blocksstable/ob_data_file_prepare.h" #include "storage/blocksstable/ob_row_generate.h" #include "observer/ob_service.h" diff --git a/mittest/mtlenv/storage/test_multi_version_sstable_merge.cpp b/mittest/mtlenv/storage/test_multi_version_sstable_merge.cpp index bed7fc518..ceed7ab1b 100644 --- a/mittest/mtlenv/storage/test_multi_version_sstable_merge.cpp +++ b/mittest/mtlenv/storage/test_multi_version_sstable_merge.cpp @@ -16,7 +16,6 @@ #define UNITTEST #include "lib/container/ob_iarray.h" #include "storage/memtable/ob_memtable_interface.h" -#include "storage/ob_partition_component_factory.h" #include "storage/blocksstable/ob_data_file_prepare.h" #include "storage/blocksstable/ob_row_generate.h" #include "observer/ob_service.h" diff --git a/mittest/mtlenv/storage/test_tablet_create_delete_helper.cpp b/mittest/mtlenv/storage/test_tablet_create_delete_helper.cpp index b62e47e11..668128a3d 100644 --- a/mittest/mtlenv/storage/test_tablet_create_delete_helper.cpp +++ b/mittest/mtlenv/storage/test_tablet_create_delete_helper.cpp @@ -3142,7 +3142,7 @@ TEST_F(TestTabletCreateDeleteHelper, empty_memtable_replay_commit) ret = ObTabletCreateDeleteHelper::get_tablet(key, tablet_handle); ASSERT_EQ(OB_SUCCESS, ret); ObTableHandleV2 handle; - memtable::ObIMemtable *memtable; + ObIMemtable *memtable; ret = tablet_handle.get_obj()->get_active_memtable(handle); ASSERT_EQ(OB_SUCCESS, ret); ret = handle.get_memtable(memtable); @@ -3158,7 +3158,7 @@ TEST_F(TestTabletCreateDeleteHelper, empty_memtable_replay_commit) ASSERT_EQ(OB_SUCCESS, ret); ObTableHandleV2 new_handle; - memtable::ObIMemtable *new_memtable; + ObIMemtable *new_memtable; ret = tablet_handle.get_obj()->get_active_memtable(new_handle); ASSERT_EQ(OB_SUCCESS, ret); ret = new_handle.get_memtable(new_memtable); diff --git a/mittest/mtlenv/storage/test_tenant_meta_mem_mgr.cpp b/mittest/mtlenv/storage/test_tenant_meta_mem_mgr.cpp index 0e78ad71d..df1b0671e 100644 --- a/mittest/mtlenv/storage/test_tenant_meta_mem_mgr.cpp +++ b/mittest/mtlenv/storage/test_tenant_meta_mem_mgr.cpp @@ -36,27 +36,25 @@ namespace oceanbase { using namespace share; -namespace memtable +namespace memtable { + +int ObMemtable::batch_remove_unused_callback_for_uncommited_txn(const ObLSID, const memtable::ObMemtableSet *) { -int ObMemtable::get_ls_id(share::ObLSID &ls_id) + int ret = OB_SUCCESS; + return ret; +} + +} // namespace memtable + +namespace storage +{ + +int ObIMemtable::get_ls_id(share::ObLSID &ls_id) { ls_id = share::ObLSID(1001); return OB_SUCCESS; } -int ObMemtable::batch_remove_unused_callback_for_uncommited_txn( - const ObLSID , const memtable::ObMemtableSet *) -{ - int ret = OB_SUCCESS; - - return ret; -} - -} - -namespace storage -{ - int ObTablet::check_and_set_initial_state() { return OB_SUCCESS; @@ -435,9 +433,13 @@ TEST_F(TestTenantMetaMemMgr, test_memtable) int ret = OB_SUCCESS; ObTableHandleV2 handle; - ret = t3m_.acquire_memtable(handle); + bool for_inc_direct_load = false; + ret = t3m_.acquire_data_memtable(handle); ASSERT_EQ(common::OB_SUCCESS, ret); ASSERT_TRUE(nullptr != handle.table_); + handle.get_table()->set_table_type(ObITable::TableType::DATA_MEMTABLE); + + ASSERT_EQ(1, t3m_.memtable_pool_.inner_used_num_); ASSERT_EQ(1, handle.get_table()->get_ref()); @@ -467,6 +469,8 @@ TEST_F(TestTenantMetaMemMgr, test_tx_ctx_memtable) ret = t3m_.acquire_tx_ctx_memtable(handle); ASSERT_EQ(common::OB_SUCCESS, ret); ASSERT_TRUE(nullptr != handle.table_); + handle.get_table()->set_table_type(ObITable::TableType::TX_CTX_MEMTABLE); + ASSERT_EQ(1, t3m_.tx_ctx_memtable_pool_.inner_used_num_); ASSERT_EQ(1, handle.get_table()->get_ref()); @@ -496,6 +500,8 @@ TEST_F(TestTenantMetaMemMgr, test_tx_data_memtable) ret = t3m_.acquire_tx_data_memtable(handle); ASSERT_EQ(common::OB_SUCCESS, ret); ASSERT_TRUE(nullptr != handle.table_); + handle.get_table()->set_table_type(ObITable::TableType::TX_DATA_MEMTABLE); + ASSERT_EQ(1, t3m_.tx_data_memtable_pool_.inner_used_num_); ASSERT_EQ(1, handle.get_table()->get_ref()); @@ -525,6 +531,8 @@ TEST_F(TestTenantMetaMemMgr, test_lock_memtable) ret = t3m_.acquire_lock_memtable(handle); ASSERT_EQ(common::OB_SUCCESS, ret); ASSERT_TRUE(nullptr != handle.table_); + handle.get_table()->set_table_type(ObITable::TableType::LOCK_MEMTABLE); + ASSERT_EQ(1, t3m_.lock_memtable_pool_.inner_used_num_); ASSERT_EQ(1, handle.get_table()->get_ref()); @@ -1396,7 +1404,7 @@ TEST_F(TestTenantMetaMemMgr, test_table_gc) ObTableHandleV2 tx_data_memtable_handle; ObTableHandleV2 tx_ctx_memtable_handle; ObTableHandleV2 lock_memtable_handle; - ASSERT_EQ(OB_SUCCESS, t3m_.acquire_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, t3m_.acquire_data_memtable(memtable_handle)); ASSERT_EQ(OB_SUCCESS, t3m_.acquire_tx_data_memtable(tx_data_memtable_handle)); ASSERT_EQ(OB_SUCCESS, t3m_.acquire_tx_ctx_memtable(tx_ctx_memtable_handle)); ASSERT_EQ(OB_SUCCESS, t3m_.acquire_lock_memtable(lock_memtable_handle)); diff --git a/mittest/mtlenv/test_tx_data_table.cpp b/mittest/mtlenv/test_tx_data_table.cpp index 5174a29a9..aafd7770c 100644 --- a/mittest/mtlenv/test_tx_data_table.cpp +++ b/mittest/mtlenv/test_tx_data_table.cpp @@ -90,7 +90,6 @@ public: } else { tablet_id_ = tablet_id; t3m_ = t3m; - table_type_ = ObITable::TableType::TX_DATA_MEMTABLE; freezer_ = freezer; tx_data_table_ = tx_data_table; ls_tablet_svr_ = ls_handle.get_ls()->get_tablet_svr(); @@ -128,6 +127,11 @@ public: return ret; } + void destroy() + { + mgr_.destroy(); + } + private: virtual ObTxDataMemtableMgr *get_memtable_mgr_() { @@ -349,7 +353,7 @@ void TestTxDataTable::init_memtable_mgr_(ObTxDataMemtableMgr *memtable_mgr) { ASSERT_NE(nullptr, memtable_mgr); memtable_mgr->set_freezer(&tx_data_table_.freezer_); - ASSERT_EQ(OB_SUCCESS, memtable_mgr->create_memtable(SCN::min_scn(), 1, SCN::min_scn())); + ASSERT_EQ(OB_SUCCESS, memtable_mgr->create_memtable(CreateMemtableArg(1, SCN::min_scn(), SCN::min_scn(), false, false))); ASSERT_EQ(1, memtable_mgr->get_memtable_count_()); } @@ -385,6 +389,7 @@ void TestTxDataTable::do_basic_test() ObTxDataMemtableMgr *memtable_mgr = tx_data_table_.get_memtable_mgr_(); init_memtable_mgr_(memtable_mgr); + fprintf(stdout, "start insert tx data\n"); insert_tx_data_(); fprintf(stdout, "start insert rollback tx data\n"); @@ -445,8 +450,7 @@ void TestTxDataTable::do_basic_test() } // free memtable - freezing_memtable->reset(); - active_memtable->reset(); + memtable_mgr->offline(); } void TestTxDataTable::do_undo_status_test() @@ -564,6 +568,7 @@ void TestTxDataTable::do_tx_data_serialize_test() test_serialize_with_action_cnt_(TX_DATA_UNDO_ACT_MAX_NUM_PER_NODE * 100); test_serialize_with_action_cnt_(TX_DATA_UNDO_ACT_MAX_NUM_PER_NODE * 100 + 1); test_commit_versions_serialize_(); + memtable_mgr->offline(); } void TestTxDataTable::test_commit_versions_serialize_() @@ -632,7 +637,7 @@ void TestTxDataTable::do_repeat_insert_test() { ObTxDataMemtableMgr *memtable_mgr = tx_data_table_.get_memtable_mgr_(); ASSERT_NE(nullptr, memtable_mgr); memtable_mgr->set_freezer(&tx_data_table_.freezer_); - ASSERT_EQ(OB_SUCCESS, memtable_mgr->create_memtable(SCN::min_scn(), 1, SCN::min_scn())); + ASSERT_EQ(OB_SUCCESS, memtable_mgr->create_memtable(CreateMemtableArg(1, SCN::min_scn(), SCN::min_scn(), false, false))); ASSERT_EQ(1, memtable_mgr->get_memtable_count_()); insert_start_scn.convert_for_logservice(ObTimeUtil::current_time_ns()); diff --git a/mittest/multi_replica/CMakeLists.txt b/mittest/multi_replica/CMakeLists.txt index 1297dd0f6..9fb2c9971 100644 --- a/mittest/multi_replica/CMakeLists.txt +++ b/mittest/multi_replica/CMakeLists.txt @@ -37,3 +37,4 @@ ob_unittest_multi_replica(test_ob_dup_table_tablet_gc) ob_unittest_multi_replica(test_ob_dup_table_new_gc) ob_unittest_multi_replica(test_mds_replay_from_ctx_table) ob_unittest_multi_replica_longer_timeout(test_multi_transfer_tx) +ob_unittest_multi_replica(test_ob_direct_load_inc_log) diff --git a/mittest/multi_replica/test_ob_direct_load_inc_log.cpp b/mittest/multi_replica/test_ob_direct_load_inc_log.cpp new file mode 100644 index 000000000..7d2c2b1c5 --- /dev/null +++ b/mittest/multi_replica/test_ob_direct_load_inc_log.cpp @@ -0,0 +1,191 @@ +/** + * 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. + */ + +#include +#define USING_LOG_PREFIX SERVER +#define protected public +#define private public + +#include "env/ob_fast_bootstrap.h" +#include "env/ob_multi_replica_util.h" +#include "lib/mysqlclient/ob_mysql_result.h" +#include "storage/tx/ob_dup_table_lease.h" + +using namespace oceanbase::transaction; +using namespace oceanbase::storage; + +#define CUR_TEST_CASE_NAME ObDirectLoadIncLogTest + +DEFINE_MULTI_ZONE_TEST_CASE_CLASS + +MULTI_REPLICA_TEST_MAIN_FUNCTION(test_direct_load_inc_); + +#define DEFAULT_LOAD_ROW_CNT 30 + +namespace oceanbase +{ +namespace unittest +{ +class ObTestExtraLogCb : public logservice::AppendCb +{ +public: + int on_success() + { + int ret = OB_SUCCESS; + TRANS_LOG(INFO, "[ObMultiReplicaTestBase] invoke test on_success", K(ret), KP(this)); + return ret; + } + int on_failure() + { + int ret = OB_SUCCESS; + TRANS_LOG(INFO, "[ObMultiReplicaTestBase] invoke test on_failure", K(ret), KP(this)); + return ret; + } +}; + +void submit_ddl_redo_log(transaction::ObPartTransCtx *tx_ctx) +{ + ObDDLRedoLog ddl_redo; + + for (int i = 0; i < 5; i++) { + ObTestExtraLogCb *test_log_cb = + static_cast(ob_malloc(sizeof(ObTestExtraLogCb), "TestExtralCb")); + new (test_log_cb) ObTestExtraLogCb(); + int64_t replay_hint = GETTID(); + share::SCN scn; + scn.set_max(); + + ASSERT_EQ(OB_SUCCESS, + tx_ctx->submit_direct_load_inc_redo_log(ddl_redo, test_log_cb, replay_hint, scn)); + + usleep(1000); + } +} + +void submit_ddl_start_log(transaction::ObPartTransCtx *tx_ctx) +{ + storage::ObDDLIncStartLog ddl_start; + ddl_start.log_basic_.tablet_id_ = 101;//GETTID(); + + ObTestExtraLogCb *test_log_cb = + static_cast(ob_malloc(sizeof(ObTestExtraLogCb), "TestExtralCb")); + new (test_log_cb) ObTestExtraLogCb(); + int64_t replay_hint = 0; + share::SCN scn; + scn.set_max(); + + ASSERT_EQ(OB_SUCCESS, tx_ctx->submit_direct_load_inc_start_log(ddl_start, test_log_cb, scn)); +} + +void submit_ddl_end_log(transaction::ObPartTransCtx *tx_ctx) +{ + storage::ObDDLIncCommitLog ddl_commit; + ddl_commit.log_basic_.tablet_id_ = 101;//GETTID(); + + ObTestExtraLogCb *test_log_cb = + static_cast(ob_malloc(sizeof(ObTestExtraLogCb), "TestExtralCb")); + new (test_log_cb) ObTestExtraLogCb(); + int64_t replay_hint = 0; + share::SCN scn; + scn.set_max(); + + ASSERT_EQ(OB_SUCCESS, tx_ctx->submit_direct_load_inc_commit_log(ddl_commit, test_log_cb, scn)); +} + +TEST_F(GET_ZONE_TEST_CLASS_NAME(1), create_table) +{ + + int ret = OB_SUCCESS; + CREATE_TEST_TENANT(test_tenant_id); + SERVER_LOG(INFO, "[ObMultiReplicaTestBase] create test tenant success", K(test_tenant_id)); + + common::ObMySQLProxy &test_tenant_sql_proxy = get_curr_simple_server().get_sql_proxy2(); + + ACQUIRE_CONN_FROM_SQL_PROXY(test_conn, test_tenant_sql_proxy); + + WRITE_SQL_BY_CONN(test_conn, + "CREATE TABLE test_t1( " + "id_x int, " + "id_y int, " + "id_z int, " + "PRIMARY KEY(id_x)" + ") duplicate_scope='cluster' PARTITION BY hash(id_x) partitions 10;"); + + std::string primary_zone_sql = "ALTER TENANT " + std::string(DEFAULT_TEST_TENANT_NAME) + + " set primary_zone='zone1; zone3; zone2';"; + WRITE_SQL_BY_CONN(test_conn, primary_zone_sql.c_str()); + + READ_SQL_BY_CONN(test_conn, table_info_result, + "select table_id, duplicate_scope from " + "oceanbase.__all_table where table_name = 'test_t1' "); + + ASSERT_EQ(OB_SUCCESS, table_info_result->next()); + int64_t table_id; + int64_t dup_scope; + ASSERT_EQ(OB_SUCCESS, table_info_result->get_int("table_id", table_id)); + ASSERT_EQ(OB_SUCCESS, table_info_result->get_int("duplicate_scope", dup_scope)); + ASSERT_EQ(true, table_id > 0); + ASSERT_EQ(true, dup_scope != 0); + + std::string tablet_count_sql = + "select count(*), ls_id from oceanbase.__all_tablet_to_ls where table_id = " + + std::to_string(table_id) + " group by ls_id order by count(*)"; + READ_SQL_BY_CONN(test_conn, tablet_count_result, tablet_count_sql.c_str()); + int64_t tablet_count = 0; + int64_t ls_id_num = 0; + ASSERT_EQ(OB_SUCCESS, tablet_count_result->next()); + ASSERT_EQ(OB_SUCCESS, tablet_count_result->get_int("count(*)", tablet_count)); + ASSERT_EQ(OB_SUCCESS, tablet_count_result->get_int("ls_id", ls_id_num)); + ASSERT_EQ(10, tablet_count); + ASSERT_EQ(true, share::ObLSID(ls_id_num).is_valid()); + + GET_LS(test_tenant_id, ls_id_num, ls_handle); + + WRITE_SQL_BY_CONN(test_conn, "set autocommit = false;"); + WRITE_SQL_BY_CONN(test_conn, "begin;"); + + for (int i = 1; i <= DEFAULT_LOAD_ROW_CNT; i++) { + std::string insert_sql_str = "INSERT INTO test_t1 VALUES(" + std::to_string(i) + ", 0 , 0)"; + WRITE_SQL_BY_CONN(test_conn, insert_sql_str.c_str()); + } + + int64_t tx_id_num; + // GET_RUNNGING_TRX_ID(test_conn, tx_id_num); + std::string template_sql_str = "INSERT INTO test_t1 VALUES(" + std::to_string(1) + ", 0 , 0)"; + GET_TX_ID_FROM_SQL_AUDIT(test_conn, template_sql_str.c_str(), tx_id_num); + + transaction::ObPartTransCtx *tx_ctx = nullptr; + ASSERT_EQ(OB_SUCCESS, ls_handle.get_ls()->get_tx_ctx(ObTransID(tx_id_num), false, tx_ctx)); + + TRANS_LOG(INFO, "[ObMultiReplicaTestBase] get target tx ctx", K(ret), K(tx_id_num), KPC(tx_ctx)); + + submit_ddl_start_log(tx_ctx); + + std::thread t1(submit_ddl_redo_log, tx_ctx); + std::thread t2(submit_ddl_redo_log, tx_ctx); + std::thread t3(submit_ddl_redo_log, tx_ctx); + std::thread t4(submit_ddl_redo_log, tx_ctx); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + // submit_ddl_end_log(tx_ctx); + + WRITE_SQL_BY_CONN(test_conn, "commit;"); + + // Don't free log cb in thread +} +} // namespace unittest + +} // namespace oceanbase diff --git a/mittest/simple_server/CMakeLists.txt b/mittest/simple_server/CMakeLists.txt index 7014d8dc5..f24ba4780 100644 --- a/mittest/simple_server/CMakeLists.txt +++ b/mittest/simple_server/CMakeLists.txt @@ -105,6 +105,7 @@ ob_unittest_observer(test_ls_replica test_ls_replica.cpp) ob_unittest_observer(test_create_clone_tenant_resource_pool test_create_clone_tenant_resource_pool.cpp) ob_unittest_observer(test_ob_admin_arg test_ob_admin_arg.cpp) ob_unittest_observer(test_tablet_autoinc_mgr test_tablet_autoinc_mgr.cpp) +ob_unittest_observer(test_tablet_memtable_mit test_tablet_memtable_mit.cpp) ob_unittest_observer(test_tenant_snapshot_service test_tenant_snapshot_service.cpp) ob_unittest_observer(test_callbacks_with_reverse_order test_callbacks_with_reverse_order.cpp) ob_unittest_observer(test_transfer_tx_data test_transfer_with_smaller_tx_data.cpp) diff --git a/mittest/simple_server/test_memtable_new_safe_to_destroy.cpp b/mittest/simple_server/test_memtable_new_safe_to_destroy.cpp index ee4a95f3f..7a68fde86 100644 --- a/mittest/simple_server/test_memtable_new_safe_to_destroy.cpp +++ b/mittest/simple_server/test_memtable_new_safe_to_destroy.cpp @@ -194,14 +194,12 @@ TEST_F(ObTestMemtableNewSafeToDestroy, test_safe_to_destroy) WRITE_SQL_BY_CONN(user_connection, "begin;"); WRITE_SQL_FMT_BY_CONN(user_connection, "insert into qcc values(1);"); - - ASSERT_EQ(0, SSH::find_tx(user_connection, qcc_tx_id)); ObTableHandleV2 handle; ObTabletID tablet_id; ASSERT_EQ(0, SSH::select_table_tablet(tenant_id, "qcc", tablet_id)); get_memtable(tenant_id, share::ObLSID(1001), tablet_id, handle); - memtable::ObIMemtable *imemtable; + ObIMemtable *imemtable; handle.get_memtable(imemtable); memtable::ObMemtable *memtable = dynamic_cast(imemtable); TRANS_LOG(INFO, "qcc print", KPC(memtable)); @@ -221,7 +219,7 @@ TEST_F(ObTestMemtableNewSafeToDestroy, test_safe_to_destroy) handle.reset(); - storage::ObTabletMemtableMgr *memtable_mgr = memtable->get_memtable_mgr_(); + storage::ObTabletMemtableMgr *memtable_mgr = memtable->get_memtable_mgr(); EXPECT_EQ(OB_SUCCESS, memtable_mgr->release_memtables()); TRANS_LOG(INFO, "qcc print2", KPC(memtable));; diff --git a/mittest/simple_server/test_ob_minor_freeze.cpp b/mittest/simple_server/test_ob_minor_freeze.cpp index fdbbffaea..09315fd1c 100644 --- a/mittest/simple_server/test_ob_minor_freeze.cpp +++ b/mittest/simple_server/test_ob_minor_freeze.cpp @@ -37,15 +37,15 @@ namespace oceanbase { const int SLEEP_TIME = 100; -namespace memtable +namespace storage { -int64_t ObMemtable::inc_write_ref_() +int64_t ObITabletMemtable::inc_write_ref_() { ob_usleep(rand() % SLEEP_TIME); return ATOMIC_AAF(&write_ref_cnt_, 1); } -int64_t ObMemtable::dec_write_ref_() +int64_t ObITabletMemtable::dec_write_ref_() { ob_usleep(rand() % SLEEP_TIME); int64_t write_ref_cnt = ATOMIC_SAF(&write_ref_cnt_, 1); @@ -55,13 +55,13 @@ int64_t ObMemtable::dec_write_ref_() return write_ref_cnt; } -int64_t ObMemtable::inc_unsubmitted_cnt_() +int64_t ObITabletMemtable::inc_unsubmitted_cnt_() { ob_usleep(rand() % SLEEP_TIME); return ATOMIC_AAF(&unsubmitted_cnt_, 1); } -int64_t ObMemtable::dec_unsubmitted_cnt_() +int64_t ObITabletMemtable::dec_unsubmitted_cnt_() { ob_usleep(rand() % SLEEP_TIME); int64_t unsubmitted_cnt = ATOMIC_SAF(&unsubmitted_cnt_, 1); @@ -129,7 +129,6 @@ public: void tenant_freeze(); void logstream_freeze(); void tablet_freeze(); - void tablet_freeze_for_replace_tablet_meta(); void batch_tablet_freeze(); void insert_and_freeze(); void empty_memtable_flush(); @@ -374,28 +373,6 @@ void ObMinorFreezeTest::tablet_freeze() } } -void ObMinorFreezeTest::tablet_freeze_for_replace_tablet_meta() -{ - common::ObMySQLProxy &sql_proxy = get_curr_simple_server().get_sql_proxy2(); - share::ObTenantSwitchGuard tenant_guard; - OB_LOG(INFO, "tenant_id", K(RunCtx.tenant_id_)); - ASSERT_EQ(OB_SUCCESS, tenant_guard.switch_to(RunCtx.tenant_id_)); - const int64_t start = ObTimeUtility::current_time(); - while (ObTimeUtility::current_time() - start <= freeze_duration_) { - for (int j = 0; j < OB_DEFAULT_TABLE_COUNT; ++j) { - ObTableHandleV2 handle; - int ret = ls_handles_.at(j).get_ls()->get_freezer()->tablet_freeze_for_replace_tablet_meta(tablet_ids_.at(j), handle); - if (OB_EAGAIN == ret || OB_ENTRY_EXIST == ret) { - ret = OB_SUCCESS; - } - ASSERT_EQ(OB_SUCCESS, ret); - if (OB_SUCC(ret)) { - ASSERT_EQ(OB_SUCCESS, ls_handles_.at(j).get_ls()->get_freezer()->handle_frozen_memtable_for_replace_tablet_meta(tablet_ids_.at(j), handle)); - } - } - } -} - void ObMinorFreezeTest::batch_tablet_freeze() { common::ObMySQLProxy &sql_proxy = get_curr_simple_server().get_sql_proxy2(); @@ -416,7 +393,6 @@ void ObMinorFreezeTest::insert_and_freeze() std::thread tenant_freeze_thread([this]() { tenant_freeze(); }); std::thread tablet_freeze_thread([this]() { tablet_freeze(); }); std::thread logstream_freeze_thread([this]() { logstream_freeze(); }); - std::thread tablet_freeze_for_replace_tablet_meta_thread([this]() { tablet_freeze_for_replace_tablet_meta(); }); std::thread check_frozen_memtable_thread([this]() { check_frozen_memtable(); }); std::thread batch_tablet_freeze_thread([this]() { batch_tablet_freeze(); }); std::vector insert_threads; @@ -428,7 +404,6 @@ void ObMinorFreezeTest::insert_and_freeze() tenant_freeze_thread.join(); tablet_freeze_thread.join(); logstream_freeze_thread.join(); - tablet_freeze_for_replace_tablet_meta_thread.join(); check_frozen_memtable_thread.join(); batch_tablet_freeze_thread.join(); for (int i = 0; i < insert_thread_num_; ++i) { diff --git a/mittest/simple_server/test_tablet_memtable_mit.cpp b/mittest/simple_server/test_tablet_memtable_mit.cpp new file mode 100644 index 000000000..add8fd0fd --- /dev/null +++ b/mittest/simple_server/test_tablet_memtable_mit.cpp @@ -0,0 +1,360 @@ +/** + * 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. + */ + +#include + +#define protected public +#define private public + +#include "env/ob_simple_cluster_test_base.h" +#include "env/ob_simple_server_restart_helper.h" + +#include "storage/ddl/ob_tablet_ddl_kv.h" +#include "storage/tx_storage/ob_ls_service.h" +#include "storage/ob_direct_load_table_guard.h" + +#undef private +#undef protected + +static const char *TEST_FILE_NAME = "test_tablet_memtable_mit"; +static const char *BORN_CASE_NAME = "TestTabletMemtable"; +static const char *RESTART_CASE_NAME = "TestTabletMemtableRestart"; + +ObSimpleServerRestartHelper *helper_ptr = nullptr; + + +namespace oceanbase { + +using namespace observer; +using namespace memtable; +using namespace storage; +using namespace share; + +class TestRunCtx +{ +public: + uint64_t tenant_id_ = 0; +}; +TestRunCtx RunCtx; +ObLSID LS_ID; +ObTabletID TABLET_ID; + +namespace storage { + +int ObDDLKV::flush(ObLSID ls_id) +{ + int ret = OB_SUCCESS; + if (!ready_for_flush()) { + return OB_ERR_UNEXPECTED; + } else { + ObTabletMemtableMgr *mgr = get_memtable_mgr(); + ObTableHandleV2 handle; + EXPECT_EQ(OB_SUCCESS, mgr->get_first_frozen_memtable(handle)); + if (handle.get_table() == this) { + mgr->release_head_memtable_(this); + STORAGE_LOG(INFO, "flush and release one ddl kv ddl_kv", KP(this)); + } + } + return ret; +} + +} + +namespace unittest { + + +class TestTabletMemtable : public ObSimpleClusterTestBase { +public: + TestTabletMemtable() : ObSimpleClusterTestBase(TEST_FILE_NAME) {} + ~TestTabletMemtable() {} + + void basic_test(); + void create_test_table(const char* table_name); + +private: + common::ObArenaAllocator allocator_; // for medium info +}; + +#define EXE_SQL(sql_str) \ + ASSERT_EQ(OB_SUCCESS, sql.assign(sql_str)); \ + ASSERT_EQ(OB_SUCCESS, sql_proxy.write(sql.ptr(), affected_rows)); + +#define EXE_SQL_FMT(...) \ + ASSERT_EQ(OB_SUCCESS, sql.assign_fmt(__VA_ARGS__)); \ + ASSERT_EQ(OB_SUCCESS, sql_proxy.write(sql.ptr(), affected_rows)); + +#define WRITE_SQL_BY_CONN(conn, sql_str) \ + ASSERT_EQ(OB_SUCCESS, sql.assign(sql_str)); \ + ASSERT_EQ(OB_SUCCESS, conn->execute_write(OB_SYS_TENANT_ID, sql.ptr(), affected_rows)); + +#define WRITE_SQL_FMT_BY_CONN(conn, ...) \ + ASSERT_EQ(OB_SUCCESS, sql.assign_fmt(__VA_ARGS__)); \ + ASSERT_EQ(OB_SUCCESS, conn->execute_write(OB_SYS_TENANT_ID, sql.ptr(), affected_rows)); + +#define READ_SQL_FMT_BY_CONN(conn, res, ...) \ + ASSERT_EQ(OB_SUCCESS, sql.assign_fmt(__VA_ARGS__)); \ + ASSERT_EQ(OB_SUCCESS, conn->execute_read(OB_SYS_TENANT_ID, sql.ptr(), res)); + +#define DEF_VAL_FOR_SQL \ + int ret = OB_SUCCESS; \ + ObSqlString sql; \ + int64_t affected_rows = 0; \ + sqlclient::ObISQLConnection *connection = nullptr; + +void TestTabletMemtable::create_test_table(const char* table_name) +{ + DEF_VAL_FOR_SQL + ObString create_sql; + ASSERT_EQ(OB_SUCCESS, get_curr_simple_server().get_sql_proxy2().acquire(connection)); + WRITE_SQL_FMT_BY_CONN(connection, "create table if not exists %s (c1 int, c2 int)", table_name); + + HEAP_VAR(ObMySQLProxy::MySQLResult, res) + { + int64_t int_tablet_id = 0; + int64_t int_ls_id = 0; + int64_t retry_times = 10; + + READ_SQL_FMT_BY_CONN(connection, + res, + "SELECT tablet_id, ls_id FROM oceanbase.DBA_OB_TABLE_LOCATIONS WHERE TABLE_NAME = \'%s\'", + table_name); + common::sqlclient::ObMySQLResult *result = res.mysql_result(); + ASSERT_EQ(OB_SUCCESS, result->next()); + ASSERT_EQ(OB_SUCCESS, result->get_int("tablet_id", int_tablet_id)); + ASSERT_EQ(OB_SUCCESS, result->get_int("ls_id", int_ls_id)); + TABLET_ID = int_tablet_id; + LS_ID = int_ls_id; + fprintf(stdout, "get table info finish : tablet_id = %ld, ls_id = %ld\n", TABLET_ID.id(), LS_ID.id()); + } +} + +void TestTabletMemtable::basic_test() { + share::ObTenantSwitchGuard tenant_guard; + ASSERT_EQ(OB_SUCCESS, tenant_guard.switch_to(RunCtx.tenant_id_)); + + create_test_table("test_tablet_memtable"); + + ObLSService *ls_svr = MTL(ObLSService *); + ObLSHandle ls_handle; + ASSERT_EQ(1001, LS_ID.id()); + ASSERT_EQ(OB_SUCCESS, ls_svr->get_ls(LS_ID, ls_handle, ObLSGetMod::STORAGE_MOD)); + + ObLS *ls = nullptr; + ObLSIterator *ls_iter = nullptr; + ASSERT_NE(nullptr, ls = ls_handle.get_ls()); + + ObTabletHandle tablet_handle; + ObTablet *tablet = nullptr; + ASSERT_EQ(OB_SUCCESS, ls->get_tablet(TABLET_ID, tablet_handle)); + ASSERT_NE(nullptr, tablet = tablet_handle.get_obj()); + + // *********** CREATE DATA METMABLE ************ + ASSERT_EQ(OB_SUCCESS, tablet->create_memtable(1, SCN::min_scn(), false /*for_direct_load*/, false /*for_replay*/)); + ObProtectedMemtableMgrHandle *protected_handle = nullptr; + ASSERT_EQ(OB_SUCCESS, tablet->get_protected_memtable_mgr_handle(protected_handle)); + ASSERT_NE(nullptr, protected_handle); + ASSERT_EQ(true, protected_handle->has_memtable()); + + // *********** CHECK METMABLE TYPE ************ + ObTableHandleV2 memtable_handle; + ObITabletMemtable *memtable = nullptr; + ASSERT_EQ(OB_SUCCESS, protected_handle->get_active_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, memtable_handle.get_tablet_memtable(memtable)); + ASSERT_EQ(ObITable::TableType::DATA_MEMTABLE, memtable->get_table_type()); + + // *********** DO TABLET FREEZE ************ + ObFreezer *freezer = nullptr; + ASSERT_NE(nullptr, freezer = ls->get_freezer()); + ASSERT_EQ(OB_SUCCESS, ls->tablet_freeze(TABLET_ID, true /* is_sync */)); + ASSERT_EQ(OB_ENTRY_NOT_EXIST, protected_handle->get_active_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, protected_handle->get_boundary_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, memtable_handle.get_tablet_memtable(memtable)); + STORAGE_LOG(INFO, "finish freeze data memtable", KPC(memtable)); + + // *********** CREATE DIRECT LOAD MEMTABLE ************ + ASSERT_EQ(OB_SUCCESS, tablet->create_memtable(1, SCN::min_scn(), true /*for_direct_load*/, false /*for_replay*/)); + ASSERT_EQ(OB_SUCCESS, protected_handle->get_active_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, memtable_handle.get_tablet_memtable(memtable)); + ASSERT_EQ(ObITable::TableType::DIRECT_LOAD_MEMTABLE, memtable->get_table_type()); + STORAGE_LOG(INFO, "finish create direct load memtable", KPC(memtable)); + + // *********** GET DIRECT LOAD MEMTABLE FOR WRITE ************ + memtable->inc_write_ref(); + + // *********** CONCURRENT TABLET FREEZE ************ + ObFuture result; + int64_t freeze_start_time = ObClockGenerator::getClock(); + ASSERT_EQ(OB_SUCCESS, ls->tablet_freeze_with_rewrite_meta(TABLET_ID, &result)); + + sleep(2); + ASSERT_EQ(TabletMemtableFreezeState::ACTIVE, memtable->get_freeze_state()); + STORAGE_LOG(INFO, "waiting write finish", KPC(memtable)); + + // *********** DIRECT LOAD MEMTABLE WRITE FINISH ************ + memtable->dec_write_ref(); + ASSERT_EQ(OB_SUCCESS, ls->wait_freeze_finished(result)); + STORAGE_LOG(INFO, "write_ref_cnt should be zero", KPC(memtable)); + + // *********** CHECK FREEZE RESULT ************ + ASSERT_EQ(OB_ENTRY_NOT_EXIST, protected_handle->get_active_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, protected_handle->get_boundary_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, memtable_handle.get_tablet_memtable(memtable)); + STORAGE_LOG(INFO, "get boundary memtable", KPC(memtable)); + + ASSERT_EQ(ObITable::TableType::DIRECT_LOAD_MEMTABLE, memtable->get_table_type()); + ASSERT_NE(TabletMemtableFreezeState::ACTIVE, memtable->get_freeze_state()); + ASSERT_EQ(true, memtable->is_in_prepare_list_of_data_checkpoint()); + + // *********** CREATE ANOTHER DIRECT LOAD MEMTABLE ************ + ASSERT_EQ(OB_SUCCESS, tablet->create_memtable(1, SCN::min_scn(), true /*for_direct_load*/, false /*for_replay*/)); + ASSERT_EQ(OB_SUCCESS, protected_handle->get_active_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, memtable_handle.get_tablet_memtable(memtable)); + STORAGE_LOG(INFO, "create a new direct load memtable", KPC(memtable)); + + // *********** CONSTURCT A DIRECT LOAD TABLE GUARD ************ + SCN fake_ddl_redo_scn = SCN::plus(SCN::min_scn(), 10); + ObDirectLoadTableGuard direct_load_guard(*tablet, fake_ddl_redo_scn, false); + + // *********** CHECK DIRECT LOAD TABLE GUARD UASBLE ************ + ObDDLKV *memtable_for_direct_load = nullptr; + ASSERT_EQ(OB_SUCCESS, direct_load_guard.prepare_memtable(memtable_for_direct_load)); + ASSERT_EQ(OB_ERR_UNEXPECTED, direct_load_guard.prepare_memtable(memtable_for_direct_load)); + ASSERT_EQ(OB_SUCCESS, memtable_for_direct_load->set_rec_scn(fake_ddl_redo_scn)); + ASSERT_EQ(memtable, memtable_for_direct_load); + ASSERT_EQ(1, memtable_for_direct_load->get_write_ref()); + direct_load_guard.reset(); + ASSERT_EQ(0, memtable_for_direct_load->get_write_ref()); + + // *********** DO LOGSTREAM FREEZE ************ + ASSERT_EQ(OB_SUCCESS, ls->logstream_freeze(true /* is_sync */)); + STORAGE_LOG(INFO, "finish logstream freeze"); + + // *********** CHECK LOGSTREAM FREEZE RESULT ************ + ASSERT_EQ(OB_ENTRY_NOT_EXIST, protected_handle->get_active_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, protected_handle->get_boundary_memtable(memtable_handle)); + ASSERT_EQ(OB_SUCCESS, memtable_handle.get_tablet_memtable(memtable)); + ASSERT_EQ(ObITable::TableType::DIRECT_LOAD_MEMTABLE, memtable->get_table_type()); + + ASSERT_NE(TabletMemtableFreezeState::ACTIVE, memtable->get_freeze_state()); + ASSERT_EQ(true, memtable->is_in_prepare_list_of_data_checkpoint()); + STORAGE_LOG(INFO, "finish check logstream freeze result", KPC(memtable)); + + // *********** WAIT ALL MEMTABLES FLUSH ************ + int64_t retry_times = 0; + while (retry_times <= 10) { + sleep(1); + if (protected_handle->has_memtable()) { + ObSEArray handles; + ASSERT_EQ(OB_SUCCESS, protected_handle->get_all_memtables(handles)); + STORAGE_LOG(INFO, "wait all memtable flushed", K(retry_times)); + for (int i = 0; i < handles.count(); i++) { + ObITabletMemtable *memtable = static_cast(handles.at(i).get_table()); + STORAGE_LOG(INFO, "PRINT Table", K(memtable->key_), K(memtable->get_freeze_state())); + } + retry_times++; + } else { + break; + } + } + + ASSERT_FALSE(protected_handle->has_memtable()); + fprintf(stdout, "finish basic test\n"); +} + +TEST_F(TestTabletMemtable, observer_start) { SERVER_LOG(INFO, "observer_start succ"); } + +TEST_F(TestTabletMemtable, add_tenant) +{ + // create tenant + ASSERT_EQ(OB_SUCCESS, create_tenant()); + ASSERT_EQ(OB_SUCCESS, get_tenant_id(RunCtx.tenant_id_)); + ASSERT_NE(0, RunCtx.tenant_id_); + ASSERT_EQ(OB_SUCCESS, get_curr_simple_server().init_sql_proxy2()); +} + +TEST_F(TestTabletMemtable, init_config) +{ + DEF_VAL_FOR_SQL + common::ObMySQLProxy &sys_proxy = get_curr_simple_server().get_sql_proxy(); + sqlclient::ObISQLConnection *sys_conn = nullptr; + ASSERT_EQ(OB_SUCCESS, sys_proxy.acquire(sys_conn)); + ASSERT_NE(nullptr, sys_conn); + sleep(2); +} + +TEST_F(TestTabletMemtable, create_table) +{ + common::ObMySQLProxy &sql_proxy = get_curr_simple_server().get_sql_proxy2(); + + OB_LOG(INFO, "create_table start"); + ObSqlString sql; + int64_t affected_rows = 0; + EXE_SQL("create table if not exists test_tablet_memtable (c1 int, c2 int, primary key(c1))"); + OB_LOG(INFO, "create_table succ"); +} + +TEST_F(TestTabletMemtable, basic_test) +{ + basic_test(); +} + +class TestTabletMemtableRestart : public ObSimpleClusterTestBase +{ +public: + TestTabletMemtableRestart() : ObSimpleClusterTestBase(TEST_FILE_NAME) {} +private: + +}; + +TEST_F(TestTabletMemtableRestart, observer_restart) +{ + SERVER_LOG(INFO, "observer restart succ"); +} + +} // namespace unittest +} // namespace oceanbase + + +int main(int argc, char **argv) +{ + int c = 0; + int time_sec = 0; + int concurrency = 1; + char *log_level = (char *)"DEBUG"; + while (EOF != (c = getopt(argc, argv, "t:l:"))) { + switch (c) { + case 't': + time_sec = atoi(optarg); + break; + case 'l': + log_level = optarg; + oceanbase::unittest::ObSimpleClusterTestBase::enable_env_warn_log_ = false; + break; + case 'c': + concurrency = atoi(optarg); + break; + default: + break; + } + } + std::string gtest_file_name = std::string(TEST_FILE_NAME) + "_gtest.log"; + oceanbase::unittest::init_gtest_output(gtest_file_name); + + int ret = 0; + ObSimpleServerRestartHelper restart_helper(argc, argv, TEST_FILE_NAME, BORN_CASE_NAME, + RESTART_CASE_NAME); + helper_ptr = &restart_helper; + restart_helper.set_sleep_sec(time_sec); + restart_helper.run(); + + return ret; +} \ No newline at end of file diff --git a/mittest/simple_server/test_transfer_in_after_abort.cpp b/mittest/simple_server/test_transfer_in_after_abort.cpp index eb0cb1fd5..6acc2ccd6 100644 --- a/mittest/simple_server/test_transfer_in_after_abort.cpp +++ b/mittest/simple_server/test_transfer_in_after_abort.cpp @@ -221,7 +221,7 @@ public: void check_memtable_cleanout(ObTableHandleV2 &handle, const bool memtable_is_all_delay_cleanout) { - memtable::ObIMemtable *imemtable; + ObIMemtable *imemtable; handle.get_memtable(imemtable); memtable::ObMemtable *memtable = dynamic_cast(imemtable); diff --git a/mittest/simple_server/test_tx_data_table_mit.cpp b/mittest/simple_server/test_tx_data_table_mit.cpp index ef27484f9..d29d7cf91 100644 --- a/mittest/simple_server/test_tx_data_table_mit.cpp +++ b/mittest/simple_server/test_tx_data_table_mit.cpp @@ -375,7 +375,8 @@ void ObTxDataTableTest::check_minor_merge() sleep(1); } } - ASSERT_GT(cnt, 0); + // ASSERT_GT(cnt, 0); + // 确认没有未能转储的memtable retry_times = 10; diff --git a/src/logservice/libobcdc/src/ob_cdc_lob_ctx.cpp b/src/logservice/libobcdc/src/ob_cdc_lob_ctx.cpp index 12851e132..1961b9492 100644 --- a/src/logservice/libobcdc/src/ob_cdc_lob_ctx.cpp +++ b/src/logservice/libobcdc/src/ob_cdc_lob_ctx.cpp @@ -75,7 +75,7 @@ void ObLobDataGetCtx::reset() type_ = ObLobDataGetTaskType::FULL_LOB; host_ = nullptr; column_id_ = common::OB_INVALID_ID; - dml_flag_ = blocksstable::ObDmlFlag::DF_MAX; + dml_flag_.reset(); new_lob_data_ = nullptr; old_lob_data_ = nullptr; lob_col_value_handle_done_count_ = 0; @@ -87,7 +87,7 @@ void ObLobDataGetCtx::reset() void ObLobDataGetCtx::reset( void *host, const uint64_t column_id, - const blocksstable::ObDmlFlag &dml_flag, + const blocksstable::ObDmlRowFlag &dml_flag, const common::ObLobData *new_lob_data) { host_ = host; @@ -222,8 +222,8 @@ int64_t ObLobDataGetCtx::to_string(char *buf, const int64_t buf_len) const } (void)common::databuff_printf(buf, buf_len, pos, - "column_id=%ld, dml=%s, ref_cnt[new=%d, old=%d], handle_cnt=%d, type=%d, ", - column_id_, print_dml_flag(dml_flag_), new_lob_col_ctx_.get_col_ref_cnt(), + "column_id=%ld, dml_flag=%s, dml_serialize_flag=%d, ref_cnt[new=%d, old=%d], handle_cnt=%d, type=%d, ", + column_id_, dml_flag_.getFlagStr(), dml_flag_.get_serialize_flag(), new_lob_col_ctx_.get_col_ref_cnt(), old_lob_col_ctx_.get_col_ref_cnt(), lob_col_value_handle_done_count_, type_); if (nullptr != new_lob_data_) { diff --git a/src/logservice/libobcdc/src/ob_cdc_lob_ctx.h b/src/logservice/libobcdc/src/ob_cdc_lob_ctx.h index dede51f54..7e7733a10 100644 --- a/src/logservice/libobcdc/src/ob_cdc_lob_ctx.h +++ b/src/logservice/libobcdc/src/ob_cdc_lob_ctx.h @@ -13,12 +13,12 @@ #ifndef OCEANBASE_LIBOBCDC_LOB_CTX_H_ #define OCEANBASE_LIBOBCDC_LOB_CTX_H_ -#include "common/object/ob_object.h" // ObLobData, ObLobDataOutRowCtx -#include "storage/blocksstable/ob_datum_row.h" // ObDmlFlag -#include "lib/atomic/ob_atomic.h" // ATOMIC_** +#include "common/object/ob_object.h" // ObLobData, ObLobDataOutRowCtx +#include "storage/blocksstable/ob_datum_row.h" // ObDmlRowFlag +#include "lib/atomic/ob_atomic.h" // ATOMIC_** #include "lib/allocator/ob_allocator.h" #include "lib/ob_define.h" -#include "ob_log_lighty_list.h" // LightyList +#include "ob_log_lighty_list.h" // LightyList namespace oceanbase { @@ -75,13 +75,13 @@ struct ObLobDataGetCtx void reset( void *host, const uint64_t column_id, - const blocksstable::ObDmlFlag &dml_flag, + const blocksstable::ObDmlRowFlag &dml_flag, const common::ObLobData *new_lob_data); void set_old_lob_data(const common::ObLobData *old_lob_data) { old_lob_data_ = old_lob_data; } - bool is_insert() const { return blocksstable::ObDmlFlag::DF_INSERT == dml_flag_; } - bool is_update() const { return blocksstable::ObDmlFlag::DF_UPDATE == dml_flag_; } - bool is_delete() const { return blocksstable::ObDmlFlag::DF_DELETE == dml_flag_; } + bool is_insert() const { return dml_flag_.is_insert(); } + bool is_update() const { return dml_flag_.is_update(); } + bool is_delete() const { return dml_flag_.is_delete(); } bool is_ext_info_log() const { return ObLobDataGetTaskType::EXT_INFO_LOG == type_; } const common::ObLobData *get_lob_data(const bool is_new_col) const @@ -143,7 +143,7 @@ struct ObLobDataGetCtx ObLobDataGetTaskType type_; void *host_; // ObLobDataOutRowCtxList uint64_t column_id_; - blocksstable::ObDmlFlag dml_flag_; + blocksstable::ObDmlRowFlag dml_flag_; const common::ObLobData *new_lob_data_; const common::ObLobData *old_lob_data_; int8_t lob_col_value_handle_done_count_; diff --git a/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.cpp b/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.cpp index fee0231d6..94edf21c7 100644 --- a/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.cpp +++ b/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.cpp @@ -17,6 +17,7 @@ #include "ob_cdc_part_trans_resolver.h" #include "ob_log_cluster_id_filter.h" // ClusterIdFilter #include "logservice/logfetcher/ob_log_part_serve_info.h" // PartServeInfo +#include "ob_log_config.h" // TCONF namespace oceanbase { @@ -141,7 +142,8 @@ ObCDCPartTransResolver::ObCDCPartTransResolver( offlined_(false), tls_id_(), part_trans_dispatcher_(tls_id_str, task_pool, task_map, dispatcher), - cluster_id_filter_(cluster_id_filter) + cluster_id_filter_(cluster_id_filter), + enable_direct_load_inc_(false) {} ObCDCPartTransResolver::~ObCDCPartTransResolver() @@ -150,9 +152,11 @@ ObCDCPartTransResolver::~ObCDCPartTransResolver() int ObCDCPartTransResolver::init( const logservice::TenantLSID &tls_id, - const int64_t start_commit_version) + const int64_t start_commit_version, + const bool enable_direct_load_inc) { tls_id_ = tls_id; + enable_direct_load_inc_ = enable_direct_load_inc; return part_trans_dispatcher_.init(tls_id, start_commit_version); } @@ -429,6 +433,16 @@ int ObCDCPartTransResolver::read_trans_log_( } break; } + case transaction::ObTxLogType::TX_DIRECT_LOAD_INC_LOG: + { + if (OB_FAIL(handle_direct_load_inc_log_(tx_id, lsn, submit_ts, handling_miss_log, tx_log_block))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("handle_direct_load_inc_log_ fail", KR(ret), K_(tls_id), K(tx_id), K(tx_id), K(lsn), K(tx_log_header), + K(missing_info)); + } + } + break; + } case transaction::ObTxLogType::TX_RECORD_LOG: { if (OB_FAIL(handle_record_(tx_id, lsn, missing_info, tx_log_block))) { @@ -588,6 +602,60 @@ int ObCDCPartTransResolver::handle_multi_data_source_log_( return ret; } +int ObCDCPartTransResolver::handle_direct_load_inc_log_( + const transaction::ObTransID &tx_id, + const palf::LSN &lsn, + const int64_t submit_ts, + const bool handling_miss_log, + transaction::ObTxLogBlock &tx_log_block) +{ + int ret = OB_SUCCESS; + transaction::ObTxDirectLoadIncLog::TempRef tmp_ref; + transaction::ObTxDirectLoadIncLog direct_load_inc_log(tmp_ref); + PartTransTask *task = NULL; + + if (OB_FAIL(obtain_task_(tx_id, task, handling_miss_log))) { + LOG_ERROR("obtain_task_ fail", KR(ret), K_(tls_id), K(tx_id), K(lsn), K(handling_miss_log)); + } else if (OB_FAIL(push_fetched_log_entry_(lsn, *task))) { + if (OB_ENTRY_EXIST == ret) { + LOG_WARN("redo already fetched, ignore", KR(ret), K_(tls_id), K(tx_id), K(lsn), + "task_sorted_log_entry_info", task->get_sorted_log_entry_info()); + ret = OB_SUCCESS; + } else { + LOG_ERROR("push_fetched_log_entry failed", KR(ret), K_(tls_id), K(tx_id), K(lsn), KPC(task)); + } + } else if (!enable_direct_load_inc_) { + // ignore all direct load inc log + } else if (OB_FAIL(tx_log_block.deserialize_log_body(direct_load_inc_log))) { + LOG_ERROR("deserialize_direct_load_inc_log failed", KR(ret), K_(tls_id), K(tx_id), K(lsn)); + } else if (transaction::ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_REDO != direct_load_inc_log.get_ddl_log_type()) { + LOG_DEBUG("ignore DLI_START and DLI_END log", K_(tls_id), K(tx_id), K(lsn), K(direct_load_inc_log)); + } else { + transaction::ObTxDLIncLogBuf &log_buf = const_cast(direct_load_inc_log.get_dli_buf()); + + if (OB_FAIL(task->push_direct_load_inc_log( + tx_id, + lsn, + submit_ts, + log_buf.get_buf(), + log_buf.get_buf_size()))) { + if (OB_ENTRY_EXIST == ret) { + LOG_DEBUG("direct_load_inc_log duplication", KR(ret), K_(tls_id), K(tx_id), K(lsn), K(submit_ts), + K(direct_load_inc_log), K(handling_miss_log), K(task)); + ret = OB_SUCCESS; + } else if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("push_direct_load_inc_log into PartTransTask fail", KR(ret), K_(tls_id), K(tx_id), K(lsn), + K(handling_miss_log), K(task), K(direct_load_inc_log)); + } + } else { + LOG_DEBUG("handle_direct_load_inc_log", K_(tls_id), K(tx_id), K(lsn), K(submit_ts), K(direct_load_inc_log), + K(handling_miss_log), KPC(task)); + } + } + + return ret; +} + int ObCDCPartTransResolver::handle_record_( const transaction::ObTransID &tx_id, const palf::LSN &lsn, diff --git a/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.h b/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.h index c1e27d38b..01db14b5c 100644 --- a/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.h +++ b/src/logservice/libobcdc/src/ob_cdc_part_trans_resolver.h @@ -146,7 +146,8 @@ public: // init part_trans_resolver virtual int init( const logservice::TenantLSID &ls_id, - const int64_t start_commit_version) = 0; + const int64_t start_commit_version, + const bool enable_direct_load_inc) = 0; public: /// read log entry @@ -219,7 +220,8 @@ public: public: virtual int init( const logservice::TenantLSID &tls_id, - const int64_t start_commit_version); + const int64_t start_commit_version, + const bool enable_direct_load_inc); virtual int read( const char *buf, @@ -294,6 +296,14 @@ private: const bool handling_miss_log, transaction::ObTxLogBlock &tx_log_block); + // read ObTxDirectLoadIncLog + int handle_direct_load_inc_log_( + const transaction::ObTransID &tx_id, + const palf::LSN &lsn, + const int64_t submit_ts, + const bool handling_miss_log, + transaction::ObTxLogBlock &tx_log_block); + // read ObTxRecordLog int handle_record_( const transaction::ObTransID &tx_id, @@ -427,6 +437,7 @@ private: logservice::TenantLSID tls_id_; PartTransDispatcher part_trans_dispatcher_; IObLogClusterIDFilter &cluster_id_filter_; + bool enable_direct_load_inc_; private: DISALLOW_COPY_AND_ASSIGN(ObCDCPartTransResolver); }; diff --git a/src/logservice/libobcdc/src/ob_log_config.h b/src/logservice/libobcdc/src/ob_log_config.h index 4afe2a358..17ec00f49 100644 --- a/src/logservice/libobcdc/src/ob_log_config.h +++ b/src/logservice/libobcdc/src/ob_log_config.h @@ -607,6 +607,9 @@ public: DEF_CAP(print_mod_memory_usage_threshold, OB_CLUSTER_PARAMETER, "0M", "[0M,]", "print mod memory usage threshold"); DEF_STR(print_mod_memory_usage_label, OB_CLUSTER_PARAMETER, "|", "mod label for print memmory usage"); + // Whether to sync the incremental direct load data + T_DEF_BOOL(enable_direct_load_inc, OB_CLUSTER_PARAMETER, 0, "0:disabled, 1:enabled"); + #undef OB_CLUSTER_PARAMETER public: diff --git a/src/logservice/libobcdc/src/ob_log_entry_task_pool.cpp b/src/logservice/libobcdc/src/ob_log_entry_task_pool.cpp index b7bf1dabe..18ac31693 100644 --- a/src/logservice/libobcdc/src/ob_log_entry_task_pool.cpp +++ b/src/logservice/libobcdc/src/ob_log_entry_task_pool.cpp @@ -70,6 +70,7 @@ void ObLogEntryTaskPool::destroy() } int ObLogEntryTaskPool::alloc( + const bool is_direct_load_inc_log, ObLogEntryTask *&log_entry_task, PartTransTask &host) { @@ -83,7 +84,7 @@ int ObLogEntryTaskPool::alloc( ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc log_entry_task failed", KR(ret), K_(alloc_cnt), "memory_hold", allocator_.hold()); } else { - log_entry_task = new(ptr) ObLogEntryTask(host); + log_entry_task = new(ptr) ObLogEntryTask(host, is_direct_load_inc_log); ATOMIC_INC(&alloc_cnt_); } diff --git a/src/logservice/libobcdc/src/ob_log_entry_task_pool.h b/src/logservice/libobcdc/src/ob_log_entry_task_pool.h index 019342925..76cf56e0f 100644 --- a/src/logservice/libobcdc/src/ob_log_entry_task_pool.h +++ b/src/logservice/libobcdc/src/ob_log_entry_task_pool.h @@ -29,6 +29,7 @@ public: public: virtual int alloc( + const bool is_direct_load_inc_log, ObLogEntryTask *&task, PartTransTask &host) = 0; virtual void free(ObLogEntryTask *task) = 0; @@ -49,6 +50,7 @@ public: public: int alloc( + const bool is_direct_load_inc_log, ObLogEntryTask *&log_entry_task, PartTransTask &host) override; void free(ObLogEntryTask *log_entry_task) override; diff --git a/src/logservice/libobcdc/src/ob_log_fetcher.cpp b/src/logservice/libobcdc/src/ob_log_fetcher.cpp index 03bea71b4..beecfd064 100644 --- a/src/logservice/libobcdc/src/ob_log_fetcher.cpp +++ b/src/logservice/libobcdc/src/ob_log_fetcher.cpp @@ -84,6 +84,7 @@ ObLogFetcher::~ObLogFetcher() int ObLogFetcher::init( const bool is_loading_data_dict_baseline_data, + const bool enable_direct_load_inc, const ClientFetchingMode fetching_mode, const ObBackupPathString &archive_dest, IObLogFetcherDispatcher *dispatcher, @@ -200,6 +201,7 @@ int ObLogFetcher::init( heartbeat_dispatch_tid_ = 0; last_timestamp_ = OB_INVALID_TIMESTAMP; is_loading_data_dict_baseline_data_ = is_loading_data_dict_baseline_data; + enable_direct_load_inc_ = enable_direct_load_inc; fetching_mode_ = fetching_mode; archive_dest_ = archive_dest; log_ext_handler_concurrency_ = cfg.cdc_read_archive_log_concurrency; @@ -212,7 +214,7 @@ int ObLogFetcher::init( IObCDCPartTransResolver::test_checkpoint_mode_on = cfg.test_checkpoint_mode_on; IObCDCPartTransResolver::test_mode_ignore_log_type = static_cast(cfg.test_mode_ignore_log_type.get()); - LOG_INFO("init fetcher succ", K_(is_loading_data_dict_baseline_data), + LOG_INFO("init fetcher succ", K_(is_loading_data_dict_baseline_data), K(enable_direct_load_inc), "test_mode_on", IObCDCPartTransResolver::test_mode_on, "test_mode_ignore_log_type", IObCDCPartTransResolver::test_mode_ignore_log_type, "test_mode_ignore_redo_count", IObCDCPartTransResolver::test_mode_ignore_redo_count, @@ -441,7 +443,7 @@ int ObLogFetcher::add_ls( } // Push LS into ObLogLSFetchMgr else if (OB_FAIL(ls_fetch_mgr_.add_ls(tls_id, start_parameters, is_loading_data_dict_baseline_data_, - fetching_mode_, archive_dest_))) { + enable_direct_load_inc_, fetching_mode_, archive_dest_))) { LOG_ERROR("add partition by part fetch mgr fail", KR(ret), K(tls_id), K(start_parameters), K(is_loading_data_dict_baseline_data_)); } else if (OB_FAIL(ls_fetch_mgr_.get_ls_fetch_ctx(tls_id, ls_fetch_ctx))) { diff --git a/src/logservice/libobcdc/src/ob_log_fetcher.h b/src/logservice/libobcdc/src/ob_log_fetcher.h index c6979ed85..63782508b 100644 --- a/src/logservice/libobcdc/src/ob_log_fetcher.h +++ b/src/logservice/libobcdc/src/ob_log_fetcher.h @@ -135,6 +135,7 @@ public: int init( const bool is_loading_data_dict_baseline_data, + const bool enable_direct_load_inc, const ClientFetchingMode fetching_mode, const ObBackupPathString &archive_dest, IObLogFetcherDispatcher *dispatcher, @@ -259,6 +260,7 @@ private: bool is_inited_; bool is_running_; bool is_loading_data_dict_baseline_data_; + bool enable_direct_load_inc_; ClientFetchingMode fetching_mode_; ObBackupPathString archive_dest_; archive::LargeBufferPool large_buffer_pool_; diff --git a/src/logservice/libobcdc/src/ob_log_formatter.cpp b/src/logservice/libobcdc/src/ob_log_formatter.cpp index 6fa386529..87dadf5ca 100644 --- a/src/logservice/libobcdc/src/ob_log_formatter.cpp +++ b/src/logservice/libobcdc/src/ob_log_formatter.cpp @@ -453,7 +453,7 @@ int ObLogFormatter::init_binlog_record_for_dml_stmt_task_( } else { // select ... for update to record DF_LOCK log to prevent loss of row lock information on the // standby machine in the event of a master/standby switchover, no synchronization required - if (ObDmlFlag::DF_LOCK == stmt_task->get_dml_flag()) { + if (stmt_task->get_dml_flag().is_lock()) { is_ignore = true; } else { RecordType record_type = get_record_type(stmt_task->get_dml_flag()); @@ -702,8 +702,13 @@ int ObLogFormatter::check_table_need_ignore_( "table_id", table_schema->get_table_id(), "table_type", ob_table_type_str(table_schema->get_table_type())); - if (OB_FAIL(parse_aux_lob_meta_table_(dml_stmt_task))) { - LOG_ERROR("parse_aux_lob_meta_table_ failed", KR(ret), K(dml_stmt_task)); + // Incremental direct load doesn't support lob with outrow in phase1 and Observer will + // disallow the behavior which loads lob data with outrow. + bool need_parse_aux_lob_meta_table = true; + // need_parse_aux_lob_meta_table = !dml_stmt_task.get_redo_log_entry_task().get_redo_log_node()->is_direct_load_inc_log(); + if (need_parse_aux_lob_meta_table && OB_FAIL(parse_aux_lob_meta_table_(dml_stmt_task))) { + LOG_ERROR("parse_aux_lob_meta_table_ failed", KR(ret), K(need_parse_aux_lob_meta_table), + K(dml_stmt_task)); } // Filter sys tables that are not user tables and are not in backup mode } else if (! table_schema->is_user_table() @@ -805,7 +810,7 @@ void ObLogFormatter::handle_non_full_columns_( "commit_log_lsn", task.get_commit_log_lsn(), "commit_version", task.get_trans_commit_version(), "dml_type", dml_stmt_task.get_dml_flag(), - "dml_type_str", get_dml_str(dml_stmt_task.get_dml_flag()), + "dml_type_str", dml_stmt_task.get_dml_flag().getFlagStr(), "table_name", table_schema.get_table_name(), "table_id", table_schema.get_table_id(), K(dml_stmt_task)); @@ -1572,7 +1577,7 @@ int ObLogFormatter::fill_orig_default_value_( int ObLogFormatter::set_src_category_(IBinlogRecord *br_data, RowValue *rv, - const ObDmlFlag &dml_flag, + const ObDmlRowFlag &dml_flag, const bool is_hbase_mode_put) { int ret = OB_SUCCESS; @@ -1586,7 +1591,7 @@ int ObLogFormatter::set_src_category_(IBinlogRecord *br_data, // 1. INSERT statements are always set to full column log format // 2. DELETE and UPDATE must be populated with old values in full column logging mode, so if they are populated with old values, they are in full column logging format // 3. OB-HBase mode put special handling - if (ObDmlFlag::DF_INSERT == dml_flag || rv->contain_old_column_ || is_hbase_mode_put) { + if (dml_flag.is_insert() || rv->contain_old_column_ || is_hbase_mode_put) { src_category = SRC_FULL_RECORDED; } else { src_category = SRC_FULL_FAKED; @@ -1603,7 +1608,7 @@ int ObLogFormatter::build_binlog_record_( ObLogBR *br, RowValue *rv, const int64_t new_column_cnt, - const ObDmlFlag &dml_flag, + const ObDmlRowFlag &dml_flag, const TABLE_SCHEMA *simple_table_schema) { int ret = OB_SUCCESS; @@ -1646,17 +1651,16 @@ int ObLogFormatter::build_binlog_record_( br_data->setNewColumn(rv->new_column_array_, static_cast(rv->column_num_)); br_data->setOldColumn(rv->old_column_array_, static_cast(rv->column_num_)); - ObDmlFlag current_dml_flag = dml_flag; + ObDmlRowFlag current_dml_flag = dml_flag; if (is_hbase_mode_put) { - current_dml_flag = ObDmlFlag::DF_INSERT; - + current_dml_flag.set_flag(DF_INSERT); // modify record type RecordType type = get_record_type(current_dml_flag); if (OB_FAIL(br->setInsertRecordTypeForHBasePut(type))) { LOG_ERROR("br setInsertRecordTypeForHBasePut fail", KR(ret), K(br), "type", print_record_type(type), - "dml_flag", get_dml_str(dml_flag), - "current_dml_flag", get_dml_str(current_dml_flag), + K(dml_flag), + K(current_dml_flag), "table_name", simple_table_schema->get_table_name(), "table_id", simple_table_schema->get_table_id()); } else { @@ -1664,25 +1668,19 @@ int ObLogFormatter::build_binlog_record_( } } - switch (current_dml_flag) { - case ObDmlFlag::DF_DELETE: { + if (current_dml_flag.is_delete()) { ret = format_dml_delete_(br_data, rv); - break; - } - case ObDmlFlag::DF_INSERT: { + } else if (current_dml_flag.is_delete_insert()) { + ret = format_dml_put_(br_data, rv); + } else if (current_dml_flag.is_insert()) { ret = format_dml_insert_(br_data, rv); - break; - } - case ObDmlFlag::DF_UPDATE: { + } else if (current_dml_flag.is_update()) { ret = format_dml_update_(br_data, rv); - break; - } - default: { + } else { ret = OB_NOT_SUPPORTED; LOG_ERROR("unknown DML type, not supported", K(current_dml_flag)); - break; - } } + if (OB_FAIL(ret)) { LOG_ERROR("format dml failed", KR(ret), K(table_id), K(current_dml_flag), KPC(simple_table_schema)); } @@ -1693,7 +1691,7 @@ int ObLogFormatter::build_binlog_record_( } int ObLogFormatter::is_hbase_mode_put_(const uint64_t table_id, - const ObDmlFlag &dml_flag, + const ObDmlRowFlag &dml_flag, const int64_t column_number, const int64_t new_column_cnt, const bool contain_old_column, @@ -1709,26 +1707,21 @@ int ObLogFormatter::is_hbase_mode_put_(const uint64_t table_id, LOG_ERROR("hbase_util_ is null", KR(ret), K(hbase_util_)); } else if (OB_FAIL(hbase_util_->is_hbase_table(table_id, is_hbase_table))) { LOG_ERROR("ObLogHbaseUtil is_hbase_table fail", KR(ret), K(table_id), K(is_hbase_table)); - } else if (is_hbase_table && ObDmlFlag::DF_UPDATE == dml_flag && false == contain_old_column) { + } else if (is_hbase_table && dml_flag.is_update() && false == contain_old_column) { if (column_number == new_column_cnt) { is_hbase_mode_put = true; } else if (skip_hbase_mode_put_column_count_not_consistency_) { is_hbase_mode_put = true; - LOG_INFO("skip hbase mode put column count not consistency", K(table_id), - "dml_flag", get_dml_str(dml_flag), - "hbase_mode_put_column_cnt", new_column_cnt, - K(column_number)); + LOG_INFO("skip hbase mode put column count not consistency", K(table_id), K(dml_flag), + "hbase_mode_put_column_cnt", new_column_cnt, K(column_number)); } else { - LOG_ERROR("hbase mode put column cnt is not consistency", K(table_id), - "dml_flag", get_dml_str(dml_flag), - "hbase_mode_put_column_cnt", new_column_cnt, - K(column_number)); + LOG_ERROR("hbase mode put column cnt is not consistency", K(table_id), K(dml_flag), + "hbase_mode_put_column_cnt", new_column_cnt, K(column_number)); ret = OB_ERR_UNEXPECTED; } - LOG_DEBUG("[HBASE] [PUT]", K(is_hbase_mode_put), K(table_id), - "dml_flag", get_dml_str(dml_flag), + LOG_DEBUG("[HBASE] [PUT]", K(is_hbase_mode_put), K(table_id), K(dml_flag), K(column_number), K(new_column_cnt), K(contain_old_column)); } else { // do nothing @@ -1933,6 +1926,44 @@ int ObLogFormatter::format_dml_update_(IBinlogRecord *br_data, const RowValue *r return ret; } +int ObLogFormatter::format_dml_put_(IBinlogRecord *br_data, const RowValue *row_value) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(br_data) || OB_ISNULL(row_value)) { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("invalid argument", KR(ret), K(br_data), K(row_value)); + } else { + for (int64_t i = 0; OB_SUCCESS == ret && i < row_value->column_num_; i++) { + if (!row_value->is_changed_[i]) { + ObString *str_val = row_value->orig_default_value_[i]; + + if (OB_ISNULL(str_val)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("column original default value is NULL", KR(ret), K(i), + "column_num", row_value->column_num_); + } else { + br_data->putNew(str_val->ptr(), str_val->length()); + } + } else { + ObString *str_val = row_value->new_columns_[i]; + + if (OB_ISNULL(str_val)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("changed column new value is NULL", KR(ret), K(i), + "column_num", row_value->column_num_); + } else { + br_data->putNew(str_val->ptr(), str_val->length()); + } + } + + // FIXME: No old values are populated, regardless of whether it is a full column log + } + } + + return ret; +} + int ObLogFormatter::get_schema_with_online_schema_( const int64_t version, const uint64_t tenant_id, diff --git a/src/logservice/libobcdc/src/ob_log_formatter.h b/src/logservice/libobcdc/src/ob_log_formatter.h index 84c78970f..9a80b17aa 100644 --- a/src/logservice/libobcdc/src/ob_log_formatter.h +++ b/src/logservice/libobcdc/src/ob_log_formatter.h @@ -23,7 +23,7 @@ #include "lib/allocator/ob_allocator.h" // ObIAllocator #include "lib/thread/ob_multi_fixed_queue_thread.h" // ObMQThread -#include "storage/blocksstable/ob_datum_row.h" // ObDmlFlag +#include "storage/blocksstable/ob_datum_row.h" // ObDmlRowFlag #include "ob_log_binlog_record.h" // IBinlogRecord, ObLogBR @@ -266,7 +266,7 @@ private: ObLogBR *br, RowValue *rv, const int64_t new_column_cnt, - const blocksstable::ObDmlFlag &dml_flag, + const blocksstable::ObDmlRowFlag &dml_flag, const TABLE_SCHEMA *simple_table_schema); // HBase mode put // 1. hbase table @@ -274,18 +274,19 @@ private: // 3. new value all columns, old value empty int is_hbase_mode_put_( const uint64_t table_id, - const blocksstable::ObDmlFlag &dml_flag, + const blocksstable::ObDmlRowFlag &dml_flag, const int64_t column_number, const int64_t new_column_cnt, const bool contain_old_column, bool &is_hbase_mode_put); int set_src_category_(IBinlogRecord *br, RowValue *rv, - const blocksstable::ObDmlFlag &dml_flag, + const blocksstable::ObDmlRowFlag &dml_flag, const bool is_hbase_mode_put); int format_dml_delete_(IBinlogRecord *binlog_record, const RowValue *row_value); int format_dml_insert_(IBinlogRecord *binlog_record, const RowValue *row_value); int format_dml_update_(IBinlogRecord *binlog_record, const RowValue *row_value); + int format_dml_put_(IBinlogRecord *binlog_record, const RowValue *row_value); template int fill_orig_default_value_( RowValue *rv, diff --git a/src/logservice/libobcdc/src/ob_log_instance.cpp b/src/logservice/libobcdc/src/ob_log_instance.cpp index 89f3f5406..688ae0df2 100644 --- a/src/logservice/libobcdc/src/ob_log_instance.cpp +++ b/src/logservice/libobcdc/src/ob_log_instance.cpp @@ -751,6 +751,8 @@ int ObLogInstance::init_components_(const uint64_t start_tstamp_ns) const char *tb_black_list = TCONF.get_tb_black_list_buf() != NULL ? TCONF.get_tb_black_list_buf() : TCONF.tb_black_list.str(); + const bool enable_direct_load_inc = (1 == TCONF.enable_direct_load_inc); + if (OB_UNLIKELY(! is_working_mode_valid(working_mode))) { ret = OB_INVALID_CONFIG; LOG_ERROR("working_mode is not valid", KR(ret), K(working_mode_str), "working_mode", print_working_mode(working_mode)); @@ -965,7 +967,8 @@ int ObLogInstance::init_components_(const uint64_t start_tstamp_ns) } } - INIT(trans_redo_dispatcher_, ObLogTransRedoDispatcher, redo_dispatcher_mem_limit, enable_sort_by_seq_no, *trans_stat_mgr_); + INIT(trans_redo_dispatcher_, ObLogTransRedoDispatcher, redo_dispatcher_mem_limit, + enable_sort_by_seq_no, *trans_stat_mgr_); INIT(ddl_processor_, ObLogDDLProcessor, schema_getter_, TCONF.skip_reversed_schema_verison, TCONF.enable_white_black_list); @@ -991,15 +994,15 @@ int ObLogInstance::init_components_(const uint64_t start_tstamp_ns) } } - INIT(fetcher_, ObLogFetcher, false/*is_load_data_dict_baseline_data*/, fetching_mode, archive_dest, - &dispatcher_, sys_ls_handler_, &trans_task_pool_, log_entry_task_pool_, + INIT(fetcher_, ObLogFetcher, false/*is_load_data_dict_baseline_data*/, enable_direct_load_inc, fetching_mode, + archive_dest, &dispatcher_, sys_ls_handler_, &trans_task_pool_, log_entry_task_pool_, &mysql_proxy_.get_ob_mysql_proxy(), err_handler, cluster_info.cluster_id_, TCONF, start_seq); if (OB_SUCC(ret)) { if (is_data_dict_refresh_mode(refresh_mode_)) { if (OB_FAIL(ObLogMetaDataService::get_instance().init(start_tstamp_ns, fetching_mode, archive_dest, sys_ls_handler_, &mysql_proxy_.get_ob_mysql_proxy(), err_handler, *part_trans_parser_, - cluster_info.cluster_id_, TCONF, start_seq))) { + cluster_info.cluster_id_, TCONF, start_seq, enable_direct_load_inc))) { LOG_ERROR("ObLogMetaDataService init failed", KR(ret), K(start_tstamp_ns)); } } @@ -1702,7 +1705,7 @@ int ObLogInstance::verify_ob_trace_id_(IBinlogRecord *br) } else { int record_type = br->recordType(); - if (EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type) { + if (EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type || EPUT == record_type) { // only verify insert\update\delete type const ObString ob_trace_id_config(ob_trace_id_str_); ObLogBR *oblog_br = NULL; @@ -1815,7 +1818,7 @@ int ObLogInstance::verify_dml_unique_id_(IBinlogRecord *br) int record_type = br->recordType(); - if (EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type) { + if (EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type || EPUT == record_type) { // only verify insert\update\delete type ObLogBR *oblog_br = NULL; ObLogEntryTask *log_entry_task = NULL; diff --git a/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.cpp b/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.cpp index 72fd5350f..d43021e1f 100644 --- a/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.cpp +++ b/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.cpp @@ -117,6 +117,7 @@ int ObLogLSFetchMgr::add_ls( const logservice::TenantLSID &tls_id, const logfetcher::ObLogFetcherStartParameters &start_parameters, const bool is_loading_data_dict_baseline_data, + const bool enable_direct_load_inc, const ClientFetchingMode fetching_mode, const ObBackupPathString &archive_dest_str) { @@ -149,7 +150,7 @@ int ObLogLSFetchMgr::add_ls( } else if (OB_ISNULL(part_trans_resolver)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid part_trans_resolver", K(part_trans_resolver)); - } else if (OB_FAIL(part_trans_resolver->init(tls_id, start_tstamp_ns))) { + } else if (OB_FAIL(part_trans_resolver->init(tls_id, start_tstamp_ns, enable_direct_load_inc))) { LOG_ERROR("init part trans resolver fail", KR(ret), K(tls_id), K(start_tstamp_ns)); } // alloc a LSFetchCtx diff --git a/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.h b/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.h index 842635401..8b34f3f9f 100644 --- a/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.h +++ b/src/logservice/libobcdc/src/ob_log_ls_fetch_mgr.h @@ -45,6 +45,7 @@ public: const logservice::TenantLSID &tls_id, const logfetcher::ObLogFetcherStartParameters &start_parameters, const bool is_loading_data_dict_baseline_data, + const bool enable_direct_load_inc, const ClientFetchingMode fetching_mode, const ObBackupPathString &archive_dest_str) = 0; @@ -104,6 +105,7 @@ public: const logservice::TenantLSID &tls_id, const logfetcher::ObLogFetcherStartParameters &start_parameters, const bool is_loading_data_dict_baseline_data, + const bool enable_direct_load_inc, const ClientFetchingMode fetching_mode, const ObBackupPathString &archive_dest_str); virtual int recycle_ls(const logservice::TenantLSID &tls_id); diff --git a/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.cpp b/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.cpp index 024c1ab54..36606c2d7 100644 --- a/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.cpp +++ b/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.cpp @@ -70,7 +70,8 @@ int ObLogMetaDataFetcher::init( IObLogErrHandler *err_handler, const int64_t cluster_id, const ObLogConfig &cfg, - const int64_t start_seq) + const int64_t start_seq, + const bool enable_direct_load_inc) { int ret = OB_SUCCESS; @@ -93,7 +94,7 @@ int ObLogMetaDataFetcher::init( } else { trans_task_pool_alloc_.set_label("DictConFAlloc"); INIT(log_fetcher_, ObLogFetcher, true/*is_loading_data_dict_baseline_data*/, - fetching_mode, archive_dest, fetcher_dispatcher, + enable_direct_load_inc, fetching_mode, archive_dest, fetcher_dispatcher, sys_ls_handler, &trans_task_pool_, &log_entry_task_pool_, proxy, err_handler, cluster_id, cfg, start_seq); diff --git a/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.h b/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.h index 539c5bdec..8aa8be11b 100644 --- a/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.h +++ b/src/logservice/libobcdc/src/ob_log_meta_data_fetcher.h @@ -43,7 +43,8 @@ public: IObLogErrHandler *err_handler, const int64_t cluster_id, const ObLogConfig &cfg, - const int64_t start_seq); + const int64_t start_seq, + const bool enable_direct_load_inc); int start(); void stop(); void destroy(); diff --git a/src/logservice/libobcdc/src/ob_log_meta_data_service.cpp b/src/logservice/libobcdc/src/ob_log_meta_data_service.cpp index f99163ab3..68a07e31a 100644 --- a/src/logservice/libobcdc/src/ob_log_meta_data_service.cpp +++ b/src/logservice/libobcdc/src/ob_log_meta_data_service.cpp @@ -63,7 +63,8 @@ int ObLogMetaDataService::init( IObLogPartTransParser &part_trans_parser, const int64_t cluster_id, const ObLogConfig &cfg, - const int64_t start_seq) + const int64_t start_seq, + const bool enable_direct_load_inc) { int ret = OB_SUCCESS; @@ -77,7 +78,7 @@ int ObLogMetaDataService::init( } else if (OB_FAIL(fetcher_dispatcher_.init(&incremental_replayer_, start_seq))) { LOG_ERROR("ObLogMetaDataFetcherDispatcher init fail", KR(ret)); } else if (OB_FAIL(fetcher_.init(fetching_mode, archive_dest, &fetcher_dispatcher_, sys_ls_handler, - proxy, err_handler, cluster_id, cfg, start_seq))) { + proxy, err_handler, cluster_id, cfg, start_seq, enable_direct_load_inc))) { LOG_ERROR("ObLogMetaDataFetcher init fail", KR(ret), K(fetching_mode), "fetching_log_mode", print_fetching_mode(fetching_mode), K(archive_dest)); } else if (OB_FAIL(fetcher_.start())) { diff --git a/src/logservice/libobcdc/src/ob_log_meta_data_service.h b/src/logservice/libobcdc/src/ob_log_meta_data_service.h index 424ee21ff..6777ea4aa 100644 --- a/src/logservice/libobcdc/src/ob_log_meta_data_service.h +++ b/src/logservice/libobcdc/src/ob_log_meta_data_service.h @@ -56,7 +56,8 @@ public: IObLogPartTransParser &part_trans_parser, const int64_t cluster_id, const ObLogConfig &cfg, - const int64_t start_seq); + const int64_t start_seq, + const bool enable_direct_load_inc); void destroy(); static ObLogMetaDataService &get_instance(); diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp b/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp index 8f9c6b624..d138f72e3 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp +++ b/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp @@ -23,11 +23,13 @@ #include "ob_log_instance.h" // TCTX #include "ob_log_config.h" // TCONF #include "ob_cdc_lob_aux_table_parse.h" // parse_aux_lob_meta_table_row +#include "src/storage/ddl/ob_ddl_redo_log_row_iterator.h" using namespace oceanbase::common; using namespace oceanbase::share::schema; using namespace oceanbase::transaction; using namespace oceanbase::memtable; +using namespace oceanbase::storage; namespace oceanbase { @@ -183,13 +185,21 @@ int ObLogPartTransParser::parse(ObLogEntryTask &task, volatile bool &stop_flag) } else if (OB_UNLIKELY(! redo_node->check_data_integrity())) { ret = OB_INVALID_DATA; LOG_ERROR("redo data is not valid", KR(ret), KPC(redo_node)); - } else if (OB_FAIL(parse_stmts_(tenant, *redo_node, is_build_baseline, - task, *part_trans_task, row_index, stop_flag))) { - LOG_ERROR("parse_stmts_ fail", KR(ret), K(tenant), KPC(redo_node), - K(is_build_baseline), K(task), K(row_index)); + } else if (redo_node->is_direct_load_inc_log()) { + if (OB_FAIL(parse_direct_load_inc_stmts_(tenant, *redo_node, task, *part_trans_task, row_index, stop_flag))) { + LOG_ERROR("parse_ddl_stmts_ fail", KR(ret), K(tenant), KPC(redo_node), K(task), K(row_index)); + } else { + ATOMIC_AAF(&total_log_size_, redo_node->get_data_len()); + LOG_DEBUG("[PARSE] LogEntryTask parse ddl redo log succ", K(task)); + } } else { - ATOMIC_AAF(&total_log_size_, redo_node->get_data_len()); - LOG_DEBUG("[PARSE] LogEntryTask parse succ", K(task)); + if (OB_FAIL(parse_stmts_(tenant, *redo_node, is_build_baseline, task, *part_trans_task, + row_index, stop_flag))) { + LOG_ERROR("parse_stmts_ fail", KR(ret), K(tenant), KPC(redo_node), K(task), K(row_index)); + } else { + ATOMIC_AAF(&total_log_size_, redo_node->get_data_len()); + LOG_DEBUG("[PARSE] LogEntryTask parse redo log succ", K(task)); + } } } } @@ -295,10 +305,10 @@ int ObLogPartTransParser::parse_stmts_( } } else if (MutatorType::MUTATOR_ROW == mutator_type) { bool is_ignored = false; - MutatorRow *row = NULL; + MemtableMutatorRow *row = NULL; ObCDCTableInfo table_info; - if (OB_FAIL(parse_mutator_row_( + if (OB_FAIL(parse_memtable_mutator_row_( tenant, tablet_id, redo_data, @@ -310,7 +320,7 @@ int ObLogPartTransParser::parse_stmts_( row, table_info, is_ignored))) { - LOG_ERROR("parse_mutator_row_ failed", KR(ret), + LOG_ERROR("parse_memtable_mutator_row_ failed", KR(ret), "tls_id", task.get_tls_id(), "trans_id", task.get_trans_id(), K(tablet_id), K(redo_log_entry_task), K(is_build_baseline), K(row_index)); @@ -374,6 +384,74 @@ int ObLogPartTransParser::parse_stmts_( return ret; } +int ObLogPartTransParser::parse_direct_load_inc_stmts_( + ObLogTenant *tenant, + const RedoLogMetaNode &redo_log_node, + ObLogEntryTask &redo_log_entry_task, + PartTransTask &task, + uint64_t &row_index, + volatile bool &stop_flag) +{ + int ret = OB_SUCCESS; + const char *ddl_redo_data = redo_log_node.get_data(); + const int64_t ddl_redo_data_len = redo_log_node.get_data_len(); + + if (OB_ISNULL(tenant) || OB_ISNULL(ddl_redo_data) || OB_UNLIKELY(ddl_redo_data_len <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("invalid argument", KR(ret), KPC(tenant), K(ddl_redo_data), K(ddl_redo_data_len), K(task), K(redo_log_entry_task)); + } else { + ObDDLRedoLog ddl_redo_log; + int64_t pos = 0; + if (OB_FAIL(ddl_redo_log.deserialize(ddl_redo_data, ddl_redo_data_len, pos))) { + LOG_ERROR("ObDDLRedoLog deserialize failed", KR(ret), K(ddl_redo_log), K(ddl_redo_data_len), K(pos)); + } else { + const common::ObTabletID tablet_id = ddl_redo_log.get_redo_info().table_key_.get_tablet_id(); + ObArenaAllocator allocator; + ObDDLRedoLogRowIterator ddl_redo_log_row_iterator(allocator, tenant->get_tenant_id()); + if (OB_FAIL(ddl_redo_log_row_iterator.init(ddl_redo_log.get_redo_info().data_buffer_))){ + LOG_ERROR("direct_load_log_row_iterator init failed", KR(ret), K(ddl_redo_log)); + } else { + while (OB_SUCCESS == ret) { + bool is_ignored = false; + MacroBlockMutatorRow *row = nullptr; + const blocksstable::ObDatumRow *datum_row = nullptr; + const ObStoreRowkey *row_key = nullptr; + transaction::ObTxSEQ seq; + blocksstable::ObDmlRowFlag dml_flag; + ObCDCTableInfo table_info; + + if (OB_FAIL(ddl_redo_log_row_iterator.get_next_row(datum_row, row_key, seq, dml_flag))) { + if (OB_ITER_END != ret) { + LOG_ERROR("get next macroblock row failed", KR(ret)); + } + } else if (OB_ISNULL(datum_row) || OB_ISNULL(row_key)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("datum_row or row_key is nullptr", K(datum_row), K(row_key)); + } else if (OB_FAIL(alloc_macroblock_mutator_row_(task, redo_log_entry_task, datum_row, row_key, seq, dml_flag, row))) { + LOG_ERROR("alloc macroblock mutator row failed", KR(ret), K(task), K(redo_log_entry_task), KPC(datum_row), + KPC(row_key), K(seq), K(dml_flag), K(row)); + } else if (OB_FAIL(parse_macroblock_mutator_row_(tenant, tablet_id, task, redo_log_entry_task, row, table_info, is_ignored))) { + LOG_ERROR("parse macroblock mutator row failed", K(tenant), K(tablet_id), K(task), K(redo_log_entry_task), + KPC(row), K(table_info), K(is_ignored), K(datum_row), K(row_key), K(seq), K(dml_flag), K(ddl_redo_log)); + } else if (!is_ignored && OB_FAIL(parse_dml_stmts_(table_info.get_table_id(), row_index, *row, + redo_log_entry_task, task))) { + LOG_ERROR("parse_dml_stmts failed", KR(ret), K(table_info), K(row_index), KPC(row), K(redo_log_entry_task), K(task), + K(datum_row), K(row_key), K(seq), K(dml_flag), K(ddl_redo_log)); + } else { + ++row_index; + } + } // for each row + + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + } + } + } + } + + return ret; +} + int ObLogPartTransParser::parse_mutator_header_( const char *buf, const int64_t buf_len, @@ -423,7 +501,7 @@ int ObLogPartTransParser::filter_mutator_table_lock_(const char *buf, const int6 return ret; } -int ObLogPartTransParser::parse_mutator_row_( +int ObLogPartTransParser::parse_memtable_mutator_row_( ObLogTenant *tenant, const ObTabletID &tablet_id, const char *redo_data, @@ -432,76 +510,24 @@ int ObLogPartTransParser::parse_mutator_row_( int64_t &pos, PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row, + MemtableMutatorRow *&row, ObCDCTableInfo &table_info, bool &is_ignored) { int ret = OB_SUCCESS; - is_ignored = false; - row = NULL; - bool need_rollback = false; - bool need_filter = false; - bool is_in_table_id_cache = false; - const char *filter_reason = NULL; - - if (OB_FAIL(alloc_mutator_row_(part_trans_task, redo_log_entry_task, row))) { - LOG_ERROR("alloc_mutator_row_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task)); + if (OB_FAIL(alloc_memtable_mutator_row_(part_trans_task, redo_log_entry_task, row))) { + LOG_ERROR("alloc_memtable_mutator_row_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task)); } else if (OB_FAIL(row->deserialize(redo_data, redo_data_len, pos))) { LOG_ERROR("deserialize mutator row fail", KR(ret), KPC(row), K(redo_data_len), K(pos)); - } else if (OB_FAIL(check_row_need_rollback_(part_trans_task, *row, need_rollback))) { - LOG_ERROR("check_row_need_rollback_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task), KPC(row)); - } else if (need_rollback) { - LOG_DEBUG("rollback row by RollbackToSavepoint", - "tls_id", part_trans_task.get_tls_id(), - "trans_id", part_trans_task.get_trans_id(), - "row_seq_no", row->seq_no_); - } else if (OB_FAIL(get_table_info_of_tablet_(tenant, part_trans_task, tablet_id, table_info))) { - LOG_ERROR("get_table_info_of_tablet_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task), KPC(row)); - } else if (table_info.is_index_table()) { - need_filter = true; - filter_reason = "INDEX_TABLE"; - // DDL Table and LOB_AUX TABLE for DDL Table should not ignore - } else if (part_trans_task.is_ddl_trans() - && ! (is_ddl_tablet(part_trans_task.get_ls_id(), tablet_id) - || is_all_ddl_operation_lob_aux_tablet(part_trans_task.get_ls_id(), tablet_id))) { - need_filter = true; - filter_reason = "NON_DDL_RELATED_TABLE"; - } else if (part_trans_task.is_ddl_trans() && is_build_baseline - && is_all_ddl_operation_lob_aux_tablet(part_trans_task.get_ls_id(), tablet_id)) { - need_filter = true; - filter_reason = "DDL_OPERATION_LOB_AUX_TABLE_IN_BUILD_BASELINE"; - } else if (part_trans_task.is_ddl_trans()) { - // do nothing, ddl trans should not be filtered - } else { - IObLogPartMgr &part_mgr = tenant->get_part_mgr(); - if (OB_FAIL(part_mgr.is_exist_table_id_cache(table_info.get_table_id(), is_in_table_id_cache))) { - LOG_ERROR("check is_exist_table_id_cache failed", KR(ret), - "tls_id", part_trans_task.get_tls_id(), - "trans_id", part_trans_task.get_trans_id(), - K(tablet_id), K(table_info)); - } else { - need_filter = ! is_in_table_id_cache; - filter_reason = "NOT_EXIST_IN_TB_ID_CACHE"; - } - } - - if (need_filter) { - LOG_DEBUG("filter mutator row", - "tls_id", part_trans_task.get_tls_id(), - "trans_id", part_trans_task.get_trans_id(), - K(tablet_id), - K(table_info), - K(filter_reason), - K(is_build_baseline)); - } - - if (OB_SUCC(ret)) { - is_ignored = need_rollback || need_filter; + } else if (OB_FAIL(check_row_need_ignore_(is_build_baseline, tenant, part_trans_task, redo_log_entry_task, + *row, tablet_id, table_info, is_ignored))) { + LOG_ERROR("check_row_need_ignore_ failed", KR(ret), K(is_build_baseline), K(part_trans_task), + K(redo_log_entry_task), KPC(row)); } if (OB_FAIL(ret) || is_ignored) { - free_mutator_row_(part_trans_task, redo_log_entry_task, row); + free_memtable_mutator_row_(part_trans_task, redo_log_entry_task, row); } else if (OB_ISNULL(row)) { ret = OB_INVALID_DATA; } @@ -509,10 +535,10 @@ int ObLogPartTransParser::parse_mutator_row_( return ret; } -int ObLogPartTransParser::alloc_mutator_row_( +int ObLogPartTransParser::alloc_memtable_mutator_row_( PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row) + MemtableMutatorRow *&row) { int ret = OB_SUCCESS; void *mutator_row_buf = NULL; @@ -520,35 +546,35 @@ int ObLogPartTransParser::alloc_mutator_row_( const bool is_ddl_trans = part_trans_task.is_ddl_trans(); if (is_ddl_trans) { - mutator_row_buf = part_trans_task.alloc(sizeof(MutatorRow)); + mutator_row_buf = part_trans_task.alloc(sizeof(MemtableMutatorRow)); } else { - mutator_row_buf = redo_log_entry_task.alloc(sizeof(MutatorRow)); + mutator_row_buf = redo_log_entry_task.alloc(sizeof(MemtableMutatorRow)); } - if (OB_ISNULL(row = static_cast(mutator_row_buf))) { - LOG_ERROR("alloc memory for MutatorRow fail", K(sizeof(MutatorRow))); + if (OB_ISNULL(row = static_cast(mutator_row_buf))) { + LOG_ERROR("alloc memory for MemtableMutatorRow fail", K(sizeof(MemtableMutatorRow))); ret = OB_ALLOCATE_MEMORY_FAILED; } else { - // FIXME: Destroy MutatorRow from regular channels and free memory + // FIXME: Destroy MemtableMutatorRow from regular channels and free memory // Currently destroyed in DmlStmtTask and DdlStmtTask, but no memory is freed // Since this memory is allocated by the Allocator of the PartTransTask, it is guaranteed not to leak if (is_ddl_trans) { - new (row) MutatorRow(part_trans_task.get_allocator()); + new (row) MemtableMutatorRow(part_trans_task.get_allocator()); } else { - new (row) MutatorRow(redo_log_entry_task.get_allocator()); + new (row) MemtableMutatorRow(redo_log_entry_task.get_allocator()); } } return ret; } -void ObLogPartTransParser::free_mutator_row_( +void ObLogPartTransParser::free_memtable_mutator_row_( PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row) + MemtableMutatorRow *&row) { if (OB_NOT_NULL(row)) { - row->~MutatorRow(); + row->~MemtableMutatorRow(); if (part_trans_task.is_ddl_trans()) { part_trans_task.free(row); } else { @@ -592,7 +618,7 @@ int ObLogPartTransParser::check_row_need_rollback_( int ret = OB_SUCCESS; need_rollback = false; const RollbackList &rollback_list = part_trans_task.get_rollback_list(); - const auto &row_seq_no = row.seq_no_; + const auto &row_seq_no = row.get_seq_no(); const RollbackNode *rollback_node = rollback_list.head_; while (OB_SUCC(ret) && OB_NOT_NULL(rollback_node) && ! need_rollback) { @@ -632,7 +658,7 @@ int ObLogPartTransParser::filter_row_data_( const uint64_t tenant_id = task.get_tenant_id(); // Temporary row data structure to avoid allocation of row data memory // TODO allocator - MutatorRow row(task.get_allocator()); + MemtableMutatorRow row(task.get_allocator()); if (OB_ISNULL(redo_data) || OB_UNLIKELY(redo_data_len <= 0) || OB_UNLIKELY(cur_pos < 0) || OB_UNLIKELY(! table_info.is_valid())) { LOG_ERROR("invalid argument", K(redo_data), K(task), K(redo_data_len), K(cur_pos), K(table_info)); @@ -840,12 +866,15 @@ int ObLogPartTransParser::parse_ddl_lob_aux_stmts_( LOG_ERROR("allocate memory for DmlStmtTask fail", KR(ret), "Dmlsize", sizeof(DmlStmtTask)); } else { new (stmt_task) DmlStmtTask(part_trans_task, invalid_log_entry_task, row); - stmt_task->set_table_id(table_id); ColValueList *rowkey_cols = nullptr; ColValueList *new_cols = nullptr; ColValueList *old_cols = nullptr; - if (OB_FAIL(part_trans_task.add_ddl_lob_aux_stmt(row_index, stmt_task))) { + if (OB_ISNULL(stmt_task)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("stmt_task is nullptr", KR(ret), K(stmt_task)); + } else if (FALSE_IT(stmt_task->set_table_id(table_id))) { + } else if (OB_FAIL(part_trans_task.add_ddl_lob_aux_stmt(row_index, stmt_task))) { LOG_ERROR("add_ddl_lob_aux_stmt into trans task fail", KR(ret), K(part_trans_task), K(row_index), "stmt_task", *stmt_task); } else if (OB_FAIL(stmt_task->parse_aux_meta_table_cols(lob_aux_table_schema_info))) { @@ -908,7 +937,10 @@ int ObLogPartTransParser::parse_dml_stmts_( new (stmt_task) DmlStmtTask(task, redo_log_entry_task, row); stmt_task->set_table_id(table_id); - if (OB_FAIL(redo_log_entry_task.add_stmt(row_index, stmt_task))) { + if (OB_ISNULL(stmt_task)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("stmt_task is nullptr", KR(ret), K(stmt_task)); + } else if (OB_FAIL(redo_log_entry_task.add_stmt(row_index, stmt_task))) { LOG_ERROR("add stmt into trans task fail", KR(ret), K(task), K(row_index), "stmt_task", *stmt_task); } else { // Update the Local Schema version of PartTransTask @@ -929,10 +961,147 @@ int ObLogPartTransParser::parse_dml_stmts_( return ret; } -const transaction::ObTxSEQ &ObLogPartTransParser::get_row_seq_(PartTransTask &task, MutatorRow &row) const +const transaction::ObTxSEQ ObLogPartTransParser::get_row_seq_(PartTransTask &task, MutatorRow &row) const { //return task.is_cluster_version_before_320() ? row.sql_no_ : row.seq_no_; - return row.seq_no_; + return row.get_seq_no(); +} + +int ObLogPartTransParser::alloc_macroblock_mutator_row_( + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + const blocksstable::ObDatumRow *datum_row, + const common::ObStoreRowkey *row_key, + transaction::ObTxSEQ &seq_no, + blocksstable::ObDmlRowFlag &dml_flag, + MacroBlockMutatorRow *&row) +{ + int ret = OB_SUCCESS; + row = NULL; + + if (OB_ISNULL(row = static_cast(redo_log_entry_task.alloc(sizeof(MacroBlockMutatorRow))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("alloc memory for MacroBlockMutatorRow fail", KR(ret), K(sizeof(MacroBlockMutatorRow))); + } else if (FALSE_IT(new (row) MacroBlockMutatorRow(redo_log_entry_task.get_allocator(), dml_flag, seq_no))) { + } else if (OB_FAIL(row->init(redo_log_entry_task.get_allocator(), *datum_row, *row_key))) { + LOG_ERROR("macroblock row init fail", KR(ret), KPC(datum_row), KPC(row_key)); + } else { + // succ + } + + return ret; +} + +void ObLogPartTransParser::free_macroblock_mutator_row_( + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + MacroBlockMutatorRow *&row) +{ + if (OB_NOT_NULL(row)) { + row->~MacroBlockMutatorRow(); + redo_log_entry_task.free(row); + row = NULL; + } +} + +int ObLogPartTransParser::parse_macroblock_mutator_row_( + ObLogTenant *tenant, + const ObTabletID &tablet_id, + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + MacroBlockMutatorRow *&row, + ObCDCTableInfo &table_info, + bool &is_ignored) +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(check_row_need_ignore_(false /* is_build_baseline */, tenant, part_trans_task, + redo_log_entry_task, *row, tablet_id, table_info, is_ignored))) { + LOG_ERROR("check_row_need_ignore_ failed", KR(ret), K(tablet_id), K(part_trans_task), + K(redo_log_entry_task), KPC(row)); + } + + if (OB_FAIL(ret) || is_ignored) { + free_macroblock_mutator_row_(part_trans_task, redo_log_entry_task, row); + } else if (OB_ISNULL(row)) { + ret = OB_INVALID_DATA; + } else { + row->set_table_id(table_info.get_table_id()); + } + + return ret; +} + +int ObLogPartTransParser::check_row_need_ignore_( + const bool is_build_baseline, + ObLogTenant *tenant, + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + MutatorRow &row, + const ObTabletID &tablet_id, + ObCDCTableInfo &table_info, + bool &is_ignored) +{ + int ret = OB_SUCCESS; + IObLogPartMgr &part_mgr = tenant->get_part_mgr(); + is_ignored = false; + bool need_rollback = false; + bool need_filter = false; + bool is_in_table_id_cache = false; + const char *filter_reason = NULL; + + if (OB_FAIL(check_row_need_rollback_(part_trans_task, row, need_rollback))) { + LOG_ERROR("check_row_need_rollback_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task), K(row)); + } else if (need_rollback) { + LOG_DEBUG("rollback row by RollbackToSavepoint", + "tls_id", part_trans_task.get_tls_id(), + "trans_id", part_trans_task.get_trans_id(), + "row_seq_no", row.get_seq_no()); + } else if (OB_FAIL(get_table_info_of_tablet_(tenant, part_trans_task, tablet_id, table_info))) { + LOG_ERROR("get_table_info_of_tablet_ failed", KR(ret), K(tablet_id), K(part_trans_task), K(redo_log_entry_task), K(row)); + } else if (table_info.is_index_table()) { + need_filter = true; + filter_reason = "INDEX_TABLE"; + // DDL Table and LOB_AUX TABLE for DDL Table should not ignore + } else if (part_trans_task.is_ddl_trans() + && ! (is_ddl_tablet(part_trans_task.get_ls_id(), tablet_id) + || is_all_ddl_operation_lob_aux_tablet(part_trans_task.get_ls_id(), tablet_id))) { + need_filter = true; + filter_reason = "NON_DDL_RELATED_TABLE"; + } else if (part_trans_task.is_ddl_trans() && is_build_baseline + && is_all_ddl_operation_lob_aux_tablet(part_trans_task.get_ls_id(), tablet_id)) { + need_filter = true; + filter_reason = "DDL_OPERATION_LOB_AUX_TABLE_IN_BUILD_BASELINE"; + } else if (part_trans_task.is_ddl_trans()) { + // do nothing, ddl trans should not be filtered + } else { + IObLogPartMgr &part_mgr = tenant->get_part_mgr(); + if (OB_FAIL(part_mgr.is_exist_table_id_cache(table_info.get_table_id(), is_in_table_id_cache))) { + LOG_ERROR("check is_exist_table_id_cache failed", KR(ret), + "tls_id", part_trans_task.get_tls_id(), + "trans_id", part_trans_task.get_trans_id(), + K(tablet_id), K(table_info)); + } else { + need_filter = ! is_in_table_id_cache; + filter_reason = "NOT_EXIST_IN_TB_ID_CACHE"; + } + } + + if (need_filter) { + LOG_DEBUG("filter mutator row", + "tls_id", part_trans_task.get_tls_id(), + "trans_id", part_trans_task.get_trans_id(), + K(tablet_id), + K(table_info), + K(filter_reason), + K(is_build_baseline)); + } + + if (OB_SUCC(ret)) { + is_ignored = need_rollback || need_filter; + } + + return ret; } int ObLogPartTransParser::parse_ext_info_log_mutator_row_( @@ -942,7 +1111,7 @@ int ObLogPartTransParser::parse_ext_info_log_mutator_row_( int64_t &pos, PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row, + MemtableMutatorRow *&row, bool &is_ignored) { int ret = OB_SUCCESS; @@ -950,8 +1119,8 @@ int ObLogPartTransParser::parse_ext_info_log_mutator_row_( row = nullptr; bool need_rollback = false; - if (OB_FAIL(alloc_mutator_row_(part_trans_task, redo_log_entry_task, row))) { - LOG_ERROR("alloc_mutator_row_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task)); + if (OB_FAIL(alloc_memtable_mutator_row_(part_trans_task, redo_log_entry_task, row))) { + LOG_ERROR("alloc_memtable_mutator_row_ failed", KR(ret), K(part_trans_task), K(redo_log_entry_task)); } else if (OB_FAIL(row->deserialize(redo_data, redo_data_len, pos))) { LOG_ERROR("deserialize mutator row fail", KR(ret), KPC(row), K(redo_data_len), K(pos)); } else if (OB_FAIL(check_row_need_rollback_(part_trans_task, *row, need_rollback))) { @@ -971,7 +1140,7 @@ int ObLogPartTransParser::parse_ext_info_log_mutator_row_( } if (OB_FAIL(ret) || is_ignored) { - free_mutator_row_(part_trans_task, redo_log_entry_task, row); + free_memtable_mutator_row_(part_trans_task, redo_log_entry_task, row); row = nullptr; } else if (OB_ISNULL(row)) { ret = OB_INVALID_DATA; @@ -991,7 +1160,7 @@ int ObLogPartTransParser::handle_mutator_ext_info_log_( { int ret = OB_SUCCESS; bool is_ignored = false; - MutatorRow *row = nullptr; + MemtableMutatorRow *row = nullptr; if (OB_FAIL(parse_ext_info_log_mutator_row_( tenant, redo_data, @@ -1011,7 +1180,7 @@ int ObLogPartTransParser::handle_mutator_ext_info_log_( const transaction::ObTransID &trans_id = part_trans_task.get_trans_id(); const uint64_t table_id = 0; ObLobId lob_id; // empty - transaction::ObTxSEQ row_seq_no = row->seq_no_; + transaction::ObTxSEQ row_seq_no = row->get_seq_no(); ObString ext_info_log; ObCDCLobAuxMetaStorager &lob_aux_meta_storager = TCTX.lob_aux_meta_storager_; LobAuxMetaKey lob_aux_meta_key(commit_version, tenant_id, trans_id, table_id, lob_id, row_seq_no); @@ -1029,7 +1198,7 @@ int ObLogPartTransParser::handle_mutator_ext_info_log_( "trans_id", part_trans_task.get_trans_id()); } if (OB_NOT_NULL(row)) { - free_mutator_row_(part_trans_task, redo_log_entry_task, row); + free_memtable_mutator_row_(part_trans_task, redo_log_entry_task, row); } return ret; } diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_parser.h b/src/logservice/libobcdc/src/ob_log_part_trans_parser.h index 76aa4de4c..256426a4a 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_parser.h +++ b/src/logservice/libobcdc/src/ob_log_part_trans_parser.h @@ -82,6 +82,14 @@ private: PartTransTask &task, uint64_t &row_index, volatile bool &stop_flag); + int parse_direct_load_inc_stmts_( + ObLogTenant *tenant, + const RedoLogMetaNode &redo_log_node, + ObLogEntryTask &redo_log_entry_task, + PartTransTask &task, + uint64_t &row_index, + volatile bool &stop_flag); + // try parse mutator_header to get mutator type(support if ob_version >= 320) // and move forward cur_pos to skip header if header is supported // @@ -138,16 +146,16 @@ private: MutatorRow &row, ObLogEntryTask &redo_log_entry_task, PartTransTask &part_trans_task); - const transaction::ObTxSEQ &get_row_seq_(PartTransTask &task, MutatorRow &row) const; - int alloc_mutator_row_( + const transaction::ObTxSEQ get_row_seq_(PartTransTask &task, MutatorRow &row) const; + int alloc_memtable_mutator_row_( PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row); - void free_mutator_row_( + MemtableMutatorRow *&row); + void free_memtable_mutator_row_( PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row); - int parse_mutator_row_( + MemtableMutatorRow *&row); + int parse_memtable_mutator_row_( ObLogTenant *tenant, const ObTabletID &tablet_id, const char *redo_data, @@ -156,7 +164,36 @@ private: int64_t &pos, PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row, + MemtableMutatorRow *&row, + ObCDCTableInfo &table_info, + bool &is_ignored); + int alloc_macroblock_mutator_row_( + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + const blocksstable::ObDatumRow *datum_row, + const common::ObStoreRowkey *row_key, + transaction::ObTxSEQ &seq_no, + blocksstable::ObDmlRowFlag &dml_flag, + MacroBlockMutatorRow *&row); + void free_macroblock_mutator_row_( + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + MacroBlockMutatorRow *&row); + int parse_macroblock_mutator_row_( + ObLogTenant *tenant, + const ObTabletID &tablet_id, + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + MacroBlockMutatorRow *&row, + ObCDCTableInfo &table_info, + bool &is_ignored); + int check_row_need_ignore_( + const bool is_build_baseline, + ObLogTenant *tenant, + PartTransTask &part_trans_task, + ObLogEntryTask &redo_log_entry_task, + MutatorRow &row, + const ObTabletID &tablet_id, ObCDCTableInfo &table_info, bool &is_ignored); int handle_mutator_ext_info_log_( @@ -174,7 +211,7 @@ private: int64_t &pos, PartTransTask &part_trans_task, ObLogEntryTask &redo_log_entry_task, - MutatorRow *&row, + MemtableMutatorRow *&row, bool &is_ignored); private: diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp b/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp index 0e5699ac9..84db09b94 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp +++ b/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp @@ -78,11 +78,10 @@ uint64_t IStmtTask::get_tenant_id() const return host_.get_tenant_id(); } -//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////// MutatorRow /////////////////////////////////////////////// MutatorRow::MutatorRow( common::ObIAllocator &allocator) : - ObMemtableMutatorRow(), allocator_(allocator), deserialized_(false), cols_parsed_(false), @@ -97,242 +96,11 @@ MutatorRow::~MutatorRow() reset(); } -int MutatorRow::deserialize(const char *buf, const int64_t data_len, int64_t &pos) -{ - int ret = OB_SUCCESS; - transaction::ObCLogEncryptInfo empty_clog_encrypt_info; - empty_clog_encrypt_info.init(); - - const bool need_extract_encrypt_meta = false; - share::ObEncryptMeta unused_encrypt_meta; - share::ObCLogEncryptStatMap unused_encrypt_stat_map; - ObEncryptRowBuf row_buf; - - if (OB_UNLIKELY(deserialized_)) { - LOG_ERROR("deserialize twice"); - ret = OB_STATE_NOT_MATCH; - } else if (OB_ISNULL(buf) || OB_UNLIKELY(pos < 0) || OB_UNLIKELY(pos > data_len)) { - LOG_ERROR("invalid argument", K(buf), K(pos), K(data_len)); - ret = OB_INVALID_ARGUMENT; - } else if (OB_FAIL(ObMemtableMutatorRow::deserialize(buf, data_len, pos, - row_buf, empty_clog_encrypt_info, need_extract_encrypt_meta, - unused_encrypt_meta, unused_encrypt_stat_map))) { - LOG_ERROR("deserialize mutator fail", KR(ret), KP(buf), K(data_len), K(pos)); - } else { - deserialized_ = true; - } - - return ret; -} - -int MutatorRow::deserialize_first( - const char *buf, - const int64_t buf_len, - int64_t &pos, - int32_t &row_size) -{ - int ret = OB_SUCCESS; - row_size = 0; - int64_t new_pos = pos; - - if (OB_UNLIKELY(deserialized_)) { - LOG_ERROR("deserialize twice"); - ret = OB_STATE_NOT_MATCH; - } else if (OB_ISNULL(buf) || OB_UNLIKELY(pos < 0) || OB_UNLIKELY(pos > buf_len)) { - LOG_ERROR("invalid argument", K(buf), K(pos), K(buf_len)); - ret = OB_INVALID_ARGUMENT; - } else if (OB_FAIL(decode_i32(buf, buf_len, new_pos, (int32_t *)&row_size_))) { - LOG_ERROR("deserialize row_size fail", KR(ret), K(new_pos), K(row_size_)); - } else if (pos + row_size_ > buf_len) { - LOG_ERROR("size overflow", KR(ret), KP(buf), K(buf_len), K(pos), K_(row_size)); - ret = OB_SIZE_OVERFLOW; - } else if (OB_FAIL(decode_vi64(buf, buf_len, new_pos, (int64_t *)&table_id_))) { - LOG_ERROR("deserialize table_id fail", KR(ret), K(new_pos), K(table_id_)); - } else { - row_size = row_size_; - // The pos indicates the position that has been resolved - pos = new_pos; - } - - return ret; -} - -int MutatorRow::deserialize_second( - const char *buf, - const int64_t buf_len, - int64_t &pos, - int64_t &table_version) -{ - int ret = OB_SUCCESS; - table_version = 0; - int64_t new_pos = pos; - - if (OB_UNLIKELY(deserialized_)) { - LOG_ERROR("deserialize twice"); - ret = OB_STATE_NOT_MATCH; - } else if (OB_ISNULL(buf) || OB_UNLIKELY(pos < 0) || OB_UNLIKELY(pos > buf_len)) { - LOG_ERROR("invalid argument", K(buf), K(pos), K(buf_len)); - ret = OB_INVALID_ARGUMENT; - } else if (OB_FAIL(rowkey_.deserialize(buf, buf_len, new_pos))) { - LOG_ERROR("deserialize rowkey fail", KR(ret), K(new_pos), K(rowkey_)); - } else if (OB_FAIL(decode_vi64(buf, buf_len, new_pos, &table_version_))) { - LOG_ERROR("deserialize table_version fail", KR(ret), K(new_pos), K(table_version_)); - } else { - table_version = table_version_; - // The pos indicates the position that has been resolved - pos = new_pos; - } - - return ret; -} - -// If obj2str_helper is empty, then won’t conversion of obj to string -// also allow table schema to be empty -int MutatorRow::parse_cols( - ObObj2strHelper *obj2str_helper /* = NULL */, - const uint64_t tenant_id, - const uint64_t table_id, - const TableSchemaInfo *tb_schema_info /* = NULL */, - const ObTimeZoneInfoWrap *tz_info_wrap, - const bool enable_output_hidden_primary_key /* = false */, - const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info /* = NULL */) -{ - int ret = OB_SUCCESS; - - if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id) - || OB_UNLIKELY(OB_INVALID_ID == table_id)) { - ret = OB_INVALID_ARGUMENT; - LOG_ERROR("invalid args", KR(ret), K(tenant_id), K(table_id)); - } else if (OB_UNLIKELY(cols_parsed_)) { - LOG_ERROR("columns has been parsed", K(cols_parsed_)); - ret = OB_STATE_NOT_MATCH; - } else if (OB_UNLIKELY(! deserialized_)) { - LOG_ERROR("row has not been deserialized"); - ret = OB_STATE_NOT_MATCH; - } - - // parse value of new column - if (OB_SUCC(ret)) { - if (OB_ISNULL(new_row_.data_) || OB_UNLIKELY(new_row_.size_ <= 0)) { - LOG_WARN("new row data is empty", K(new_row_), - "mutator_row", (const ObMemtableMutatorRow &)(*this)); - new_cols_.reset(); - } else if (OB_FAIL(parse_columns_(true/*is_parse_new_col*/, new_row_.data_, new_row_.size_, - obj2str_helper, tenant_id, table_id, tb_schema_info, tz_info_wrap, enable_output_hidden_primary_key, - all_ddl_operation_table_schema_info, new_cols_))) { - LOG_ERROR("parse new columns fail", KR(ret), K(tenant_id), K(table_id), K(new_row_), K(obj2str_helper), - K(tb_schema_info), K(enable_output_hidden_primary_key)); - } else { - // succ - } - } - - // parse value of old column - if (OB_SUCC(ret)) { - if (OB_ISNULL(old_row_.data_) || OB_UNLIKELY(old_row_.size_ <= 0)) { - // no old cols - old_cols_.reset(); - } else if (OB_FAIL(parse_columns_(false/*is_parse_new_col*/, old_row_.data_, old_row_.size_, - obj2str_helper, tenant_id, table_id, tb_schema_info, tz_info_wrap, enable_output_hidden_primary_key, - all_ddl_operation_table_schema_info, old_cols_))) { - LOG_ERROR("parse old columns fail", KR(ret), K(tenant_id), K(table_id), K(old_row_), K(obj2str_helper), - K(tb_schema_info), K(enable_output_hidden_primary_key)); - } else { - // succ - } - } - - // parse rowkey data - if (OB_SUCC(ret)) { - rowkey_cols_.reset(); - - if (OB_FAIL(parse_rowkey_( - rowkey_cols_, - rowkey_, - obj2str_helper, - tenant_id, - table_id, - tb_schema_info, - tz_info_wrap, - enable_output_hidden_primary_key))) { - LOG_ERROR("parse_rowkey_ fail", KR(ret), K(rowkey_), K(obj2str_helper), - K(enable_output_hidden_primary_key)); - } else { - // succ - } - } - - if (OB_SUCC(ret)) { - cols_parsed_ = true; - } - - return ret; -} - -template -int MutatorRow::parse_cols( - const CDC_INNER_TABLE_SCHEMA &inner_table_schema_info) -{ - int ret = OB_SUCCESS; - const share::schema::ObTableSchema &table_schema = inner_table_schema_info.get_table_schema(); - - if (OB_UNLIKELY(cols_parsed_)) { - ret = OB_STATE_NOT_MATCH; - LOG_ERROR("columns has been parsed", KR(ret), K(cols_parsed_)); - } else if (OB_UNLIKELY(! deserialized_)) { - ret = OB_STATE_NOT_MATCH; - LOG_ERROR("row has not been deserialized", KR(ret)); - } - - // parse value of new column - if (OB_SUCC(ret)) { - if (OB_ISNULL(new_row_.data_) || OB_UNLIKELY(new_row_.size_ <= 0)) { - LOG_WARN("new row data is empty", K(new_row_), - "mutator_row", (const ObMemtableMutatorRow &)(*this)); - new_cols_.reset(); - } else if (OB_FAIL(parse_columns_(true/*is_parse_new_col*/, new_row_.data_, - new_row_.size_, inner_table_schema_info, new_cols_))) { - LOG_ERROR("parse new columns fail", KR(ret), K(new_row_), K(table_schema)); - } else { - // succ - } - } - - // parse value of old column - if (OB_SUCC(ret)) { - if (OB_ISNULL(old_row_.data_) || OB_UNLIKELY(old_row_.size_ <= 0)) { - // no old cols - old_cols_.reset(); - } else if (OB_FAIL(parse_columns_(false/*is_parse_new_col*/, old_row_.data_, - old_row_.size_, inner_table_schema_info, old_cols_))) { - LOG_ERROR("parse old columns fail", KR(ret), K(old_row_), K(table_schema)); - } else { - // succ - } - } - - // parse rowkey data - if (OB_SUCC(ret)) { - rowkey_cols_.reset(); - - if (OB_FAIL(parse_rowkey_(table_schema, rowkey_, rowkey_cols_))) { - LOG_ERROR("parse_rowkey_ fail", KR(ret), K(rowkey_)); - } else { - // succ - } - } - - if (OB_SUCC(ret)) { - cols_parsed_ = true; - } - - return ret; -} - int MutatorRow::parse_columns_( const bool is_parse_new_col, - const char *col_data, - const int64_t col_data_size, + const blocksstable::ObDatumRow &datum_row, + const blocksstable::ObDmlRowFlag &dml_flag, + const int64_t rowkey_cnt, ObObj2strHelper *obj2str_helper, const uint64_t tenant_id, const uint64_t table_id, @@ -343,26 +111,32 @@ int MutatorRow::parse_columns_( ColValueList &cols) { int ret = OB_SUCCESS; - blocksstable::ObRowReader row_reader; - blocksstable::ObDatumRow datum_row(tenant_id); + // warpper cols for udt column values ObCDCUdtValueMap udt_value_map(allocator_, tb_schema_info, cols); - - // NOTE: Allow obj2str_helper and column_schema to be empty - if (OB_ISNULL(col_data) || OB_UNLIKELY(col_data_size <= 0)) { + if (OB_UNLIKELY(!datum_row.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_ERROR("invalid argument", KR(ret), K(col_data_size), K(col_data)); - } - // Validate cols values - else if (OB_UNLIKELY(cols.num_ > 0)) { - ret = OB_INVALID_ARGUMENT; - LOG_ERROR("column value list is not reseted", KR(ret), K(cols)); - } else if (OB_FAIL(row_reader.read_row(col_data, col_data_size, nullptr, datum_row))) { - LOG_WARN("Failed to read datum row", KR(ret), K(tenant_id), K(table_id), K(is_parse_new_col)); + LOG_ERROR("datum_row in invalid", KR(ret), K(datum_row)); } else { OBLOG_FORMATTER_LOG(DEBUG, "prepare to handle datum_row", K(is_parse_new_col), K(datum_row)); // Iterate through all Cells using Cell Reader + // The normal row and macroblock row is different: + // Normal Row: [rowkey column | user column] + // MacroBlock Row: [rowkey column | extra rowkey column | user column] + // Formatter need to filter the extra rowkey column + const int64_t macroblock_row_user_column_idx = rowkey_cnt + OB_MAX_EXTRA_ROWKEY_COLUMN_NUMBER; + // record the offset of the stored column between column + int64_t column_offset = 0; + for (int64_t column_stored_idx = 0; OB_SUCC(ret) && column_stored_idx < datum_row.get_column_count(); column_stored_idx++) { + if (dml_flag.is_delete_insert()) { + // filter extra rowkey column + if (column_stored_idx >= rowkey_cnt && column_stored_idx < macroblock_row_user_column_idx) continue; + if (column_stored_idx == macroblock_row_user_column_idx) { + column_offset = OB_MAX_EXTRA_ROWKEY_COLUMN_NUMBER; + } + } + const ObObj *value = NULL; uint64_t column_id = OB_INVALID_ID; ColumnSchemaInfo *column_schema_info = NULL; @@ -374,11 +148,11 @@ int MutatorRow::parse_columns_( } else if (OB_FAIL(get_column_info_( tb_schema_info, all_ddl_operation_table_schema_info, - column_stored_idx, + column_stored_idx - column_offset, false/*is_rowkey_column_idx*/, column_id, column_schema_info))) { - LOG_ERROR("get_column_info", KR(ret), K_(table_id), K(column_stored_idx)); + LOG_ERROR("get_column_info", KR(ret), K(table_id), K(column_stored_idx)); } else if (datum.is_nop()) { OBLOG_FORMATTER_LOG(DEBUG, "handle nop datum", K(column_stored_idx), K(is_parse_new_col), K(datum)); if (OB_NOT_NULL(column_schema_info) && column_schema_info->is_usr_column()) { @@ -426,7 +200,7 @@ int MutatorRow::parse_columns_( if (OB_FAIL(set_obj_propertie_( column_id, - column_stored_idx, + column_stored_idx - column_offset, column_schema_info, all_ddl_operation_table_schema_info, obj_meta, @@ -444,6 +218,10 @@ int MutatorRow::parse_columns_( // do nothing } else if (is_lob_storage) { const ObLobCommon &lob_common = datum.get_lob_data(); + + // Incremental direct load doesn't support lob with outrow in phase1 and Observer will + // disallow the behavior which loads lob data with outrow. + // is_out_row = ! lob_common.in_row_ && (!dml_flag.is_delete_insert()); is_out_row = ! lob_common.in_row_; OBLOG_FORMATTER_LOG(DEBUG, "handle_lob_v2_data", K(is_parse_new_col), K(column_stored_idx), K(lob_common), K(obj)); @@ -467,7 +245,7 @@ int MutatorRow::parse_columns_( LOG_ERROR("allocate memory for ObLobDataGetCtx fail", KR(ret), "size", sizeof(ObLobDataGetCtx)); } else { new(lob_data_get_ctx) ObLobDataGetCtx(); - lob_data_get_ctx->reset((void *)(&new_lob_ctx_cols_), column_id, dml_flag_, &lob_data); + lob_data_get_ctx->reset((void *)(&new_lob_ctx_cols_), column_id, dml_flag, &lob_data); new_lob_ctx_cols_.add(lob_data_get_ctx); } @@ -730,7 +508,7 @@ int MutatorRow::parse_rowkey_( if (OB_UNLIKELY(rowkey_count != rowkey_info.get_size())) { ret = OB_INVALID_DATA; LOG_ERROR("rowkey count does not match schema", KR(ret), - K(tenant_id), K(table_id), K(rowkey_count), K(rowkey_info), KPC(tb_schema_info)); + K(tenant_id), K(table_id), K(rowkey), K(rowkey_count), K(rowkey_info), KPC(tb_schema_info)); } else if (! column_schema_info->is_usr_column()) { // ignore hidden rowkey column OBLOG_FORMATTER_LOG(DEBUG, "ignore non user-required rowkey column", KPC(column_schema_info), @@ -767,28 +545,17 @@ int MutatorRow::parse_rowkey_( template int MutatorRow::parse_columns_( const bool is_parse_new_col, - const char *col_data, - const int64_t col_data_size, + const blocksstable::ObDatumRow &datum_row, const CDC_INNER_TABLE_SCHEMA &inner_table_schema, ColValueList &cols) { int ret = OB_SUCCESS; - blocksstable::ObRowReader row_reader; - blocksstable::ObDatumRow datum_row(OB_SERVER_TENANT_ID); const ObArray &col_des_array = inner_table_schema.get_cols_des_array(); const share::schema::ObTableSchema &table_schema = inner_table_schema.get_table_schema(); - // NOTE: Allow obj2str_helper and column_schema to be empty - if (OB_ISNULL(col_data) || OB_UNLIKELY(col_data_size <= 0)) { + if (OB_UNLIKELY(!datum_row.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_ERROR("invalid argument", KR(ret), K(col_data_size), K(col_data)); - } - // Validate cols values - else if (OB_UNLIKELY(cols.num_ > 0)) { - ret = OB_INVALID_ARGUMENT; - LOG_ERROR("column value list is not reseted", KR(ret), K(cols)); - } else if (OB_FAIL(row_reader.read_row(col_data, col_data_size, nullptr, datum_row))) { - LOG_ERROR("Failed to read datum row", KR(ret)); + LOG_ERROR("datum_row is invalid", KR(ret), K(datum_row)); } else { OBLOG_FORMATTER_LOG(DEBUG, "parse_columns_", K(is_parse_new_col), K(datum_row)); @@ -806,7 +573,7 @@ int MutatorRow::parse_columns_( } else if (OB_INVALID_ID == column_id) { // Note: the column_id obtained here may be invalid // For example a delete statement with only one cell and an invalid column_id in the cell - OBLOG_FORMATTER_LOG(DEBUG, "cell column_id is invalid", K(i), K(datum_row), K_(table_id), K_(rowkey)); + OBLOG_FORMATTER_LOG(DEBUG, "cell column_id is invalid", K(i), K(datum_row)); } else { if (OB_SUCC(ret)) { ObObjMeta obj_meta; @@ -890,8 +657,8 @@ int MutatorRow::add_column_( // NOTE: Allow obj2str_helper and column_schema to be empty if (OB_ISNULL(cv_node)) { + LOG_ERROR("allocate memory for ColValue fail", "size", sizeof(ColValue)); ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("allocate memory for ColValue fail", KR(ret), "size", sizeof(ColValue)); } else { cv_node->reset(); cv_node->value_ = *value; @@ -962,8 +729,6 @@ void MutatorRow::reset() rowkey_cols_.reset(); new_lob_ctx_cols_.reset(); - - ObMemtableMutatorRow::reset(); } int MutatorRow::get_cols( @@ -998,7 +763,465 @@ int MutatorRow::get_cols( return ret; } -int MutatorRow::parse_ext_info_log(ObString &ext_info_log) +//////////////////////////////////////// MutatorRow /////////////////////////////////////////////// + +//////////////////////////////////////// MacroBlockMutatorRow /////////////////////////////////////////////// +MacroBlockMutatorRow::MacroBlockMutatorRow( + common::ObIAllocator &allocator, + const blocksstable::ObDmlRowFlag &dml_flag, + const transaction::ObTxSEQ &seq_no) : + MutatorRow(allocator), + is_inited_(false), + table_id_(OB_INVALID_ID), + dml_flag_(dml_flag), + seq_no_(seq_no), + row_(), + row_key_() +{ + deserialized_ = true; +} + +MacroBlockMutatorRow::~MacroBlockMutatorRow() +{ + reset(); +} + +int MacroBlockMutatorRow::init(ObIAllocator &allocator, const blocksstable::ObDatumRow &src_datum_row, const common::ObStoreRowkey &src_row_key) +{ + int ret = OB_SUCCESS; + + if (IS_INIT) { + ret = OB_INIT_TWICE; + LOG_ERROR("MacroBlockMutatorRow has been initialized", KR(ret)); + } else if (OB_FAIL(row_.init(allocator, src_datum_row.get_capacity()))) { + LOG_ERROR("row_ init failed", KR(ret), K(src_datum_row)); + } else if (OB_FAIL(row_.deep_copy(src_datum_row, allocator))) { + LOG_ERROR("row_ deep_copy failed", KR(ret), K(src_datum_row)); + } else if (OB_FAIL(src_row_key.deep_copy(row_key_, allocator))) { + LOG_ERROR("row_key_ deep_copy failed", KR(ret), K(src_row_key)); + } else { + is_inited_ = true; + } + + return ret; +} + +void MacroBlockMutatorRow::reset() +{ + is_inited_ = false; + table_id_ = OB_INVALID_ID; + dml_flag_.reset(); + seq_no_.reset(); + row_.reset(); + row_key_.reset(); + MutatorRow::reset(); +} + +// Parse the column data +// If obj2str_helper is empty, do not convert obj to string +int MacroBlockMutatorRow::parse_cols( + ObObj2strHelper *obj2str_helper /* = NULL */, + const uint64_t tenant_id, + const uint64_t table_id, + const TableSchemaInfo *tb_schema_info /* = NULL */, + const ObTimeZoneInfoWrap *tz_info_wrap, + const bool enable_output_hidden_primary_key /* = false */, + const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info /* = NULL */) +{ + int ret = OB_SUCCESS; + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_ERROR("MacroBlockMutatorRow has not been initialized", KR(ret)); + } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id) + || OB_UNLIKELY(OB_INVALID_ID == table_id)) { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("invalid args", KR(ret), K(tenant_id), K(table_id)); + } else if (OB_UNLIKELY(cols_parsed_)) { + LOG_ERROR("columns has been parsed", K(cols_parsed_)); + ret = OB_STATE_NOT_MATCH; + } else if (OB_UNLIKELY(! deserialized_)) { + LOG_ERROR("row has not been deserialized"); + ret = OB_STATE_NOT_MATCH; + } + + // parse value of new column + if (OB_SUCC(ret)) { + if (OB_FAIL(parse_columns_( + true, + row_, + dml_flag_, + row_key_.get_obj_cnt(), + obj2str_helper, + tenant_id, + table_id, + tb_schema_info, + tz_info_wrap, + enable_output_hidden_primary_key, + all_ddl_operation_table_schema_info, + new_cols_))) { + LOG_ERROR("parse new columns fail", KR(ret), K(tenant_id), K(table_id), K(obj2str_helper), + K(tb_schema_info), K(enable_output_hidden_primary_key)); + } + } + + // parse rowkey data + if (OB_SUCC(ret)) { + rowkey_cols_.reset(); + if (OB_FAIL(parse_rowkey_( + rowkey_cols_, + row_key_, + obj2str_helper, + tenant_id, + table_id, + tb_schema_info, + tz_info_wrap, + enable_output_hidden_primary_key))) { + LOG_ERROR("parse_rowkey_ fail", KR(ret), K(row_key_), K(obj2str_helper), K(enable_output_hidden_primary_key)); + } else { + // succ + } + } + + if (OB_SUCC(ret)) { + cols_parsed_ = true; + } + + return ret; +} + +// Parse the column data based on ObTableSchema +int MacroBlockMutatorRow::parse_cols(const ObCDCLobAuxTableSchemaInfo &inner_table_schema_info) +{ + int ret = OB_SUCCESS; + const share::schema::ObTableSchema &table_schema = inner_table_schema_info.get_table_schema(); + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_ERROR("MacroBlockMutatorRow has not been initialized", KR(ret)); + } else if (OB_UNLIKELY(cols_parsed_)) { + ret = OB_STATE_NOT_MATCH; + LOG_ERROR("columns has been parsed", KR(ret), K(cols_parsed_)); + } else if (OB_UNLIKELY(! deserialized_)) { + ret = OB_STATE_NOT_MATCH; + LOG_ERROR("row has not been deserialized", KR(ret)); + } + + // parse value of new column + if (OB_SUCC(ret)) { + if (OB_FAIL(parse_columns_( + true/*is_parse_new_col*/, + row_, + inner_table_schema_info, + new_cols_))) { + LOG_ERROR("parse new columns fail", KR(ret), K(table_schema)); + } else { + // succ + } + } + + return ret; +} + +int MacroBlockMutatorRow::parse_ext_info_log(ObString &ext_info_log) +{ + int ret = OB_NOT_SUPPORTED; + LOG_WARN("macroblock mutator row parse_ext_info_log is not supported", KR(ret)); + return ret; +} + +//////////////////////////////////////// MacroBlockMutatorRow /////////////////////////////////////////////// + +//////////////////////////////////////// MemtableMutatorRow /////////////////////////////////////////////// + +MemtableMutatorRow::MemtableMutatorRow( + common::ObIAllocator &allocator) : + ObMemtableMutatorRow(), + MutatorRow(allocator) +{} + +MemtableMutatorRow::~MemtableMutatorRow() +{ + reset(); +} + +void MemtableMutatorRow::reset() +{ + ObMemtableMutatorRow::reset(); + MutatorRow::reset(); +} + +int MemtableMutatorRow::deserialize(const char *buf, const int64_t data_len, int64_t &pos) +{ + int ret = OB_SUCCESS; + transaction::ObCLogEncryptInfo empty_clog_encrypt_info; + empty_clog_encrypt_info.init(); + + const bool need_extract_encrypt_meta = false; + share::ObEncryptMeta unused_encrypt_meta; + share::ObCLogEncryptStatMap unused_encrypt_stat_map; + ObEncryptRowBuf row_buf; + + if (OB_UNLIKELY(deserialized_)) { + LOG_ERROR("deserialize twice"); + ret = OB_STATE_NOT_MATCH; + } else if (OB_ISNULL(buf) || OB_UNLIKELY(pos < 0) || OB_UNLIKELY(pos > data_len)) { + LOG_ERROR("invalid argument", K(buf), K(pos), K(data_len)); + ret = OB_INVALID_ARGUMENT; + } else if (OB_FAIL(ObMemtableMutatorRow::deserialize(buf, data_len, pos, + row_buf, empty_clog_encrypt_info, need_extract_encrypt_meta, + unused_encrypt_meta, unused_encrypt_stat_map))) { + LOG_ERROR("deserialize mutator fail", KR(ret), KP(buf), K(data_len), K(pos)); + } else { + deserialized_ = true; + } + + return ret; +} + +int MemtableMutatorRow::deserialize_first( + const char *buf, + const int64_t buf_len, + int64_t &pos, + int32_t &row_size) +{ + int ret = OB_SUCCESS; + row_size = 0; + int64_t new_pos = pos; + + if (OB_UNLIKELY(deserialized_)) { + LOG_ERROR("deserialize twice"); + ret = OB_STATE_NOT_MATCH; + } else if (OB_ISNULL(buf) || OB_UNLIKELY(pos < 0) || OB_UNLIKELY(pos > buf_len)) { + LOG_ERROR("invalid argument", K(buf), K(pos), K(buf_len)); + ret = OB_INVALID_ARGUMENT; + } else if (OB_FAIL(decode_i32(buf, buf_len, new_pos, (int32_t *)&row_size_))) { + LOG_ERROR("deserialize row_size fail", KR(ret), K(new_pos), K(row_size_)); + } else if (pos + row_size_ > buf_len) { + LOG_ERROR("size overflow", KR(ret), KP(buf), K(buf_len), K(pos), K_(row_size)); + ret = OB_SIZE_OVERFLOW; + } else if (OB_FAIL(decode_vi64(buf, buf_len, new_pos, (int64_t *)&table_id_))) { + LOG_ERROR("deserialize table_id fail", KR(ret), K(new_pos), K(table_id_)); + } else { + row_size = row_size_; + // The pos indicates the position that has been resolved + pos = new_pos; + } + + return ret; +} + +int MemtableMutatorRow::deserialize_second( + const char *buf, + const int64_t buf_len, + int64_t &pos, + int64_t &table_version) +{ + int ret = OB_SUCCESS; + table_version = 0; + int64_t new_pos = pos; + + if (OB_UNLIKELY(deserialized_)) { + LOG_ERROR("deserialize twice"); + ret = OB_STATE_NOT_MATCH; + } else if (OB_ISNULL(buf) || OB_UNLIKELY(pos < 0) || OB_UNLIKELY(pos > buf_len)) { + LOG_ERROR("invalid argument", K(buf), K(pos), K(buf_len)); + ret = OB_INVALID_ARGUMENT; + } else if (OB_FAIL(rowkey_.deserialize(buf, buf_len, new_pos))) { + LOG_ERROR("deserialize rowkey fail", KR(ret), K(new_pos), K(rowkey_)); + } else if (OB_FAIL(decode_vi64(buf, buf_len, new_pos, &table_version_))) { + LOG_ERROR("deserialize table_version fail", KR(ret), K(new_pos), K(table_version_)); + } else { + table_version = table_version_; + // The pos indicates the position that has been resolved + pos = new_pos; + } + + return ret; +} + +// If obj2str_helper is empty, then won’t conversion of obj to string +// also allow table schema to be empty +int MemtableMutatorRow::parse_cols( + ObObj2strHelper *obj2str_helper /* = NULL */, + const uint64_t tenant_id, + const uint64_t table_id, + const TableSchemaInfo *tb_schema_info /* = NULL */, + const ObTimeZoneInfoWrap *tz_info_wrap, + const bool enable_output_hidden_primary_key /* = false */, + const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info /* = NULL */) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id) + || OB_UNLIKELY(OB_INVALID_ID == table_id)) { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("invalid args", KR(ret), K(tenant_id), K(table_id)); + } else if (OB_UNLIKELY(cols_parsed_)) { + LOG_ERROR("columns has been parsed", K(cols_parsed_)); + ret = OB_STATE_NOT_MATCH; + } else if (OB_UNLIKELY(! deserialized_)) { + LOG_ERROR("row has not been deserialized"); + ret = OB_STATE_NOT_MATCH; + } + + blocksstable::ObRowReader row_reader; + blocksstable::ObDatumRow datum_row(tenant_id); + + // parse value of new column + if (OB_SUCC(ret)) { + if (OB_ISNULL(new_row_.data_) || OB_UNLIKELY(new_row_.size_ <= 0)) { + LOG_WARN("new row data is empty", K(new_row_), + "mutator_row", (const ObMemtableMutatorRow &)(*this)); + new_cols_.reset(); + } else if (OB_FAIL(row_reader.read_row(new_row_.data_, new_row_.size_, nullptr, datum_row))) { + LOG_WARN("read datum row fail", KR(ret), K(datum_row)); + } else if (OB_FAIL(parse_columns_( + true/*is_parse_new_col*/, + datum_row, + dml_flag_, + rowkey_.get_obj_cnt(), + obj2str_helper, + tenant_id, + table_id, + tb_schema_info, + tz_info_wrap, + enable_output_hidden_primary_key, + all_ddl_operation_table_schema_info, + new_cols_))) { + LOG_ERROR("parse new columns fail", KR(ret), K(tenant_id), K(table_id), K(new_row_), K(obj2str_helper), + K(tb_schema_info), K(enable_output_hidden_primary_key)); + } else { + // succ + } + } + + // parse value of old column + if (OB_SUCC(ret)) { + if (OB_ISNULL(old_row_.data_) || OB_UNLIKELY(old_row_.size_ <= 0)) { + // no old cols + old_cols_.reset(); + } else if (OB_FAIL(row_reader.read_row(old_row_.data_, old_row_.size_, nullptr, datum_row))) { + LOG_WARN("read datum row fail", KR(ret), K(datum_row)); + } else if (OB_FAIL(parse_columns_( + false/*is_parse_new_col*/, + datum_row, + dml_flag_, + rowkey_.get_obj_cnt(), + obj2str_helper, + tenant_id, + table_id, + tb_schema_info, + tz_info_wrap, + enable_output_hidden_primary_key, + all_ddl_operation_table_schema_info, + old_cols_))) { + LOG_ERROR("parse old columns fail", KR(ret), K(tenant_id), K(table_id), K(old_row_), K(obj2str_helper), + K(tb_schema_info), K(enable_output_hidden_primary_key)); + } else { + // succ + } + } + + // parse rowkey data + if (OB_SUCC(ret)) { + rowkey_cols_.reset(); + + if (OB_FAIL(parse_rowkey_( + rowkey_cols_, + rowkey_, + obj2str_helper, + tenant_id, + table_id, + tb_schema_info, + tz_info_wrap, + enable_output_hidden_primary_key))) { + LOG_ERROR("parse_rowkey_ fail", KR(ret), K(rowkey_), K(obj2str_helper), + K(enable_output_hidden_primary_key)); + } else { + // succ + } + } + + if (OB_SUCC(ret)) { + cols_parsed_ = true; + } + + return ret; +} + +int MemtableMutatorRow::parse_cols(const ObCDCLobAuxTableSchemaInfo &inner_table_schema_info) +{ + int ret = OB_SUCCESS; + const share::schema::ObTableSchema &table_schema = inner_table_schema_info.get_table_schema(); + + if (OB_UNLIKELY(cols_parsed_)) { + ret = OB_STATE_NOT_MATCH; + LOG_ERROR("columns has been parsed", KR(ret), K(cols_parsed_)); + } else if (OB_UNLIKELY(! deserialized_)) { + ret = OB_STATE_NOT_MATCH; + LOG_ERROR("row has not been deserialized", KR(ret)); + } + + blocksstable::ObRowReader row_reader; + blocksstable::ObDatumRow datum_row(OB_SERVER_TENANT_ID); + + // parse value of new column + if (OB_SUCC(ret)) { + if (OB_ISNULL(new_row_.data_) || OB_UNLIKELY(new_row_.size_ <= 0)) { + LOG_WARN("new row data is empty", K(new_row_), + "mutator_row", (const ObMemtableMutatorRow &)(*this)); + new_cols_.reset(); + } else if (OB_FAIL(row_reader.read_row(new_row_.data_, new_row_.size_, nullptr, datum_row))) { + LOG_WARN("read datum row fail", KR(ret), K(datum_row)); + } else if (OB_FAIL(parse_columns_( + true/*is_parse_new_col*/, + datum_row, + inner_table_schema_info, + new_cols_))) { + LOG_ERROR("parse new columns fail", KR(ret), K(new_row_), K(table_schema)); + } else { + // succ + } + } + + // parse value of old column + if (OB_SUCC(ret)) { + if (OB_ISNULL(old_row_.data_) || OB_UNLIKELY(old_row_.size_ <= 0)) { + // no old cols + old_cols_.reset(); + } else if (OB_FAIL(row_reader.read_row(old_row_.data_, old_row_.size_, nullptr, datum_row))) { + LOG_WARN("read datum row fail", KR(ret), K(datum_row)); + } else if (OB_FAIL(parse_columns_( + false/*is_parse_new_col*/, + datum_row, + inner_table_schema_info, + old_cols_))) { + LOG_ERROR("parse old columns fail", KR(ret), K(old_row_), K(table_schema)); + } else { + // succ + } + } + + // parse rowkey data + if (OB_SUCC(ret)) { + rowkey_cols_.reset(); + + if (OB_FAIL(parse_rowkey_(table_schema, rowkey_, rowkey_cols_))) { + LOG_ERROR("parse_rowkey_ fail", KR(ret), K(rowkey_)); + } else { + // succ + } + } + + if (OB_SUCC(ret)) { + cols_parsed_ = true; + } + + return ret; +} + +int MemtableMutatorRow::parse_ext_info_log(ObString &ext_info_log) { int ret = OB_SUCCESS; blocksstable::ObRowReader row_reader; @@ -1011,9 +1234,9 @@ int MutatorRow::parse_ext_info_log(ObString &ext_info_log) ret = OB_STATE_NOT_MATCH; LOG_ERROR("row has not been deserialized", KR(ret)); } else if (OB_ISNULL(new_row_.data_) || OB_UNLIKELY(new_row_.size_ <= 0)) { - LOG_WARN("new row data is empty", K(new_row_), - "mutator_row", (const ObMemtableMutatorRow &)(*this)); - new_cols_.reset(); + LOG_WARN("new row data is empty", K(new_row_), + "mutator_row", (const ObMemtableMutatorRow &)(*this)); + new_cols_.reset(); } else if (OB_UNLIKELY(new_cols_.num_ > 0)) { ret = OB_INVALID_ARGUMENT; LOG_ERROR("column value list is not reseted", KR(ret), K(new_cols_)); @@ -1029,6 +1252,8 @@ int MutatorRow::parse_ext_info_log(ObString &ext_info_log) return ret; } +//////////////////////////////////////// MemtableMutatorRow /////////////////////////////////////////////// + //////////////////////////////////////// DmlStmtUniqueID /////////////////////////////////////////////// int64_t DmlStmtUniqueID::get_dml_unique_id_length() const { @@ -1131,8 +1356,7 @@ DmlStmtTask::DmlStmtTask( row_(row) { // set hash value - IStmtTask::set_hash_value(row.rowkey_.murmurhash(host.get_tls_id().hash())); - + IStmtTask::set_hash_value(row_.hash(host.get_tls_id().hash())); } DmlStmtTask::~DmlStmtTask() { reset(); } @@ -1237,7 +1461,7 @@ DdlStmtTask::DdlStmtTask(PartTransTask &host, MutatorRow &row) : ddl_exec_tenant_id_(OB_INVALID_TENANT_ID) { // set hash value - IStmtTask::set_hash_value(row.rowkey_.murmurhash(host.get_tls_id().hash())); + IStmtTask::set_hash_value(row_.hash(host.get_tls_id().hash())); ddl_op_schema_version_str_[0] = '\0'; } @@ -1536,11 +1760,11 @@ int DdlStmtTask::parse_ddl_info_( ddl_op_tablegroup_id_ = OB_INVALID_ID; ddl_exec_tenant_id_ = OB_INVALID_TENANT_ID; - if (blocksstable::ObDmlFlag::DF_LOCK == row_.dml_flag_) { + if (row_.get_dml_flag().is_lock()) { // do nothing } // only parse insert stmt - else if (blocksstable::ObDmlFlag::DF_INSERT != row_.dml_flag_) { + else if (!row_.get_dml_flag().is_insert()) { LOG_WARN("ignore NON-INSERT statement of table __all_ddl_operation", K(row_)); contain_ddl_stmt = false; } else if (rowkey_cols->num_ != 1) { @@ -1841,7 +2065,7 @@ void DdlStmtTask::reset() //////////////////////////////////////////////////////////////////////////////////// -ObLogEntryTask::ObLogEntryTask(PartTransTask &host) : +ObLogEntryTask::ObLogEntryTask(PartTransTask &host, const bool is_direct_load_inc_log) : host_(&host), participant_(NULL), tls_id_(), @@ -1851,7 +2075,11 @@ ObLogEntryTask::ObLogEntryTask(PartTransTask &host) : stmt_list_(), formatted_stmt_num_(0), row_ref_cnt_(0), - arena_allocator_(host.get_log_entry_task_base_allocator(), "LogEntryTask", host.get_tenant_id()) + arena_allocator_( + host.get_log_entry_task_base_allocator(), + "LogEntryTask", + host.get_tenant_id(), + is_direct_load_inc_log ? OB_MALLOC_BIG_BLOCK_SIZE : OB_MALLOC_NORMAL_BLOCK_SIZE) { } @@ -2490,6 +2718,43 @@ int PartTransTask::push_redo_log( return ret; } +int PartTransTask::push_direct_load_inc_log( + const transaction::ObTransID &trans_id, + const palf::LSN &log_lsn, + const int64_t tstamp, + const char *buf, + const int64_t buf_len) +{ + int ret = OB_SUCCESS; + const bool need_store_data = need_store_data_(); + const uint8_t row_flags = ObTransRowFlag::NORMAL_ROW; + + if (OB_UNLIKELY(!log_lsn.is_valid()) + || OB_ISNULL(buf) + || OB_UNLIKELY(buf_len <= 0)) { + LOG_ERROR("invalid arguments", K(log_lsn), KP(buf), K(buf_len)); + ret = OB_INVALID_ARGUMENT; + } else if (OB_FAIL(push_dml_redo_on_row_start_(need_store_data, true/*enable_direct_load_inc*/, + log_lsn, buf, buf_len, buf_len))) { + if (OB_ENTRY_EXIST == ret) { + // direct load inc log duplicate + } else { + LOG_ERROR("push_direct_load_inc_log_on_row_start_ fail", KR(ret), K(trans_id), K(log_lsn), + KP(buf), K(buf_len)); + } + } else if (need_store_data && OB_FAIL(get_and_submit_store_task_(tls_id_.get_tenant_id(), + row_flags, log_lsn, buf, buf_len))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("get_and_submit_store_task_ fail", KR(ret), K_(tls_id), K(row_flags), K(log_lsn)); + } + } else { + LOG_DEBUG("push direct load inc log", KR(ret), K_(tls_id), K(log_lsn), K(tstamp), K(buf_len), + K(trans_id), K_(sorted_redo_list)); + } + + return ret; +} + int PartTransTask::push_rollback_to_info(const palf::LSN &lsn, const ObTxSEQ &rollback_from, const ObTxSEQ &rollback_to) { int ret = OB_SUCCESS; @@ -2929,8 +3194,8 @@ int PartTransTask::push_redo_on_row_start_( } } } else { - if (OB_FAIL(push_dml_redo_on_row_start_(need_store_data, meta, log_lsn, redo_data, redo_data_size, - mutator_row_size))) { + if (OB_FAIL(push_dml_redo_on_row_start_(need_store_data, false, log_lsn, redo_data, redo_data_size, + mutator_row_size))) { if (OB_ENTRY_EXIST != ret) { LOG_ERROR("push_dml_redo_on_row_start_ fail", KR(ret), K(trans_id), K(meta), K(log_lsn), KP(redo_data), K(redo_data_size)); @@ -2995,7 +3260,7 @@ int PartTransTask::push_ddl_redo_on_row_start_( int PartTransTask::push_dml_redo_on_row_start_( const bool need_store_data, - const memtable::ObMemtableMutatorMeta &meta, + const bool is_direct_load_inc_log, const palf::LSN &log_lsn, const char *redo_data, const int64_t redo_data_size, @@ -3004,7 +3269,6 @@ int PartTransTask::push_dml_redo_on_row_start_( int ret = OB_SUCCESS; char *mutator_row_data = NULL; DmlRedoLogNode *meta_node = NULL; - const uint8_t row_flags = meta.get_flags(); if (OB_ISNULL(meta_node = static_cast(allocator_.alloc(sizeof(DmlRedoLogNode))))) { LOG_ERROR("allocate memory for DmlRedoLogNode fail", "size", sizeof(DmlRedoLogNode)); @@ -3013,7 +3277,7 @@ int PartTransTask::push_dml_redo_on_row_start_( if (! need_store_data) { // The allocator of PartTransTask alloc memory if (OB_ISNULL(mutator_row_data = static_cast(allocator_.alloc(mutator_row_size)))) { - LOG_ERROR("allocate memory for mutator row data fail", K(mutator_row_size), K(meta)); + LOG_ERROR("allocate memory for mutator row data fail", K(mutator_row_size)); ret = OB_ALLOCATE_MEMORY_FAILED; } else { // Fill the data carried in this redo log @@ -3026,6 +3290,10 @@ int PartTransTask::push_dml_redo_on_row_start_( // reset redo log meta node meta_node->init_for_data_persistence(log_lsn, mutator_row_size); } + + if (OB_UNLIKELY(is_direct_load_inc_log)) { + meta_node->set_direct_load_inc_log(); + } } if (OB_SUCC(ret)) { diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_task.h b/src/logservice/libobcdc/src/ob_log_part_trans_task.h index 62eff7353..a7ecf3c1e 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_task.h +++ b/src/logservice/libobcdc/src/ob_log_part_trans_task.h @@ -205,81 +205,56 @@ struct ColValue K_(is_col_nop)); }; -/////////////////////////////////////////////////////////////////////////////////// - typedef LightyList ColValueList; class ObObj2strHelper; -// row value -class MutatorRow : public memtable::ObMemtableMutatorRow +//////////////////////////////////////// MutatorRow /////////////////////////////////////////////// +class MutatorRow { public: explicit MutatorRow(common::ObIAllocator &allocator); virtual ~MutatorRow(); - public: common::ObIAllocator &get_allocator() { return allocator_; } - - // Deserialize a row - virtual int deserialize(const char *buf, const int64_t data_len, int64_t &pos); - - // Support for filtering table data within PG - // Deserialize some fields: first step to get row_size, table_id - int deserialize_first( - const char *buf, - const int64_t data_len, - int64_t &pos, - int32_t &row_size); - - // Deserialize some fields: Step 2 continues the parsing to get the table_version - int deserialize_second( - const char *buf, - const int64_t data_len, - int64_t &pos, - int64_t &table_version); - void reset(); - // Parse the column data // If obj2str_helper is empty, do not convert obj to string - int parse_cols( + virtual int parse_cols( ObObj2strHelper *obj2str_helper = NULL, const uint64_t tenant_id = OB_INVALID_TENANT_ID, const uint64_t table_id = OB_INVALID_ID, const TableSchemaInfo *tb_schema_info = NULL, const ObTimeZoneInfoWrap *tz_info_wrap = nullptr, const bool enable_output_hidden_primary_key = false, - const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info = NULL); - + const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info = NULL) = 0; // Parse the column data based on ObTableSchema - template - int parse_cols( - const CDC_INNER_TABLE_SCHEMA &lob_aux_table_schema_info); - + virtual int parse_cols( const ObCDCLobAuxTableSchemaInfo &lob_aux_table_schema_info) = 0; + virtual int parse_ext_info_log(ObString &ext_info_log) = 0; int get_cols( ColValueList **rowkey_cols, ColValueList **new_cols, ColValueList **old_cols, ObLobDataOutRowCtxList **new_lob_ctx_cols); - ObLobDataOutRowCtxList &get_new_lob_ctx_cols() { return new_lob_ctx_cols_; } - - int parse_ext_info_log(ObString &ext_info_log); + virtual uint64_t hash(const uint64_t hash) const = 0; + virtual uint64_t get_table_id() const = 0; + virtual blocksstable::ObDmlRowFlag get_dml_flag() const = 0; + virtual const transaction::ObTxSEQ &get_seq_no() const = 0; public: TO_STRING_KV( - "Row", static_cast(*this), - K_(deserialized), - K_(cols_parsed), - K_(new_cols), - K_(old_cols), - K_(rowkey_cols)); + K_(deserialized), + K_(cols_parsed), + K_(new_cols), + K_(old_cols), + K_(rowkey_cols)); -private: +protected: int parse_columns_( const bool is_parse_new_col, - const char *col_data, - const int64_t col_data_size, + const blocksstable::ObDatumRow &datum_row, + const blocksstable::ObDmlRowFlag &dml_flag, + const int64_t rowkey_cnt, ObObj2strHelper *obj2str_helper, const uint64_t tenant_id, const uint64_t table_id, @@ -330,8 +305,7 @@ private: template int parse_columns_( const bool is_parse_new_col, - const char *col_data, - const int64_t col_data_size, + const blocksstable::ObDatumRow &datum_row, const CDC_INNER_TABLE_SCHEMA &inner_table_schema, ColValueList &cols); template @@ -351,22 +325,129 @@ private: ObObjMeta &obj_meta, ObObj &obj); -private: - common::ObIAllocator &allocator_; - - bool deserialized_; - bool cols_parsed_; - ColValueList new_cols_; // A list of new values for the columns, currently no primary key values are stored, only normal columns - ColValueList old_cols_; // A list of old values for the columns, currently no primary key values are stored, only normal columns - ColValueList rowkey_cols_; // rowkey column - - ObLobDataOutRowCtxList new_lob_ctx_cols_; - +protected: + common::ObIAllocator &allocator_; + bool deserialized_; + bool cols_parsed_; + ColValueList new_cols_; // A list of new values for the columns, currently no primary key values are stored, only normal columns + ColValueList old_cols_; // A list of old values for the columns, currently no primary key values are stored, only normal columns + ColValueList rowkey_cols_; // rowkey column + ObLobDataOutRowCtxList new_lob_ctx_cols_; private: DISALLOW_COPY_AND_ASSIGN(MutatorRow); }; +//////////////////////////////////////// MutatorRow /////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////// MacroBlockMutatorRow /////////////////////////////////////////////// +class MacroBlockMutatorRow : public MutatorRow +{ +public: + explicit MacroBlockMutatorRow( + common::ObIAllocator &allocator, + const blocksstable::ObDmlRowFlag &dml_flag, + const transaction::ObTxSEQ &seq_no); + + virtual ~MacroBlockMutatorRow(); +public: + int init(ObIAllocator &allocator, const blocksstable::ObDatumRow &src_datum_row, const common::ObStoreRowkey &src_row_key); + void reset(); + // Parse the column data + // If obj2str_helper is empty, do not convert obj to string + int parse_cols( + ObObj2strHelper *obj2str_helper = NULL, + const uint64_t tenant_id = OB_INVALID_TENANT_ID, + const uint64_t table_id = OB_INVALID_ID, + const TableSchemaInfo *tb_schema_info = NULL, + const ObTimeZoneInfoWrap *tz_info_wrap = nullptr, + const bool enable_output_hidden_primary_key = false, + const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info = NULL); + // Parse the column data based on ObTableSchema + int parse_cols(const ObCDCLobAuxTableSchemaInfo &lob_aux_table_schema_info); + int parse_ext_info_log(ObString &ext_info_log); + uint64_t hash(const uint64_t hash) const { return row_key_.murmurhash(hash); } + void set_table_id(const uint64_t table_id) { table_id_ = table_id; } + uint64_t get_table_id() const { return table_id_; } + blocksstable::ObDmlRowFlag get_dml_flag() const { return dml_flag_; } + const transaction::ObTxSEQ &get_seq_no() const { return seq_no_; } + +public: + TO_STRING_KV( + K_(is_inited), + K_(table_id), + K_(dml_flag), + K_(seq_no), + K_(row), + K_(row_key)); +private: + bool is_inited_; + uint64_t table_id_; + blocksstable::ObDmlRowFlag dml_flag_; + transaction::ObTxSEQ seq_no_; + blocksstable::ObDatumRow row_; + common::ObStoreRowkey row_key_; + +private: + DISALLOW_COPY_AND_ASSIGN(MacroBlockMutatorRow); +}; + +//////////////////////////////////////// MacroBlockMutatorRow /////////////////////////////////////////////// + +//////////////////////////////////////// MemtableMutatorRow /////////////////////////////////////////////// +class MemtableMutatorRow : public memtable::ObMemtableMutatorRow, public MutatorRow +{ +public: + explicit MemtableMutatorRow(common::ObIAllocator &allocator); + virtual ~MemtableMutatorRow(); + +public: + // Deserialize a row + int deserialize(const char *buf, const int64_t data_len, int64_t &pos); + + // Support for filtering table data within PG + // Deserialize some fields: first step to get row_size, table_id + int deserialize_first( + const char *buf, + const int64_t data_len, + int64_t &pos, + int32_t &row_size); + + // Deserialize some fields: Step 2 continues the parsing to get the table_version + int deserialize_second( + const char *buf, + const int64_t data_len, + int64_t &pos, + int64_t &table_version); + + void reset(); + + // Parse the column data + // If obj2str_helper is empty, do not convert obj to string + int parse_cols( + ObObj2strHelper *obj2str_helper = NULL, + const uint64_t tenant_id = OB_INVALID_TENANT_ID, + const uint64_t table_id = OB_INVALID_ID, + const TableSchemaInfo *tb_schema_info = NULL, + const ObTimeZoneInfoWrap *tz_info_wrap = nullptr, + const bool enable_output_hidden_primary_key = false, + const ObLogAllDdlOperationSchemaInfo *all_ddl_operation_table_schema_info = NULL); + + // Parse the column data based on ObTableSchema + int parse_cols(const ObCDCLobAuxTableSchemaInfo &lob_aux_table_schema_info); + int parse_ext_info_log(ObString &ext_info_log); + uint64_t hash(const uint64_t hash) const { return rowkey_.murmurhash(hash); } + uint64_t get_table_id() const { return table_id_; } + blocksstable::ObDmlRowFlag get_dml_flag() const { return dml_flag_; } + const transaction::ObTxSEQ &get_seq_no() const { return seq_no_; } + +public: + TO_STRING_KV( + "MutatorRow", static_cast(*this), + "MemtableMutatorRow", static_cast(*this)); +private: + DISALLOW_COPY_AND_ASSIGN(MemtableMutatorRow); +}; + +//////////////////////////////////////// MemtableMutatorRow /////////////////////////////////////////////// #define DELIMITER_STR "_" // The DML unique ID is part_trans_id(tenant_id + ls_id + trans_id) + redo_log_lsn + row_index, the separator is `_` @@ -429,15 +510,17 @@ public: void reset(); int64_t get_global_schema_version() const; - int64_t get_table_version() const { return row_.table_version_; } + int64_t get_table_version() const { return 0; } uint64_t get_table_id() const { return table_id_; } void set_table_id(const uint64_t table_id) { table_id_ = table_id; } const logservice::TenantLSID &get_tls_id() const; - const common::ObStoreRowkey &get_rowkey() const { return row_.rowkey_; } - blocksstable::ObDmlFlag get_dml_flag() const { return row_.dml_flag_; } - bool is_insert() const { return blocksstable::ObDmlFlag::DF_INSERT == row_.dml_flag_; } - bool is_update() const { return blocksstable::ObDmlFlag::DF_UPDATE == row_.dml_flag_; } - bool is_delete() const { return blocksstable::ObDmlFlag::DF_DELETE == row_.dml_flag_; } + // TODO(fankun.fan) + // const common::ObStoreRowkey &get_rowkey() const {} + blocksstable::ObDmlRowFlag get_dml_flag() const { return row_.get_dml_flag(); } + bool is_insert() const { return row_.get_dml_flag().is_insert(); } + bool is_update() const { return row_.get_dml_flag().is_update(); } + bool is_delete() const { return row_.get_dml_flag().is_delete(); } + bool is_put() const { return row_.get_dml_flag().is_delete_insert(); } // Parse the column data // If obj2str_helper is empty, then no conversion of obj to string @@ -474,7 +557,7 @@ public: ObLogEntryTask &get_redo_log_entry_task() { return log_entry_task_; } - const transaction::ObTxSEQ get_row_seq_no() const { return row_.seq_no_; } + const transaction::ObTxSEQ &get_row_seq_no() const { return row_.get_seq_no(); } bool is_callback() const { return 1 == is_callback_; } void mark_callback() { is_callback_ = 1; } @@ -559,7 +642,7 @@ public: uint64_t get_op_tablegroup_id() const { return ddl_op_tablegroup_id_; } int64_t get_op_schema_version() const { return ddl_op_schema_version_; } uint64_t get_exec_tenant_id() const { return ddl_exec_tenant_id_; } - const transaction::ObTxSEQ &get_row_seq_no() const { return row_.seq_no_; } + const transaction::ObTxSEQ &get_row_seq_no() const { return row_.get_seq_no(); } public: // tennat_id(UINT64_MAX: 20) + schema_version(INT64_MAX:19) @@ -646,7 +729,7 @@ typedef LightyList StmtList; class ObLogEntryTask { public: - ObLogEntryTask(PartTransTask &host); + ObLogEntryTask(PartTransTask &host, const bool is_direct_load_inc_log = false); virtual ~ObLogEntryTask(); void reset(); bool is_valid() const; @@ -805,6 +888,13 @@ public: const char *buf, const int64_t buf_len); + int push_direct_load_inc_log( + const transaction::ObTransID &trans_id, + const palf::LSN &log_lsn, + const int64_t tstamp, + const char *buf, + const int64_t buf_len); + /** * @brief: push rollback_to info: * 1. lsn of rollback_to should push into all_recorded_lsns(ObTxRollbackToLog should has independent LogEntry) @@ -1234,7 +1324,7 @@ private: const int64_t mutator_row_size); int push_dml_redo_on_row_start_( const bool need_store_data, - const memtable::ObMemtableMutatorMeta &meta, + const bool is_direct_load_inc_log, const palf::LSN &log_lsn, const char *redo_data, const int64_t redo_data_size, diff --git a/src/logservice/libobcdc/src/ob_log_resource_collector.cpp b/src/logservice/libobcdc/src/ob_log_resource_collector.cpp index 4db0fe0ad..26679a01a 100644 --- a/src/logservice/libobcdc/src/ob_log_resource_collector.cpp +++ b/src/logservice/libobcdc/src/ob_log_resource_collector.cpp @@ -317,7 +317,6 @@ int ObLogResourceCollector::revert_log_entry_task_(ObLogEntryTask *log_entry_tas } } } - log_entry_task_pool->free(log_entry_task); } diff --git a/src/logservice/libobcdc/src/ob_log_trans_log.h b/src/logservice/libobcdc/src/ob_log_trans_log.h index 0df394b85..917268fac 100644 --- a/src/logservice/libobcdc/src/ob_log_trans_log.h +++ b/src/logservice/libobcdc/src/ob_log_trans_log.h @@ -229,6 +229,11 @@ public: // Retrieve the last digit of reserve_field_ bool is_stored() const { return reserve_field_ & 0x01; } + + // Retrieve the third digit of reserve_field_ + bool is_direct_load_inc_log() const { return reserve_field_ & 0x04; } + // Set teh third digit of reserve_field_ to 1 + void set_direct_load_inc_log() { reserve_field_ |= 0x04; } int set_data_info(char *data, int64_t data_len); bool is_readed() const { return ATOMIC_LOAD(&is_readed_); } void set_readed() { ATOMIC_SET(&is_readed_, true); } @@ -267,6 +272,7 @@ private: // An 8 bit reserved field: // The lowest bit represents the data is stored // The second low bit represents the data is parsed when contain rollback to savepoint + // The third low bit represents the log is direct load inc log int8_t reserve_field_; // reserved field }; diff --git a/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.cpp b/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.cpp index 12608d153..63101e082 100644 --- a/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.cpp +++ b/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.cpp @@ -39,7 +39,9 @@ ObLogTransRedoDispatcher::~ObLogTransRedoDispatcher() destroy(); } -int ObLogTransRedoDispatcher::init(const int64_t redo_dispatcher_memory_limit, const bool enable_sort_by_seq_no, IObLogTransStatMgr &trans_stat_mgr) +int ObLogTransRedoDispatcher::init(const int64_t redo_dispatcher_memory_limit, + const bool enable_sort_by_seq_no, + IObLogTransStatMgr &trans_stat_mgr) { int ret = OB_SUCCESS; @@ -417,7 +419,7 @@ int ObLogTransRedoDispatcher::alloc_task_for_redo_(PartTransTask &part_task, if (OB_UNLIKELY(OB_ISNULL(TCTX.log_entry_task_pool_))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("log_entry_task_pool is null!", KR(ret)); - } else if (OB_FAIL(TCTX.log_entry_task_pool_->alloc(log_entry_task, part_task))) { + } else if (OB_FAIL(TCTX.log_entry_task_pool_->alloc(redo_node.is_direct_load_inc_log(), log_entry_task, part_task))) { LOG_ERROR("log_entry_task_pool_ alloc fail", KR(ret), KPC(log_entry_task), K(part_task)); } else if (OB_ISNULL(log_entry_task)) { ret = OB_ERR_UNEXPECTED; diff --git a/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.h b/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.h index e6193f2d0..5a30a3dac 100644 --- a/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.h +++ b/src/logservice/libobcdc/src/ob_log_trans_redo_dispatcher.h @@ -55,7 +55,9 @@ class ObLogTransRedoDispatcher: public IObLogTransRedoDispatcher public: ObLogTransRedoDispatcher(); virtual ~ObLogTransRedoDispatcher(); - int init(const int64_t redo_dispatcher_memory_limit, const bool enable_sort_by_seq_no, IObLogTransStatMgr &trans_stat_mgr); + int init(const int64_t redo_dispatcher_memory_limit, + const bool enable_sort_by_seq_no, + IObLogTransStatMgr &trans_stat_mgr); void destroy(); public: @@ -118,7 +120,6 @@ private: int64_t cur_dispatched_redo_memory_; // can dynamicly modify IObLogTransStatMgr *trans_stat_mgr_; bool enable_sort_by_seq_no_; // config by init and can't change unless progress restart - private: DISALLOW_COPY_AND_ASSIGN(ObLogTransRedoDispatcher); }; diff --git a/src/logservice/libobcdc/src/ob_log_utils.cpp b/src/logservice/libobcdc/src/ob_log_utils.cpp index 6011a1975..d2863967c 100644 --- a/src/logservice/libobcdc/src/ob_log_utils.cpp +++ b/src/logservice/libobcdc/src/ob_log_utils.cpp @@ -189,57 +189,44 @@ int get_local_ip(ObString &local_ip) return ret; } -RecordType get_record_type(const ObDmlFlag &dml_flag) +RecordType get_record_type(const ObDmlRowFlag &dml_flag) { RecordType record_type = EUNKNOWN; // Set record type // Note: The REPLACE type is not handled, it does not exist in Redo - switch (dml_flag) { - case ObDmlFlag::DF_INSERT: - record_type = EINSERT; - break; - - case ObDmlFlag::DF_UPDATE: - record_type = EUPDATE; - break; - - case ObDmlFlag::DF_DELETE: - record_type = EDELETE; - break; - - default: - record_type = EUNKNOWN; - break; + // Note: must judge is_delete_insert first because PUT is also is_insert, but it's flag_type is DF_TYPE_INSERT_DELETE + if (OB_UNLIKELY(dml_flag.is_delete_insert())) { + record_type = EPUT; + } else if (dml_flag.is_insert()) { + record_type = EINSERT; + } else if (dml_flag.is_update()) { + record_type = EUPDATE; + } else if (dml_flag.is_delete()) { + record_type = EDELETE; + } else { + record_type = EUNKNOWN; } return record_type; } -const char *print_dml_flag(const blocksstable::ObDmlFlag &dml_flag) +const char *print_dml_flag(const blocksstable::ObDmlRowFlag &dml_flag) { const char *str = "UNKNOWN"; - switch (dml_flag) { - case ObDmlFlag::DF_INSERT: - str = "insert"; - break; - - case ObDmlFlag::DF_UPDATE: - str = "update"; - break; - - case ObDmlFlag::DF_DELETE: - str = "delete"; - break; - - case ObDmlFlag::DF_LOCK: - str = "lock"; - break; - - default: - str = "UNKNOWN"; - break; + if (dml_flag.is_delete_insert()) { + str = "put"; + } else if (dml_flag.is_insert()) { + str = "insert"; + } else if (dml_flag.is_update()) { + str = "update"; + } else if (dml_flag.is_delete()) { + str = "delete"; + } else if (dml_flag.is_lock()) { + str = "lock"; + } else { + str = "UNKNOWN"; } return str; @@ -312,6 +299,10 @@ const char *print_record_type(int type) str = "EDML"; break; + case EPUT: + str = "EPUT"; + break; + default: str = "UNKNOWN"; break; diff --git a/src/logservice/libobcdc/src/ob_log_utils.h b/src/logservice/libobcdc/src/ob_log_utils.h index 6c9b01e35..9c61b253f 100644 --- a/src/logservice/libobcdc/src/ob_log_utils.h +++ b/src/logservice/libobcdc/src/ob_log_utils.h @@ -236,8 +236,8 @@ private: int get_local_ip(common::ObString &local_ip); -RecordType get_record_type(const blocksstable::ObDmlFlag &dml_flag); -const char *print_dml_flag(const blocksstable::ObDmlFlag &dml_flag); +RecordType get_record_type(const blocksstable::ObDmlRowFlag &dml_flag); +const char *print_dml_flag(const blocksstable::ObDmlRowFlag &dml_flag); const char *print_record_type(int type); const char *print_src_category(int src_category); const char *print_record_src_type(int type); diff --git a/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp b/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp index 33d3e0569..99369a10f 100644 --- a/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp +++ b/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp @@ -386,7 +386,7 @@ int ObBinlogRecordPrinter::output_data_file(IBinlogRecord *br, ROW_PRINTF(ptr, size, pos, ri, "unique_id:[%.*s](%d)", unique_id.length(), unique_id.ptr(), unique_id.length()); } } - } else if ((EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type) && ! only_print_dml_tx_checksum) { + } else if ((EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type || EPUT == record_type) && ! only_print_dml_tx_checksum) { ri++; ITableMeta *table_meta = br->getTableMeta(); int64_t column_count = table_meta ? table_meta->getColCount() : -1; @@ -915,7 +915,7 @@ void ObBinlogRecordPrinter::do_br_statistic_(IBinlogRecord &br) } else if (EDDL == record_type) { total_tx_count_++; total_br_count_++; - } else if (EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type) { + } else if (EINSERT == record_type || EUPDATE == record_type || EDELETE == record_type || EPUT == record_type) { dml_tx_br_count_++; total_br_count_++; binlogBuf *new_cols = br.newCols((unsigned int &)new_cols_count); diff --git a/src/observer/ob_rpc_processor_simple.cpp b/src/observer/ob_rpc_processor_simple.cpp index 3c5d7e6ab..906066d54 100644 --- a/src/observer/ob_rpc_processor_simple.cpp +++ b/src/observer/ob_rpc_processor_simple.cpp @@ -26,6 +26,7 @@ #include "share/cache/ob_cache_name_define.h" #include "share/ob_share_util.h" #include "storage/ddl/ob_ddl_redo_log_writer.h" +#include "storage/ddl/ob_ddl_inc_redo_log_writer.h" #include "storage/memtable/ob_memtable.h" #include "storage/blocksstable/ob_block_manager.h" #include "rootserver/ob_root_service.h" @@ -2305,7 +2306,7 @@ int ObRpcRemoteWriteDDLRedoLogP::process() LOG_WARN("fail to wait macro block io finish", K(ret)); } else if (OB_FAIL(sstable_redo_writer.init(arg_.ls_id_, arg_.redo_info_.table_key_.tablet_id_))) { LOG_WARN("init sstable redo writer", K(ret), K_(arg)); - } else if (OB_FAIL(sstable_redo_writer.write_macro_block_log(arg_.redo_info_, macro_handle.get_macro_id(), false, arg_.task_id_))) { + } else if (OB_FAIL(sstable_redo_writer.write_macro_block_log(arg_.redo_info_, macro_handle.get_macro_id(), false/*allow_remote_write*/, arg_.task_id_))) { LOG_WARN("fail to write macro redo", K(ret), K_(arg)); } else if (OB_FAIL(sstable_redo_writer.wait_macro_block_log_finish(arg_.redo_info_, macro_handle.get_macro_id()))) { @@ -2402,6 +2403,45 @@ int ObRpcRemoteWriteDDLCommitLogP::process() return ret; } +int ObRpcRemoteWriteDDLIncCommitLogP::process() +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!arg_.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K_(arg)); + } else { + MTL_SWITCH(arg_.tenant_id_) { + ObRole role = INVALID_ROLE; + ObDDLIncRedoLogWriter sstable_redo_writer; + ObLSService *ls_service = MTL(ObLSService*); + ObTransService *trans_service = MTL(ObTransService *); + ObLSHandle ls_handle; + ObLS *ls = nullptr; + if (OB_FAIL(ls_service->get_ls(arg_.ls_id_, ls_handle, ObLSGetMod::OBSERVER_MOD))) { + LOG_WARN("get ls failed", K(ret), K(arg_)); + } else if (OB_ISNULL(ls = ls_handle.get_ls())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error", K(ret), K(MTL_ID()), K(arg_.ls_id_)); + } else if (OB_FAIL(ls->get_ls_role(role))) { + LOG_WARN("get role failed", K(ret), K(MTL_ID()), K(arg_.ls_id_)); + } else if (ObRole::LEADER != role) { + ret = OB_NOT_MASTER; + LOG_INFO("leader may not have finished replaying clog, caller retry", K(ret), K(MTL_ID()), K(arg_.ls_id_)); + } else if (OB_FAIL(sstable_redo_writer.init(arg_.ls_id_, arg_.tablet_id_))) { + LOG_WARN("init sstable redo writer", K(ret), K(arg_.tablet_id_)); + } else if (OB_FAIL(sstable_redo_writer.write_inc_commit_log_with_retry(false/*allow_remote_write*/, + arg_.lob_meta_tablet_id_, + arg_.tx_desc_))) { + LOG_WARN("fail to write inc commit log", K(ret), K(arg_)); + } else if (OB_FAIL(trans_service->get_tx_exec_result(*arg_.tx_desc_, result_.tx_result_))) { + LOG_WARN("fail to get_tx_exec_result", K(ret), K(arg_)); + } + } + } + + return ret; +} + int ObCleanSequenceCacheP::process() { int ret = OB_SUCCESS; diff --git a/src/observer/ob_rpc_processor_simple.h b/src/observer/ob_rpc_processor_simple.h index f724b0f44..78f24b32b 100644 --- a/src/observer/ob_rpc_processor_simple.h +++ b/src/observer/ob_rpc_processor_simple.h @@ -228,6 +228,7 @@ OB_DEFINE_PROCESSOR_S(Srv, OB_DELETE_ARB, ObRpcDeleteArbP); OB_DEFINE_PROCESSOR_S(Srv, OB_BATCH_BROADCAST_SCHEMA, ObBatchBroadcastSchemaP); OB_DEFINE_PROCESSOR_S(Srv, OB_REMOTE_WRITE_DDL_REDO_LOG, ObRpcRemoteWriteDDLRedoLogP); OB_DEFINE_PROCESSOR_S(Srv, OB_REMOTE_WRITE_DDL_COMMIT_LOG, ObRpcRemoteWriteDDLCommitLogP); +OB_DEFINE_PROCESSOR_S(Srv, OB_REMOTE_WRITE_DDL_INC_COMMIT_LOG, ObRpcRemoteWriteDDLIncCommitLogP); OB_DEFINE_PROCESSOR_S(Srv, OB_CHECK_LS_CAN_OFFLINE, ObRpcCheckLSCanOfflineP); OB_DEFINE_PROCESSOR_S(Srv, OB_CLEAN_SEQUENCE_CACHE, ObCleanSequenceCacheP); OB_DEFINE_PROCESSOR_S(Srv, OB_REGISTER_TX_DATA, ObRegisterTxDataP); diff --git a/src/observer/ob_server.cpp b/src/observer/ob_server.cpp index 9f05af91a..b3e630923 100644 --- a/src/observer/ob_server.cpp +++ b/src/observer/ob_server.cpp @@ -177,7 +177,6 @@ ObServer::ObServer() lst_operator_(), tablet_operator_(), server_tracer_(), location_service_(), - partition_cfy_(), bandwidth_throttle_(), sys_bkgd_net_percentage_(0), ethernet_speed_(0), diff --git a/src/observer/ob_server.h b/src/observer/ob_server.h index d1da8edbe..c50355d26 100644 --- a/src/observer/ob_server.h +++ b/src/observer/ob_server.h @@ -38,7 +38,6 @@ #include "storage/tx/wrs/ob_weak_read_service.h" // ObWeakReadService #include "storage/tx/wrs/ob_black_list.h" -#include "storage/ob_partition_component_factory.h" #include "rootserver/ob_root_service.h" @@ -64,7 +63,6 @@ #include "observer/ob_startup_accel_task_handler.h" #include "share/ls/ob_ls_table_operator.h" // for ObLSTableOperator #include "storage/ob_locality_manager.h" -#include "storage/ob_partition_component_factory.h" #include "storage/ddl/ob_ddl_heart_beat_task.h" #include "storage/ob_disk_usage_reporter.h" @@ -409,7 +407,6 @@ private: share::ObLocationService location_service_; // storage related - storage::ObPartitionComponentFactory partition_cfy_; common::ObInOutBandwidthThrottle bandwidth_throttle_; int64_t sys_bkgd_net_percentage_; int64_t ethernet_speed_; diff --git a/src/observer/ob_service.cpp b/src/observer/ob_service.cpp index 9520b97ba..df20c27cf 100644 --- a/src/observer/ob_service.cpp +++ b/src/observer/ob_service.cpp @@ -40,7 +40,6 @@ #include "share/ob_tablet_replica_checksum_operator.h" // ObTabletReplicaChecksumItem #include "share/rc/ob_tenant_base.h" -#include "storage/ob_partition_component_factory.h" #include "storage/ob_i_table.h" #include "storage/tx/ob_trans_service.h" #include "sql/optimizer/ob_storage_estimator.h" diff --git a/src/observer/ob_srv_xlator_storage.cpp b/src/observer/ob_srv_xlator_storage.cpp index 64d871d8f..aaa6fe04f 100644 --- a/src/observer/ob_srv_xlator_storage.cpp +++ b/src/observer/ob_srv_xlator_storage.cpp @@ -104,6 +104,7 @@ void oceanbase::observer::init_srv_xlator_for_storage(ObSrvRpcXlator *xlator) { RPC_PROCESSOR(ObRpcClearTabletAutoincSeqCacheP, gctx_); RPC_PROCESSOR(ObRpcRemoteWriteDDLRedoLogP, gctx_); RPC_PROCESSOR(ObRpcRemoteWriteDDLCommitLogP, gctx_); + RPC_PROCESSOR(ObRpcRemoteWriteDDLIncCommitLogP, gctx_); RPC_PROCESSOR(ObRpcLSMigrateReplicaP, gctx_); RPC_PROCESSOR(ObRpcLSAddReplicaP, gctx_); RPC_PROCESSOR(ObRpcLSTypeTransformP, gctx_); diff --git a/src/observer/table_load/control/ob_table_load_control_rpc_executor.cpp b/src/observer/table_load/control/ob_table_load_control_rpc_executor.cpp index 48f085bfb..eb590d58f 100644 --- a/src/observer/table_load/control/ob_table_load_control_rpc_executor.cpp +++ b/src/observer/table_load/control/ob_table_load_control_rpc_executor.cpp @@ -271,7 +271,9 @@ int ObDirectLoadControlCommitExecutor::process() ObTableLoadStore store(table_ctx); if (OB_FAIL(store.init())) { LOG_WARN("fail to init store", KR(ret)); - } else if (OB_FAIL(store.commit(res_.result_info_))) { + } else if (OB_FAIL(store.commit(res_.result_info_, + res_.sql_statistics_, + res_.trans_result_))) { LOG_WARN("fail to store commit", KR(ret)); } else if (OB_FAIL(ObTableLoadService::remove_ctx(table_ctx))) { LOG_WARN("fail to remove table ctx", KR(ret), K(key)); diff --git a/src/observer/table_load/control/ob_table_load_control_rpc_struct.cpp b/src/observer/table_load/control/ob_table_load_control_rpc_struct.cpp index 434980679..f91a7871f 100644 --- a/src/observer/table_load/control/ob_table_load_control_rpc_struct.cpp +++ b/src/observer/table_load/control/ob_table_load_control_rpc_struct.cpp @@ -20,6 +20,7 @@ namespace oceanbase namespace observer { using namespace sql; +using namespace storage; using namespace table; OB_SERIALIZE_MEMBER(ObDirectLoadControlRequest, diff --git a/src/observer/table_load/control/ob_table_load_control_rpc_struct.h b/src/observer/table_load/control/ob_table_load_control_rpc_struct.h index 21621b9f9..e41ad5064 100644 --- a/src/observer/table_load/control/ob_table_load_control_rpc_struct.h +++ b/src/observer/table_load/control/ob_table_load_control_rpc_struct.h @@ -20,7 +20,6 @@ #include "share/table/ob_table_load_define.h" #include "share/table/ob_table_load_sql_statistics.h" #include "sql/session/ob_sql_session_mgr.h" -#include "observer/table_load/ob_table_load_struct.h" #include "storage/direct_load/ob_direct_load_struct.h" #include "storage/tx/ob_trans_define_v4.h" diff --git a/src/observer/table_load/ob_table_load_client_task.cpp b/src/observer/table_load/ob_table_load_client_task.cpp index da88f46fe..ef6b2cbbd 100644 --- a/src/observer/table_load/ob_table_load_client_task.cpp +++ b/src/observer/table_load/ob_table_load_client_task.cpp @@ -29,6 +29,7 @@ namespace observer { using namespace common; using namespace sql; +using namespace storage; using namespace table; /** @@ -583,7 +584,6 @@ int ObTableLoadClientTask::init_instance() load_param.session_count_ = load_param.parallel_; load_param.batch_size_ = 100; load_param.max_error_row_count_ = param_.get_max_error_row_count(); - // load_param.sql_mode_ = 0; // TODO(suzhi.yt) 自增列会用到这个参数 load_param.column_count_ = column_idxs.count(); load_param.need_sort_ = true; load_param.px_mode_ = false; @@ -613,8 +613,10 @@ int ObTableLoadClientTask::commit_instance() ret = OB_NOT_INIT; LOG_WARN("ObTableLoadClientTask not init", KR(ret)); } else { - if (OB_FAIL(instance_.commit(result_info_))) { + if (OB_FAIL(instance_.commit())) { LOG_WARN("fail to commit instance", KR(ret)); + } else { + result_info_ = instance_.get_result_info(); } } return ret; diff --git a/src/observer/table_load/ob_table_load_coordinator.cpp b/src/observer/table_load/ob_table_load_coordinator.cpp index 75ac63ce8..36a03b854 100644 --- a/src/observer/table_load/ob_table_load_coordinator.cpp +++ b/src/observer/table_load/ob_table_load_coordinator.cpp @@ -28,6 +28,8 @@ #include "observer/table_load/ob_table_load_utils.h" #include "share/ob_share_util.h" #include "share/stat/ob_incremental_stat_estimator.h" +#include "share/stat/ob_dbms_stats_utils.h" +#include "observer/table_load/ob_table_load_index_long_wait.h" #include "observer/omt/ob_tenant.h" namespace oceanbase @@ -38,6 +40,8 @@ using namespace common; using namespace table; using namespace share; using namespace sql; +using namespace storage; +using namespace transaction; using namespace lib; using namespace omt; @@ -111,10 +115,6 @@ void ObTableLoadCoordinator::abort_ctx(ObTableLoadTableCtx *ctx) if (OB_FAIL(abort_peers_ctx(ctx))) { LOG_WARN("fail to abort peers ctx", KR(ret)); } - // 5. abort redef table, release table lock - if (OB_FAIL(abort_redef_table(ctx))) { - LOG_WARN("fail to abort redef table", KR(ret)); - } } } @@ -173,6 +173,7 @@ int ObTableLoadCoordinator::abort_peers_ctx(ObTableLoadTableCtx *ctx) LOG_WARN("fail to push back", KR(ret), K(addr)); } } + ObTableLoadIndexLongWait wait_obj(10 * 1000, WAIT_INTERVAL_US); while (!curr_round->empty() && tries < max_retry_times) { ret = OB_SUCCESS; ++round; @@ -218,24 +219,12 @@ int ObTableLoadCoordinator::abort_peers_ctx(ObTableLoadTableCtx *ctx) } std::swap(curr_round, next_round); next_round->reuse(); + wait_obj.wait(); } } return ret; } -int ObTableLoadCoordinator::abort_redef_table(ObTableLoadTableCtx *ctx) -{ - int ret = OB_SUCCESS; - ObTableLoadRedefTableAbortArg arg; - arg.tenant_id_ = ctx->param_.tenant_id_; - arg.task_id_ = ctx->ddl_param_.task_id_; - if (OB_FAIL( - ObTableLoadRedefTable::abort(arg, *ctx->coordinator_ctx_->exec_ctx_->get_session_info()))) { - LOG_WARN("fail to abort redef table", KR(ret), K(arg)); - } - return ret; -} - int ObTableLoadCoordinator::init() { int ret = OB_SUCCESS; @@ -780,6 +769,7 @@ public: if (OB_FAIL(coordinator.init())) { LOG_WARN("fail to init coordinator", KR(ret)); } + ObTableLoadIndexLongWait wait_obj(10 * 1000, WAIT_INTERVAL_US); while (OB_SUCC(ret)) { // 确认状态 if (OB_FAIL(ctx_->coordinator_ctx_->check_status(ObTableLoadStatusType::MERGING))) { @@ -789,7 +779,7 @@ public: else if (OB_FAIL(coordinator.check_peers_merge_result(is_merge_finish))) { LOG_WARN("fail to check peers merge result", KR(ret)); } else if (!is_merge_finish) { - usleep(WAIT_INTERVAL_US); // 等待1s后重试 + wait_obj.wait(); } else { break; } @@ -866,11 +856,15 @@ int ObTableLoadCoordinator::add_check_merge_result_task() * commit */ -int ObTableLoadCoordinator::commit_peers() +int ObTableLoadCoordinator::commit_peers(ObTableLoadSqlStatistics &sql_statistics) { int ret = OB_SUCCESS; + ObTransService *txs = nullptr; ObTableLoadArray all_addr_array; - if (OB_FAIL(coordinator_ctx_->partition_location_.get_all_leader(all_addr_array))) { + if (OB_ISNULL(MTL(ObTransService *))) { + ret = OB_ERR_SYS; + LOG_WARN("trans service is null", KR(ret)); + } else if (OB_FAIL(coordinator_ctx_->partition_location_.get_all_leader(all_addr_array))) { LOG_WARN("fail to get all addr", KR(ret)); } else { LOG_INFO("route_commit_peer_request begin", K(all_addr_array.count())); @@ -884,7 +878,9 @@ int ObTableLoadCoordinator::commit_peers() ObTableLoadStore store(ctx_); if (OB_FAIL(store.init())) { LOG_WARN("fail to init store", KR(ret)); - } else if (OB_FAIL(store.commit(res.result_info_))) { + } else if (OB_FAIL(store.commit(res.result_info_, + res.sql_statistics_, + res.trans_result_))) { LOG_WARN("fail to commit store", KR(ret)); } } else { // 远端, 发送rpc @@ -895,30 +891,127 @@ int ObTableLoadCoordinator::commit_peers() ATOMIC_AAF(&coordinator_ctx_->result_info_.deleted_, res.result_info_.deleted_); ATOMIC_AAF(&coordinator_ctx_->result_info_.skipped_, res.result_info_.skipped_); ATOMIC_AAF(&coordinator_ctx_->result_info_.warnings_, res.result_info_.warnings_); + if (OB_FAIL(sql_statistics.merge(res.sql_statistics_))) { + LOG_WARN("fail to add result sql stats", KR(ret), K(addr), K(res)); + } else if (ObDirectLoadMethod::is_incremental(param_.method_) && + txs->add_tx_exec_result(*ctx_->session_info_->get_tx_desc(), res.trans_result_)) { + LOG_WARN("fail to add tx exec result", KR(ret)); + } } } } return ret; } -int ObTableLoadCoordinator::commit_redef_table() +int ObTableLoadCoordinator::write_sql_stat(ObTableLoadSqlStatistics &sql_statistics) { int ret = OB_SUCCESS; - ObTableLoadRedefTableFinishArg arg; - arg.tenant_id_ = param_.tenant_id_; - arg.table_id_ = param_.table_id_; - arg.dest_table_id_ = ctx_->ddl_param_.dest_table_id_; - arg.task_id_ = ctx_->ddl_param_.task_id_; - arg.schema_version_ = ctx_->ddl_param_.schema_version_; - if (OB_FAIL( - ObTableLoadRedefTable::finish(arg, *coordinator_ctx_->exec_ctx_->get_session_info()))) { - LOG_WARN("fail to finish redef table", KR(ret), K(arg)); + const uint64_t tenant_id = MTL_ID(); + const uint64_t table_id = ctx_->ddl_param_.dest_table_id_; + ObArenaAllocator allocator("TLD_Temp"); + ObArray global_column_stats; + ObArray global_table_stats; + allocator.set_tenant_id(MTL_ID()); + global_column_stats.set_tenant_id(MTL_ID()); + global_table_stats.set_tenant_id(MTL_ID()); + if (OB_UNLIKELY(sql_statistics.is_empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid args", KR(ret), K(sql_statistics)); + } else if (ObDirectLoadMethod::is_full(ctx_->param_.method_)) { + if (OB_FAIL(sql_statistics.get_table_stat_array(global_table_stats))) { + LOG_WARN("fail to get table stat array", KR(ret)); + } else if (OB_FAIL(sql_statistics.get_col_stat_array(global_column_stats))) { + LOG_WARN("fail to get column stat array", KR(ret)); + } + } else { + ObTableStatParam param; + ObMySQLTransaction trans; // for acquire inner conn + sqlclient::ObISQLConnection *conn = nullptr; + ObArray base_table_stats; + ObArray base_column_stats; + TabStatIndMap inc_table_stats; + ColStatIndMap inc_column_stats; + const int64_t map_size = ctx_->param_.column_count_; + base_table_stats.set_tenant_id(MTL_ID()); + base_column_stats.set_tenant_id(MTL_ID()); + param.tenant_id_ = tenant_id; + param.table_id_ = table_id; + param.part_level_ = ctx_->schema_.part_level_; + param.allocator_ = &allocator; + param.global_stat_param_.need_modify_ = true; + param.part_stat_param_.need_modify_ = false; + param.subpart_stat_param_.need_modify_ = false; + if (!ctx_->schema_.is_partitioned_table_) { + param.global_part_id_ = table_id; + param.global_tablet_id_ = table_id; + } + for (int64_t i = 0; OB_SUCC(ret) && i < ctx_->schema_.column_descs_.count(); ++i) { + const ObColDesc &col_desc = ctx_->schema_.column_descs_.at(i); + ObColumnStatParam col_param; + col_param.column_id_ = col_desc.col_id_; + col_param.cs_type_ = col_desc.col_type_.get_collation_type(); + if (0 == i && ctx_->schema_.is_heap_table_) { + // skip hidden pk + } else if (OB_FAIL(param.column_params_.push_back(col_param))) { + LOG_WARN("fail to push back column param", KR(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(trans.start(GCTX.sql_proxy_, tenant_id))) { + LOG_WARN("fail to start transaction", KR(ret)); + } else if (OB_ISNULL(conn = trans.get_connection())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected conn is null", KR(ret)); + } else if (OB_FAIL(inc_table_stats.create(map_size, + "TLD_TabStatBkt", + "TLD_TabStatNode", + tenant_id))) { + LOG_WARN("fail to create table stats map", KR(ret)); + } else if (OB_FAIL(inc_column_stats.create(map_size, + "TLD_ColStatBkt", + "TLD_ColStatNode", + tenant_id))) { + LOG_WARN("fail to create column stats map", KR(ret)); + } else if (OB_FAIL(ObDbmsStatsUtils::get_current_opt_stats(allocator, + conn, + param, + base_table_stats, + base_column_stats))) { + LOG_WARN("failed to get current opt stats", KR(ret)); + } else if (OB_FAIL(sql_statistics.get_table_stats(inc_table_stats))) { + LOG_WARN("fail to get table stat array", KR(ret)); + } else if (OB_FAIL(sql_statistics.get_col_stats(inc_column_stats))) { + LOG_WARN("fail to get column stat array", KR(ret)); + } else if (OB_FAIL(ObDbmsStatsUtils::merge_tab_stats(param, + inc_table_stats, + base_table_stats, + global_table_stats))) { + LOG_WARN("fail to merge tab stats", KR(ret), K(base_table_stats)); + } else if (OB_FAIL(ObDbmsStatsUtils::merge_col_stats(param, + inc_column_stats, + base_column_stats, + global_column_stats))) { + LOG_WARN("fail to merge col stats", KR(ret), K(base_column_stats)); + } + } + if (OB_SUCC(ret)) { + ObSchemaGetterGuard schema_guard; + if (OB_UNLIKELY(global_table_stats.empty() || global_column_stats.empty())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected empty sql stats", KR(ret), K(global_table_stats), K(global_column_stats)); + } else if (OB_FAIL(ObTableLoadSchema::get_schema_guard(tenant_id, schema_guard))) { + LOG_WARN("fail to get schema guard", KR(ret), K(tenant_id)); + } else if (OB_FAIL(ObDbmsStatsUtils::split_batch_write(&schema_guard, + ctx_->session_info_, + GCTX.sql_proxy_, + global_table_stats, + global_column_stats))) { + LOG_WARN("fail to split batch write", KR(ret), K(sql_statistics), K(global_table_stats), K(global_column_stats)); + } } return ret; } -// commit() = px_commit_data() + px_commit_ddl() -// used in non px_mode int ObTableLoadCoordinator::commit(ObTableLoadResultInfo &result_info) { int ret = OB_SUCCESS; @@ -931,15 +1024,11 @@ int ObTableLoadCoordinator::commit(ObTableLoadResultInfo &result_info) ObTableLoadSqlStatistics sql_statistics; if (OB_FAIL(coordinator_ctx_->check_status(ObTableLoadStatusType::MERGED))) { LOG_WARN("fail to check coordinator status", KR(ret)); - } else if (OB_FAIL(commit_peers())) { + } else if (OB_FAIL(commit_peers(sql_statistics))) { LOG_WARN("fail to commit peers", KR(ret)); } else if (FALSE_IT(coordinator_ctx_->set_enable_heart_beat(false))) { - } else if (param_.online_opt_stat_gather_ && - OB_FAIL( - drive_sql_stat(coordinator_ctx_->exec_ctx_->get_exec_ctx()))) { - LOG_WARN("fail to drive sql stat", KR(ret)); - } else if (OB_FAIL(commit_redef_table())) { - LOG_WARN("fail to commit redef table", KR(ret)); + } else if (param_.online_opt_stat_gather_ && OB_FAIL(write_sql_stat(sql_statistics))) { + LOG_WARN("fail to write sql stat", KR(ret)); } else if (OB_FAIL(coordinator_ctx_->set_status_commit())) { LOG_WARN("fail to set coordinator status commit", KR(ret)); } else { @@ -949,83 +1038,6 @@ int ObTableLoadCoordinator::commit(ObTableLoadResultInfo &result_info) return ret; } -// used in insert /*+ append */ into select clause -// commit data loaded -int ObTableLoadCoordinator::px_commit_data() -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObTableLoadCoordinator not init", KR(ret), KP(this)); - } else { - LOG_INFO("coordinator px_commit_data"); - ObMutexGuard guard(coordinator_ctx_->get_op_lock()); - ObTableLoadSqlStatistics sql_statistics; - if (OB_FAIL(coordinator_ctx_->check_status(ObTableLoadStatusType::MERGED))) { - LOG_WARN("fail to check coordinator status", KR(ret)); - } else if (OB_FAIL(commit_peers())) { - LOG_WARN("fail to commit peers", KR(ret)); - } else if (FALSE_IT(coordinator_ctx_->set_enable_heart_beat(false))) { - } else if (param_.online_opt_stat_gather_ && - OB_FAIL( - drive_sql_stat(coordinator_ctx_->exec_ctx_->get_exec_ctx()))) { - LOG_WARN("fail to drive sql stat", KR(ret)); - } - } - return ret; -} - -// commit ddl procedure -int ObTableLoadCoordinator::px_commit_ddl() -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObTableLoadCoordinator not init", KR(ret), KP(this)); - } else { - LOG_INFO("coordinator px_commit_ddl"); - ObMutexGuard guard(coordinator_ctx_->get_op_lock()); - if (OB_FAIL(coordinator_ctx_->check_status(ObTableLoadStatusType::MERGED))) { - LOG_WARN("fail to check coordinator status", KR(ret)); - } else if (OB_FAIL(commit_redef_table())) { - LOG_WARN("fail to commit redef table", KR(ret)); - } else if (OB_FAIL(coordinator_ctx_->set_status_commit())) { - LOG_WARN("fail to set coordinator status commit", KR(ret)); - } - } - return ret; -} - -int ObTableLoadCoordinator::drive_sql_stat(ObExecContext *ctx) -{ - int ret = OB_SUCCESS; - const uint64_t tenant_id = MTL_ID(); - const uint64_t table_id = ctx_->ddl_param_.dest_table_id_; - ObSchemaGetterGuard schema_guard; - ObSchemaGetterGuard *tmp_schema_guard = nullptr; - const ObTableSchema *table_schema = nullptr; - if (OB_UNLIKELY(nullptr == ctx)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), KPC(ctx)); - } else if (OB_FAIL(ObTableLoadSchema::get_table_schema(tenant_id, table_id, schema_guard, - table_schema))) { - LOG_WARN("fail to get table schema", KR(ret), K(tenant_id), K(table_id)); - } else { - tmp_schema_guard = ctx->get_virtual_table_ctx().schema_guard_; - ctx->get_sql_ctx()->schema_guard_ = &schema_guard; - ctx->get_das_ctx().set_sql_ctx(ctx->get_sql_ctx()); - } - if (OB_SUCC(ret)) { - if (OB_FAIL(ObIncrementalStatEstimator::derive_global_stat_by_direct_load( - *ctx, table_id))) { - LOG_WARN("fail to drive global stat by direct load", KR(ret)); - } - ctx->get_sql_ctx()->schema_guard_ = tmp_schema_guard; - ctx->get_das_ctx().set_sql_ctx(ctx->get_sql_ctx()); - } - return ret; -} - /** * get status */ @@ -1361,6 +1373,7 @@ public: if (OB_FAIL(coordinator.init())) { LOG_WARN("fail to init coordinator", KR(ret)); } + ObTableLoadIndexLongWait wait_obj(10 * 1000, WAIT_INTERVAL_US); while (OB_SUCC(ret)) { // 确认trans状态为frozen if (OB_FAIL(trans_->check_trans_status(ObTableLoadTransStatusType::FROZEN))) { @@ -1370,7 +1383,7 @@ public: else if (OB_FAIL(coordinator.check_peers_trans_commit(trans_, is_peers_commit))) { LOG_WARN("fail to check peers trans commit", KR(ret)); } else if (!is_peers_commit) { - usleep(WAIT_INTERVAL_US); // 等待1s后重试 + wait_obj.wait(); } else { break; } diff --git a/src/observer/table_load/ob_table_load_coordinator.h b/src/observer/table_load/ob_table_load_coordinator.h index 8a272a5d6..69bc90f12 100644 --- a/src/observer/table_load/ob_table_load_coordinator.h +++ b/src/observer/table_load/ob_table_load_coordinator.h @@ -34,7 +34,7 @@ class ObTableLoadCoordinatorTrans; class ObTableLoadCoordinator { - static const int64_t WAIT_INTERVAL_US = 1LL * 1000 * 1000; // 1s + static const int64_t WAIT_INTERVAL_US = 3 * 1000 * 1000; // 3s static const int64_t DEFAULT_TIMEOUT_US = 10LL * 1000 * 1000; // 10s static const int64_t HEART_BEAT_RPC_TIMEOUT_US = 1LL * 1000 * 1000; // 1s // 申请和释放资源失败等待间隔时间 @@ -52,15 +52,12 @@ public: private: static int abort_active_trans(ObTableLoadTableCtx *ctx); static int abort_peers_ctx(ObTableLoadTableCtx *ctx); - static int abort_redef_table(ObTableLoadTableCtx *ctx); // table load ctrl interface public: int begin(); int finish(); int commit(table::ObTableLoadResultInfo &result_info); - int px_commit_data(); - int px_commit_ddl(); int get_status(table::ObTableLoadStatusType &status, int &error_code); int heart_beat(); private: @@ -69,9 +66,8 @@ private: int confirm_begin_peers(); int pre_merge_peers(); int start_merge_peers(); - int commit_peers(); - int commit_redef_table(); - int drive_sql_stat(sql::ObExecContext *ctx); + int commit_peers(table::ObTableLoadSqlStatistics &sql_statistics); + int write_sql_stat(table::ObTableLoadSqlStatistics &sql_statistics); int heart_beat_peer(); private: int add_check_merge_result_task(); diff --git a/src/observer/table_load/ob_table_load_index_long_wait.h b/src/observer/table_load/ob_table_load_index_long_wait.h new file mode 100644 index 000000000..7c4909702 --- /dev/null +++ b/src/observer/table_load/ob_table_load_index_long_wait.h @@ -0,0 +1,52 @@ +/** + * 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 OB_TABLE_LOAD_INDEX_LONG_WAIT_H_ +#define OB_TABLE_LOAD_INDEX_LONG_WAIT_H_ + +#include "lib/utility/utility.h" + +namespace oceanbase +{ +namespace observer +{ + +class ObTableLoadIndexLongWait +{ +public: + ObTableLoadIndexLongWait(int64_t wait_us, int64_t max_wait_us) + : wait_us_(wait_us), max_wait_us_(max_wait_us) {} + virtual ~ObTableLoadIndexLongWait() {} + + void wait() + { + if (wait_us_ < max_wait_us_) { + ob_usleep(wait_us_); + wait_us_ = 2 * wait_us_; + } else { + ob_usleep(max_wait_us_); + } + } + +private: + DISALLOW_COPY_AND_ASSIGN(ObTableLoadIndexLongWait); + +private: + // data members + int64_t wait_us_; + int64_t max_wait_us_; +}; + +} +} + +#endif /* OB_TABLE_LOAD_INDEX_LONG_WAIT_H_ */ diff --git a/src/observer/table_load/ob_table_load_instance.cpp b/src/observer/table_load/ob_table_load_instance.cpp index e8de04a11..58b1a860d 100644 --- a/src/observer/table_load/ob_table_load_instance.cpp +++ b/src/observer/table_load/ob_table_load_instance.cpp @@ -15,11 +15,16 @@ #include "observer/table_load/ob_table_load_instance.h" #include "observer/table_load/ob_table_load_coordinator.h" #include "observer/table_load/ob_table_load_exec_ctx.h" +#include "observer/table_load/ob_table_load_index_long_wait.h" #include "observer/table_load/ob_table_load_redef_table.h" #include "observer/table_load/ob_table_load_service.h" #include "observer/table_load/ob_table_load_table_ctx.h" +#include "share/ls/ob_ls_operator.h" #include "share/table/ob_table_load_define.h" #include "sql/engine/ob_exec_context.h" +#include "storage/ob_common_id_utils.h" +#include "storage/tablelock/ob_table_lock_common.h" +#include "storage/tablelock/ob_table_lock_service.h" namespace oceanbase { @@ -28,13 +33,14 @@ namespace observer using namespace sql; using namespace storage; using namespace table; +using namespace transaction; +using namespace transaction::tablelock; ObTableLoadInstance::ObTableLoadInstance() : execute_ctx_(nullptr), allocator_(nullptr), table_ctx_(nullptr), job_stat_(nullptr), - is_committed_(false), is_inited_(false) { } @@ -46,16 +52,14 @@ void ObTableLoadInstance::destroy() int ret = OB_SUCCESS; trans_ctx_.reset(); if (nullptr != table_ctx_) { - if (!is_committed_) { - // must abort here, abort redef table need exec_ctx session_info - ObTableLoadCoordinator::abort_ctx(table_ctx_); + if (OB_FAIL(end_direct_load(false /*commit*/))) { + LOG_WARN("fail to end direct load", KR(ret)); } - if (OB_FAIL(ObTableLoadService::remove_ctx(table_ctx_))) { - LOG_WARN("table ctx may remove by service", KR(ret), KP(table_ctx_)); + } + if (stmt_ctx_.is_started()) { + if (OB_FAIL(end_stmt(false /*commit*/))) { + LOG_WARN("fail to end stmt", KR(ret)); } - ObTableLoadService::put_ctx(table_ctx_); - table_ctx_ = nullptr; - job_stat_ = nullptr; } } @@ -86,13 +90,13 @@ int ObTableLoadInstance::init(ObTableLoadParam ¶m, const ObIArray & param.insert_mode_))) { LOG_WARN("fail to check support direct load", KR(ret), K(param)); } - // create table ctx - else if (OB_FAIL(create_table_ctx(param, idx_array))) { - LOG_WARN("fail to create table ctx", KR(ret)); + // start stmt + else if (OB_FAIL(start_stmt(param))) { + LOG_WARN("fail to start stmt", KR(ret), K(param)); } - // begin - else if (OB_FAIL(begin())) { - LOG_WARN("fail to begin", KR(ret)); + // start direct load + else if (OB_FAIL(start_direct_load(param, idx_array))) { + LOG_WARN("fail to start direct load", KR(ret)); } // start trans else if (!param.px_mode_ && OB_FAIL(start_trans())) { @@ -108,21 +112,382 @@ int ObTableLoadInstance::init(ObTableLoadParam ¶m, const ObIArray & return ret; } -int ObTableLoadInstance::create_table_ctx(ObTableLoadParam ¶m, - const ObIArray &idx_array) +int ObTableLoadInstance::write(int32_t session_id, const table::ObTableLoadObjRowArray &obj_rows) { int ret = OB_SUCCESS; - ObTableLoadTableCtx *table_ctx = nullptr; - ObSQLSessionInfo *session_info = execute_ctx_->get_session_info(); - ObTableLoadDDLParam ddl_param; - // start redef table + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); + } else { + if (OB_FAIL(write_trans(session_id, obj_rows))) { + LOG_WARN("fail to write trans", KR(ret)); + } + } + return ret; +} + +// commit() = px_commit_data() + px_commit_ddl() +// used in non px_mode +int ObTableLoadInstance::commit() +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); + } else { + if (OB_FAIL(commit_trans())) { + LOG_WARN("fail to commit trans", KR(ret)); + } + // end direct load + else if (OB_FAIL(end_direct_load(true /*commit*/))) { + LOG_WARN("fail to end direct load", KR(ret)); + } + // end stmt + else if (OB_FAIL(end_stmt(true /*commit*/))) { + LOG_WARN("fail to end stmt", KR(ret)); + } + } + return ret; +} + +// used in insert /*+ append */ into select clause +int ObTableLoadInstance::px_commit_data() +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); + } else { + if (OB_FAIL(end_direct_load(true /*commit*/))) { + LOG_WARN("fail to end direct load", KR(ret)); + } + } + return ret; +} + +int ObTableLoadInstance::px_commit_ddl() +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); + } else { + if (OB_FAIL(end_stmt(true /*commit*/))) { + LOG_WARN("fail to end stmt", KR(ret)); + } + } + return ret; +} + +int ObTableLoadInstance::start_stmt(const ObTableLoadParam ¶m) +{ + int ret = OB_SUCCESS; + stmt_ctx_.reset(); + stmt_ctx_.tenant_id_ = param.tenant_id_; + stmt_ctx_.table_id_ = param.table_id_; + stmt_ctx_.session_info_ = execute_ctx_->get_session_info(); + stmt_ctx_.is_incremental_ = ObDirectLoadMethod::is_incremental(param.method_); + stmt_ctx_.use_insert_into_select_tx_ = param.px_mode_; + if (stmt_ctx_.is_incremental_) { // incremental direct-load + bool end_sql_tx_if_fail = false; + bool rollback_savepoint_if_fail = false; + if (OB_FAIL(build_tx_param())) { + LOG_WARN("fail to build tx param", KR(ret), K(stmt_ctx_)); + } else if (OB_FAIL(start_sql_tx())) { + LOG_WARN("fail to start sql tx", KR(ret), K(stmt_ctx_)); + } else if (FALSE_IT(end_sql_tx_if_fail = true)) { + } else if (OB_FAIL(create_implicit_savepoint())) { + LOG_WARN("fail to create implicit savepoint", KR(ret), K(stmt_ctx_)); + } else if (OB_FAIL(lock_table_in_tx())) { + LOG_WARN("fail to lock table in tx", KR(ret), K(stmt_ctx_)); + } else if (FALSE_IT(rollback_savepoint_if_fail = true)) { + } else if (OB_FAIL(init_ddl_param_for_inc_direct_load())) { + LOG_WARN("fail to init ddl param for inc direct load", KR(ret), K(stmt_ctx_)); + } + if (OB_FAIL(ret)) { + int tmp_ret = OB_SUCCESS; + if (rollback_savepoint_if_fail && OB_TMP_FAIL(rollback_to_implicit_savepoint())) { + LOG_WARN("fail to rollback to implicit savepoint", KR(tmp_ret)); + } + if (end_sql_tx_if_fail && OB_TMP_FAIL(end_sql_tx(false /*commit*/))) { + LOG_WARN("fail to end sql tx", KR(tmp_ret)); + } + } + } else { + if (OB_FAIL(start_redef_table(param))) { + LOG_WARN("fail to start redef table", KR(ret), K(param)); + } + } + if (OB_SUCC(ret)) { + stmt_ctx_.is_started_ = true; + LOG_INFO("start stmt succeed", KR(ret), K(stmt_ctx_)); + } + return ret; +} + +int ObTableLoadInstance::end_stmt(const bool commit) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + if (stmt_ctx_.is_incremental_) { + // rollback in fail only, ignore ret + if (!commit && OB_TMP_FAIL(rollback_to_implicit_savepoint())) { + LOG_WARN("fail to rollback to implicit savepoint", KR(tmp_ret)); + } + if (OB_FAIL(end_sql_tx(commit))) { + LOG_WARN("fail to end sql tx", KR(ret)); + } + } else { + if (commit && OB_FAIL(commit_redef_table())) { + LOG_WARN("fail to commit redef table", KR(ret)); + } + if (OB_FAIL(ret) || !commit) { + if (OB_TMP_FAIL(abort_redef_table())) { + LOG_WARN("fail to abort redef table", KR(tmp_ret)); + ret = COVER_SUCC(tmp_ret); + } + } + } + stmt_ctx_.is_started_ = false; + LOG_INFO("end stmt succeed", KR(ret)); + return ret; +} + +int64_t ObTableLoadInstance::get_stmt_expire_ts(ObSQLSessionInfo *session_info) +{ + int ret = OB_SUCCESS; + const int64_t default_query_timeout = 1000 * 1000; // default timeout 1s + if (OB_ISNULL(session_info)) { + return ObTimeUtil::current_time() + default_query_timeout; + } else { + int64_t query_timeout = 0; + if (OB_FAIL(session_info->get_query_timeout(query_timeout))) { + LOG_WARN("fail to get query timeout", KR(ret)); + query_timeout = default_query_timeout; + } + return session_info->get_query_start_time() + query_timeout; + } +} + +int ObTableLoadInstance::build_tx_param() +{ + int ret = OB_SUCCESS; + ObSQLSessionInfo *session_info = stmt_ctx_.session_info_; + ObTxParam &tx_param = stmt_ctx_.tx_param_; + int64_t timeout_us = 0; + if (OB_FAIL(session_info->get_tx_timeout(timeout_us))) { + LOG_WARN("failed to get tx timeout", KR(ret)); + } else { + tx_param.timeout_us_ = timeout_us; + tx_param.lock_timeout_us_ = session_info->get_trx_lock_timeout(); + tx_param.access_mode_ = ObTxAccessMode::RW; + tx_param.isolation_ = session_info->get_tx_isolation(); + tx_param.cluster_id_ = GCONF.cluster_id; + } + return ret; +} + +int ObTableLoadInstance::start_sql_tx() +{ + int ret = OB_SUCCESS; + ObTransService *txs = MTL(ObTransService *); + ObSQLSessionInfo *session_info = stmt_ctx_.session_info_; + ObTxDesc *&tx_desc = session_info->get_tx_desc(); + if (stmt_ctx_.use_insert_into_select_tx_) { // insert into select path, tx_desc should be available + if (OB_ISNULL(tx_desc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tx_desc of insert into select should not be null", KR(ret), KP(tx_desc)); + } else if (OB_UNLIKELY(!tx_desc->is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tx_desc of insert into select should be valid", KR(ret), KPC(tx_desc)); + } else { + stmt_ctx_.tx_desc_ = tx_desc; + LOG_INFO("use insert into select tx", KPC(tx_desc)); + } + } else { // other path, tx_desc could be null, tx_param needs to be set manually + if (OB_UNLIKELY(nullptr != tx_desc && tx_desc->is_in_tx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("trans already exist", KR(ret), KPC(tx_desc)); + } else if (OB_ISNULL(tx_desc) && OB_FAIL(txs->acquire_tx(tx_desc, + session_info->get_sessid(), + session_info->get_data_version()))) { + LOG_WARN("failed to acquire tx", KR(ret), K(session_info->get_sessid()), + K(session_info->get_data_version())); + } else if (OB_FAIL(txs->start_tx(*tx_desc, stmt_ctx_.tx_param_))) { + LOG_WARN("failed to start tx", KR(ret), K(stmt_ctx_)); + int tmp_ret = OB_SUCCESS; + if (OB_TMP_FAIL(txs->release_tx(*tx_desc))) { + LOG_WARN("failed to release tx", KR(tmp_ret), KPC(tx_desc)); + } else { + tx_desc = nullptr; + } + } else { + stmt_ctx_.tx_desc_ = tx_desc; + LOG_INFO("start tx succeed", KPC(tx_desc)); + } + } + return ret; +} + +int ObTableLoadInstance::end_sql_tx(const bool commit) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + ObTransService *txs = MTL(ObTransService *); + ObSQLSessionInfo *session_info = stmt_ctx_.session_info_; + ObTxDesc *tx_desc = stmt_ctx_.tx_desc_; + if (stmt_ctx_.use_insert_into_select_tx_) { + // do nothing + } else { + if (nullptr == tx_desc) { + // do nothing + } else { + if (commit) { + const int64_t stmt_timeout_ts = get_stmt_expire_ts(session_info); + if (OB_FAIL(txs->commit_tx(*tx_desc, stmt_timeout_ts))) { + LOG_WARN("failed to commit tx", KR(ret), KPC(tx_desc)); + } else { + LOG_INFO("commit tx succeed", KPC(tx_desc)); + } + } else { + if (OB_FAIL(txs->rollback_tx(*tx_desc))) { + LOG_WARN("failed to rollback tx", KR(ret), KPC(tx_desc)); + } else { + LOG_INFO("rollback tx succeed", KPC(tx_desc)); + } + } + if (OB_TMP_FAIL(txs->release_tx(*tx_desc))) { + LOG_ERROR("failed to release tx", KR(tmp_ret), KPC(tx_desc)); + } + // reset session tx_desc + session_info->get_tx_desc() = nullptr; + } + } + stmt_ctx_.tx_desc_ = nullptr; + return ret; +} + +int ObTableLoadInstance::create_implicit_savepoint() +{ + int ret = OB_SUCCESS; + ObTransService *txs = MTL(ObTransService *); + ObTxDesc *tx_desc = stmt_ctx_.tx_desc_; + if (stmt_ctx_.use_insert_into_select_tx_) { + // do nothing + } else { + ObTxSEQ savepoint; + if (OB_FAIL(txs->create_implicit_savepoint(*tx_desc, stmt_ctx_.tx_param_, savepoint))) { + LOG_WARN("fail to create implicit savepoint", KR(ret)); + } else { + stmt_ctx_.savepoint_ = savepoint; + LOG_INFO("create implicit savepoint succeed", KPC(tx_desc), K(savepoint)); + } + } + return ret; +} + +int ObTableLoadInstance::rollback_to_implicit_savepoint() +{ + int ret = OB_SUCCESS; + ObTransService *txs = MTL(ObTransService *); + ObSQLSessionInfo *session_info = stmt_ctx_.session_info_; + ObTxDesc *tx_desc = stmt_ctx_.tx_desc_; + if (stmt_ctx_.use_insert_into_select_tx_) { + // do nothing + } else { + if (!stmt_ctx_.savepoint_.is_valid()) { + // do nothing + } else { + const int64_t stmt_timeout_ts = get_stmt_expire_ts(session_info); + const ObTxSEQ savepoint = stmt_ctx_.savepoint_; + if (OB_FAIL(txs->rollback_to_implicit_savepoint(*tx_desc, savepoint, stmt_timeout_ts, nullptr))) { + LOG_WARN("failed to rollback to implicit savepoint", KR(ret), KPC(tx_desc)); + } else { + stmt_ctx_.savepoint_.reset(); + LOG_INFO("rollback to implicit savepoint succeed", KPC(tx_desc), K(savepoint)); + } + } + } + return ret; +} + +int ObTableLoadInstance::lock_table_in_tx() +{ + int ret = OB_SUCCESS; + ObTableLockService *table_lock_service = MTL(ObTableLockService *); + const uint64_t table_id = stmt_ctx_.table_id_; + ObTxDesc *tx_desc = stmt_ctx_.tx_desc_; + ObLockTableRequest lock_table_arg; + lock_table_arg.owner_id_.set_default(); + lock_table_arg.lock_mode_ = tablelock::EXCLUSIVE; + lock_table_arg.op_type_ = ObTableLockOpType::IN_TRANS_DML_LOCK; + lock_table_arg.timeout_us_ = 0; // try lock + lock_table_arg.table_id_ = table_id; + bool lock_succeed = false; + int64_t sleep_time = 100 * 1000L; // 100ms + while (OB_SUCC(ret) && !lock_succeed) { + if (OB_FAIL(execute_ctx_->get_exec_ctx()->check_status())) { + LOG_WARN("failed to check status", KR(ret)); + } else if (OB_FAIL(table_lock_service->lock_table(*tx_desc, stmt_ctx_.tx_param_, lock_table_arg))) { + if (OB_EAGAIN == ret) { + ob_usleep(sleep_time); + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to lock table", KR(ret), K(lock_table_arg)); + } + } else { + lock_succeed = true; + LOG_INFO("lock table in tx succeed", K(table_id), KPC(tx_desc)); + } + } + return ret; +} + +int ObTableLoadInstance::init_ddl_param_for_inc_direct_load() +{ + int ret = OB_SUCCESS; + ObSchemaGetterGuard schema_guard; + ObCommonID raw_id; + share::SCN current_scn; + int64_t schema_version = 0; + uint64_t tenant_data_version = 0; + const uint64_t tenant_id = stmt_ctx_.tenant_id_; + const uint64_t table_id = stmt_ctx_.table_id_; + ObTableLoadDDLParam &ddl_param = stmt_ctx_.ddl_param_; + if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(tenant_id, + schema_guard))) { + LOG_WARN("failed to get schema guard", K(ret), K(tenant_id)); + } else if (OB_FAIL(schema_guard.get_schema_version(tenant_id, schema_version))) { + LOG_WARN("failed to get tenant schema version", K(ret), K(tenant_id)); + } else if (OB_FAIL(ObCommonIDUtils::gen_unique_id_by_rpc(tenant_id, raw_id))) { + LOG_WARN("failed to gen unique id by rpc", KR(ret), K(tenant_id)); + } else if (OB_FAIL(share::ObLSAttrOperator::get_tenant_gts(tenant_id, current_scn))) { + LOG_WARN("failed to get gts", KR(ret), K(tenant_id)); + } else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) { + LOG_WARN("failed to get min data version", KR(ret), K(tenant_id)); + } else { + ddl_param.schema_version_ = schema_version; + ddl_param.task_id_ = raw_id.id(); + ddl_param.snapshot_version_ = current_scn.convert_to_ts(); + ddl_param.data_version_ = tenant_data_version; + ddl_param.dest_table_id_ = table_id; + ddl_param.cluster_version_ = GET_MIN_CLUSTER_VERSION(); + LOG_INFO("init ddl param for inc direct load succeed", K(ddl_param)); + } + return ret; +} + +int ObTableLoadInstance::start_redef_table(const ObTableLoadParam ¶m) +{ + int ret = OB_SUCCESS; + ObTableLoadDDLParam &ddl_param = stmt_ctx_.ddl_param_; ObTableLoadRedefTableStartArg start_arg; ObTableLoadRedefTableStartRes start_res; start_arg.tenant_id_ = param.tenant_id_; start_arg.table_id_ = param.table_id_; start_arg.parallelism_ = param.parallel_; start_arg.is_load_data_ = !param.px_mode_; - if (OB_FAIL(ObTableLoadRedefTable::start(start_arg, start_res, *session_info))) { + if (OB_FAIL(ObTableLoadRedefTable::start(start_arg, start_res, *stmt_ctx_.session_info_))) { LOG_WARN("fail to start redef table", KR(ret), K(start_arg)); } else { ddl_param.dest_table_id_ = start_res.dest_table_id_; @@ -131,47 +496,171 @@ int ObTableLoadInstance::create_table_ctx(ObTableLoadParam ¶m, ddl_param.snapshot_version_ = start_res.snapshot_version_; ddl_param.data_version_ = start_res.data_format_version_; ddl_param.cluster_version_ = GET_MIN_CLUSTER_VERSION(); + LOG_INFO("start redef table succeed", K(ddl_param)); } - if (OB_SUCC(ret)) { - if (OB_ISNULL(table_ctx = ObTableLoadService::alloc_ctx())) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc table ctx", KR(ret), K(param)); - } else if (OB_FAIL(table_ctx->init(param, ddl_param, session_info))) { - LOG_WARN("fail to init table ctx", KR(ret)); - } else if (OB_FAIL(ObTableLoadCoordinator::init_ctx(table_ctx, idx_array, execute_ctx_))) { - LOG_WARN("fail to coordinator init ctx", KR(ret)); - } else if (OB_FAIL(ObTableLoadService::add_ctx(table_ctx))) { - LOG_WARN("fail to add ctx", KR(ret)); - } else { - table_ctx_ = table_ctx; - } + return ret; +} + +int ObTableLoadInstance::commit_redef_table() +{ + int ret = OB_SUCCESS; + ObTableLoadRedefTableFinishArg arg; + arg.tenant_id_ = stmt_ctx_.tenant_id_; + arg.table_id_ = stmt_ctx_.table_id_; + arg.dest_table_id_ = stmt_ctx_.ddl_param_.dest_table_id_; + arg.task_id_ = stmt_ctx_.ddl_param_.task_id_; + arg.schema_version_ = stmt_ctx_.ddl_param_.schema_version_; + if (OB_FAIL(ObTableLoadRedefTable::finish(arg, *stmt_ctx_.session_info_))) { + LOG_WARN("fail to finish redef table", KR(ret), K(arg)); + } else { + LOG_INFO("commit redef table succeed"); + } + return ret; +} + +int ObTableLoadInstance::abort_redef_table() +{ + int ret = OB_SUCCESS; + ObTableLoadRedefTableAbortArg arg; + arg.tenant_id_ = stmt_ctx_.tenant_id_; + arg.task_id_ = stmt_ctx_.ddl_param_.task_id_; + if (OB_FAIL(ObTableLoadRedefTable::abort(arg, *stmt_ctx_.session_info_))) { + LOG_WARN("fail to abort redef table", KR(ret), K(arg)); + } else { + LOG_INFO("abort redef table succeed"); + } + return ret; +} + +int ObTableLoadInstance::start_direct_load(const ObTableLoadParam ¶m, + const ObIArray &idx_array) +{ + int ret = OB_SUCCESS; + ObTableLoadTableCtx *table_ctx = nullptr; + ObSQLSessionInfo *session_info = execute_ctx_->get_session_info(); + if (OB_UNLIKELY(nullptr != table_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table ctx is not null", KR(ret)); + } else if (OB_ISNULL(table_ctx = ObTableLoadService::alloc_ctx())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc table ctx", KR(ret), K(param)); + } else if (OB_FAIL(table_ctx->init(param, stmt_ctx_.ddl_param_, session_info))) { + LOG_WARN("fail to init table ctx", KR(ret)); + } else if (OB_FAIL(ObTableLoadCoordinator::init_ctx(table_ctx, idx_array, execute_ctx_))) { + LOG_WARN("fail to coordinator init ctx", KR(ret)); + } else if (OB_FAIL(ObTableLoadService::add_ctx(table_ctx))) { + LOG_WARN("fail to add ctx", KR(ret)); + } else { + table_ctx_ = table_ctx; } if (OB_FAIL(ret)) { - int tmp_ret = OB_SUCCESS; - if (ddl_param.is_valid()) { - ObTableLoadRedefTableAbortArg abort_arg; - abort_arg.tenant_id_ = param.tenant_id_; - abort_arg.task_id_ = ddl_param.task_id_; - if (OB_TMP_FAIL(ObTableLoadRedefTable::abort(abort_arg, *session_info))) { - LOG_WARN("fail to abort redef table", KR(tmp_ret), K(abort_arg)); - } - } if (nullptr != table_ctx) { ObTableLoadService::free_ctx(table_ctx); table_ctx = nullptr; } } + if (OB_SUCC(ret)) { + ObTableLoadCoordinator coordinator(table_ctx_); + if (OB_FAIL(coordinator.init())) { + LOG_WARN("fail to init coordinator", KR(ret)); + } else if (OB_FAIL(coordinator.begin())) { + LOG_WARN("fail to coodrinator begin", KR(ret)); + } + } return ret; } -int ObTableLoadInstance::begin() +int ObTableLoadInstance::end_direct_load(const bool commit) { int ret = OB_SUCCESS; - ObTableLoadCoordinator coordinator(table_ctx_); - if (OB_FAIL(coordinator.init())) { - LOG_WARN("fail to init coordinator", KR(ret)); - } else if (OB_FAIL(coordinator.begin())) { - LOG_WARN("fail to coodrinator begin", KR(ret)); + int tmp_ret = OB_SUCCESS; + if (OB_UNLIKELY(nullptr == table_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table ctx is null", KR(ret)); + } else { + bool need_abort = !commit; + if (commit) { + ObTableLoadStatusType status = ObTableLoadStatusType::NONE; + int error_code = OB_SUCCESS; + ObTableLoadCoordinator coordinator(table_ctx_); + if (OB_FAIL(coordinator.init())) { + LOG_WARN("fail to init coordinator", KR(ret)); + } + // finish + else if (OB_FAIL(coordinator.finish())) { + LOG_WARN("fail to finish", KR(ret)); + } + ObTableLoadIndexLongWait wait_obj(10 * 1000, WAIT_INTERVAL_US); + while (OB_SUCC(ret) && ObTableLoadStatusType::MERGED != status && + OB_SUCC(execute_ctx_->check_status())) { + if (OB_FAIL(coordinator.get_status(status, error_code))) { + LOG_WARN("fail to coordinator get status", KR(ret)); + } else { + switch (status) { + case ObTableLoadStatusType::FROZEN: + case ObTableLoadStatusType::MERGING: + wait_obj.wait(); + break; + case ObTableLoadStatusType::MERGED: + break; + case ObTableLoadStatusType::ERROR: + ret = error_code; + LOG_WARN("table load has error", KR(ret)); + break; + default: + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected status", KR(ret), K(status)); + break; + } + } + } + if (OB_SUCC(ret)) { + // commit + if (OB_FAIL(coordinator.commit(result_info_))) { + LOG_WARN("fail to commit", KR(ret)); + } + } + if (OB_FAIL(ret)) { + need_abort = true; + } + } + if (need_abort) { + // must abort here, abort redef table need exec_ctx session_info + ObTableLoadCoordinator::abort_ctx(table_ctx_); + } + if (OB_TMP_FAIL(add_tx_result_to_user_session())) { + LOG_WARN("fail to add tx result to user session", KR(tmp_ret)); + ret = COVER_SUCC(tmp_ret); + } + if (OB_TMP_FAIL(ObTableLoadService::remove_ctx(table_ctx_))) { + LOG_WARN("table ctx may remove by service", KR(tmp_ret), KP(table_ctx_)); + } + ObTableLoadService::put_ctx(table_ctx_); + table_ctx_ = nullptr; + job_stat_ = nullptr; + } + return ret; +} + +int ObTableLoadInstance::add_tx_result_to_user_session() +{ + int ret = OB_SUCCESS; + ObTransService *txs = MTL(ObTransService *); + ObSQLSessionInfo *session_info = stmt_ctx_.session_info_; + ObTxDesc *tx_desc = session_info->get_tx_desc(); + if (OB_ISNULL(table_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table ctx is null", KR(ret)); + } else if (stmt_ctx_.is_incremental_ && !stmt_ctx_.has_added_tx_result_ && OB_NOT_NULL(tx_desc)) { + ObTxExecResult exec_result; + if (OB_FAIL(txs->get_tx_exec_result(*table_ctx_->session_info_->get_tx_desc(), exec_result))) { + LOG_WARN("failed to get tx exec result", KR(ret)); + } else if (OB_FAIL(txs->add_tx_exec_result(*tx_desc, exec_result))) { + LOG_WARN("failed to add tx exec result", KR(ret), K(exec_result)); + } else { + stmt_ctx_.has_added_tx_result_ = true; + LOG_INFO("add tx result to user session succeed"); + } } return ret; } @@ -196,14 +685,11 @@ int ObTableLoadInstance::start_trans() return ret; } -int ObTableLoadInstance::write(int32_t session_id, const table::ObTableLoadObjRowArray &obj_rows) +int ObTableLoadInstance::write_trans(int32_t session_id, const ObTableLoadObjRowArray &obj_rows) { int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); - } else if (OB_UNLIKELY(session_id < 0 || session_id > table_ctx_->param_.write_session_count_ || - obj_rows.empty())) { + if (OB_UNLIKELY(session_id < 0 || session_id > table_ctx_->param_.write_session_count_ || + obj_rows.empty())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", KR(ret), K(session_id), K(obj_rows.count())); } else { @@ -220,7 +706,7 @@ int ObTableLoadInstance::write(int32_t session_id, const table::ObTableLoadObjRo return ret; } -int ObTableLoadInstance::check_trans_committed() +int ObTableLoadInstance::commit_trans() { int ret = OB_SUCCESS; ObTableLoadTransStatusType trans_status = ObTableLoadTransStatusType::NONE; @@ -229,6 +715,11 @@ int ObTableLoadInstance::check_trans_committed() if (OB_FAIL(coordinator.init())) { LOG_WARN("fail to init coordinator", KR(ret)); } + // finish trans + else if (OB_FAIL(coordinator.finish_trans(trans_ctx_.trans_id_))) { + LOG_WARN("fail to finish trans", KR(ret)); + } + ObTableLoadIndexLongWait wait_obj(10 * 1000, WAIT_INTERVAL_US); while (OB_SUCC(ret) && ObTableLoadTransStatusType::COMMIT != trans_status && OB_SUCC(execute_ctx_->check_status())) { if (OB_FAIL(coordinator.get_trans_status(trans_ctx_.trans_id_, trans_status, error_code))) { @@ -236,7 +727,7 @@ int ObTableLoadInstance::check_trans_committed() } else { switch (trans_status) { case ObTableLoadTransStatusType::FROZEN: - usleep(WAIT_INTERVAL_US); + wait_obj.wait(); break; case ObTableLoadTransStatusType::COMMIT: break; @@ -254,126 +745,5 @@ int ObTableLoadInstance::check_trans_committed() return ret; } -int ObTableLoadInstance::check_merged() -{ - int ret = OB_SUCCESS; - ObTableLoadStatusType status = ObTableLoadStatusType::NONE; - int error_code = OB_SUCCESS; - ObTableLoadCoordinator coordinator(table_ctx_); - if (OB_FAIL(coordinator.init())) { - LOG_WARN("fail to init coordinator", KR(ret)); - } - while (OB_SUCC(ret) && ObTableLoadStatusType::MERGED != status && - OB_SUCC(execute_ctx_->check_status())) { - if (OB_FAIL(coordinator.get_status(status, error_code))) { - LOG_WARN("fail to coordinator get status", KR(ret)); - } else { - switch (status) { - case ObTableLoadStatusType::FROZEN: - case ObTableLoadStatusType::MERGING: - usleep(WAIT_INTERVAL_US); - break; - case ObTableLoadStatusType::MERGED: - break; - case ObTableLoadStatusType::ERROR: - ret = error_code; - LOG_WARN("table load has error", KR(ret)); - break; - default: - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected status", KR(ret), K(status)); - break; - } - } - } - return ret; -} - -// commit() = px_commit_data() + px_commit_ddl() -// used in non px_mode -int ObTableLoadInstance::commit(ObTableLoadResultInfo &result_info) -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); - } else { - ObTableLoadCoordinator coordinator(table_ctx_); - if (OB_FAIL(coordinator.init())) { - LOG_WARN("fail to init coordinator", KR(ret)); - } - // finish trans - else if (OB_FAIL(coordinator.finish_trans(trans_ctx_.trans_id_))) { - LOG_WARN("fail to finish trans", KR(ret)); - } - // wait trans commit - else if (OB_FAIL(check_trans_committed())) { - LOG_WARN("fail to check trans committed", KR(ret)); - } - // finish - else if (OB_FAIL(coordinator.finish())) { - LOG_WARN("fail to finish", KR(ret)); - } - // wait merge - else if (OB_FAIL(check_merged())) { - LOG_WARN("fail to check merged", KR(ret)); - } - // commit - else if (OB_FAIL(coordinator.commit(result_info))) { - LOG_WARN("fail to commit", KR(ret)); - } else { - is_committed_ = true; - } - } - return ret; -} - -// used in insert /*+ append */ into select clause -int ObTableLoadInstance::px_commit_data() -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); - } else { - ObTableLoadCoordinator coordinator(table_ctx_); - if (OB_FAIL(coordinator.init())) { - LOG_WARN("fail to init coordinator", KR(ret)); - } - // finish - else if (OB_FAIL(coordinator.finish())) { - LOG_WARN("fail to finish", KR(ret)); - } - // wait merge - else if (OB_FAIL(check_merged())) { - LOG_WARN("fail to check merged", KR(ret)); - } - // commit - else if (OB_FAIL(coordinator.px_commit_data())) { - LOG_WARN("fail to do px_commit_data", KR(ret)); - } - } - return ret; -} - -int ObTableLoadInstance::px_commit_ddl() -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObTableLoadInstance not init", KR(ret), KP(this)); - } else { - ObTableLoadCoordinator coordinator(table_ctx_); - if (OB_FAIL(coordinator.init())) { - LOG_WARN("fail to init coordinator", KR(ret)); - } else if (OB_FAIL(coordinator.px_commit_ddl())) { - LOG_WARN("fail to do px_commit_ddl", KR(ret)); - } else { - is_committed_ = true; - } - } - return ret; -} - } // namespace observer } // namespace oceanbase diff --git a/src/observer/table_load/ob_table_load_instance.h b/src/observer/table_load/ob_table_load_instance.h index a399ee57f..4df3aa16f 100644 --- a/src/observer/table_load/ob_table_load_instance.h +++ b/src/observer/table_load/ob_table_load_instance.h @@ -18,15 +18,21 @@ namespace oceanbase { +namespace transaction +{ +class ObTxDesc; +struct ObTxParam; +} namespace observer { class ObTableLoadParam; class ObTableLoadTableCtx; class ObTableLoadExecCtx; +class ObTableLoadDDLParam; class ObTableLoadInstance { - static const int64_t WAIT_INTERVAL_US = 1LL * 1000 * 1000; // 1s + static const int64_t WAIT_INTERVAL_US = 3 * 1000 * 1000; // 3s public: ObTableLoadInstance(); ~ObTableLoadInstance(); @@ -34,26 +40,91 @@ public: int init(ObTableLoadParam ¶m, const common::ObIArray &idx_array, ObTableLoadExecCtx *execute_ctx); int write(int32_t session_id, const table::ObTableLoadObjRowArray &obj_rows); - int commit(table::ObTableLoadResultInfo &result_info); + int commit(); int px_commit_data(); int px_commit_ddl(); - sql::ObLoadDataStat *get_job_stat() const { return job_stat_; } - void update_job_stat_parsed_rows(int64_t parsed_rows) - { - ATOMIC_AAF(&job_stat_->parsed_rows_, parsed_rows); - } - void update_job_stat_parsed_bytes(int64_t parsed_bytes) - { - ATOMIC_AAF(&job_stat_->parsed_bytes_, parsed_bytes); - } const ObTableLoadTableCtx* get_table_ctx() { return table_ctx_; } + sql::ObLoadDataStat *get_job_stat() const { return job_stat_; } + const table::ObTableLoadResultInfo &get_result_info() const { return result_info_; } private: - int create_table_ctx(ObTableLoadParam ¶m, const common::ObIArray &idx_array); - int begin(); + int start_stmt(const ObTableLoadParam ¶m); + int end_stmt(const bool commit); + // incremental + static int64_t get_stmt_expire_ts(sql::ObSQLSessionInfo *session_info); + int build_tx_param(); + int start_sql_tx(); + int end_sql_tx(const bool commit); + // abort tx is async, use rollback savepoint to sync release table lock + int create_implicit_savepoint(); + int rollback_to_implicit_savepoint(); + int lock_table_in_tx(); + int init_ddl_param_for_inc_direct_load(); + // full + int start_redef_table(const ObTableLoadParam ¶m); + int commit_redef_table(); + int abort_redef_table(); +private: + // direct load + int start_direct_load(const ObTableLoadParam ¶m, const common::ObIArray &idx_array); + int end_direct_load(const bool commit); + int add_tx_result_to_user_session(); int start_trans(); - int check_trans_committed(); - int check_merged(); + int write_trans(int32_t session_id, const table::ObTableLoadObjRowArray &obj_rows); + int commit_trans(); private: + struct StmtCtx + { + public: + StmtCtx() + : tenant_id_(OB_INVALID_TENANT_ID), + table_id_(OB_INVALID_ID), + session_info_(nullptr), + tx_desc_(nullptr), + is_incremental_(false), + use_insert_into_select_tx_(false), + is_started_(false), + has_added_tx_result_(false) + { + } + void reset() + { + tenant_id_ = OB_INVALID_TENANT_ID; + table_id_ = OB_INVALID_ID; + ddl_param_.reset(); + session_info_ = nullptr; + tx_desc_ = nullptr; + // tx_param_.reset(); + savepoint_.reset(); + is_incremental_ = false; + use_insert_into_select_tx_ = false; + is_started_ = false; + has_added_tx_result_ = false; + } + bool is_started() const { return is_started_; } + TO_STRING_KV(K_(tenant_id), + K_(table_id), + K_(ddl_param), + KP_(session_info), + KPC_(tx_desc), + K_(tx_param), + K_(savepoint), + KP_(is_incremental), + KP_(use_insert_into_select_tx), + KP_(is_started), + KP_(has_added_tx_result)); + public: + uint64_t tenant_id_; + uint64_t table_id_; + ObTableLoadDDLParam ddl_param_; + sql::ObSQLSessionInfo *session_info_; + transaction::ObTxDesc *tx_desc_; + transaction::ObTxParam tx_param_; + transaction::ObTxSEQ savepoint_; + bool is_incremental_; + bool use_insert_into_select_tx_; // whether use the transaction of insert into select + bool is_started_; + bool has_added_tx_result_; + }; struct TransCtx { public: @@ -72,11 +143,12 @@ private: common::ObIAllocator *allocator_; ObTableLoadTableCtx *table_ctx_; sql::ObLoadDataStat *job_stat_; + StmtCtx stmt_ctx_; TransCtx trans_ctx_; - bool is_committed_; + table::ObTableLoadResultInfo result_info_; bool is_inited_; DISALLOW_COPY_AND_ASSIGN(ObTableLoadInstance); }; } // namespace observer -} // namespace oceanbase \ No newline at end of file +} // namespace oceanbase diff --git a/src/observer/table_load/ob_table_load_merger.cpp b/src/observer/table_load/ob_table_load_merger.cpp index ad33df363..dddedf164 100644 --- a/src/observer/table_load/ob_table_load_merger.cpp +++ b/src/observer/table_load/ob_table_load_merger.cpp @@ -272,18 +272,13 @@ int ObTableLoadMerger::build_merge_ctx() merge_param.target_table_id_ = store_ctx_->ctx_->ddl_param_.dest_table_id_; merge_param.rowkey_column_num_ = store_ctx_->ctx_->schema_.rowkey_column_count_; merge_param.store_column_count_ = store_ctx_->ctx_->schema_.store_column_count_; - merge_param.snapshot_version_ = store_ctx_->ctx_->ddl_param_.snapshot_version_; + merge_param.fill_cg_thread_cnt_ = param_.session_count_; merge_param.table_data_desc_ = store_ctx_->table_data_desc_; merge_param.datum_utils_ = &(store_ctx_->ctx_->schema_.datum_utils_); merge_param.col_descs_ = &(store_ctx_->ctx_->schema_.column_descs_); - merge_param.lob_column_cnt_ = store_ctx_->ctx_->schema_.lob_column_cnt_; - merge_param.cmp_funcs_ = &(store_ctx_->ctx_->schema_.cmp_funcs_); merge_param.is_heap_table_ = store_ctx_->ctx_->schema_.is_heap_table_; merge_param.is_fast_heap_table_ = store_ctx_->is_fast_heap_table_; - merge_param.online_opt_stat_gather_ = param_.online_opt_stat_gather_; - merge_param.is_column_store_ = store_ctx_->ctx_->schema_.is_column_store_; - merge_param.fill_cg_thread_cnt_ = param_.session_count_; - merge_param.px_mode_ = param_.px_mode_; + merge_param.is_incremental_ = ObDirectLoadMethod::is_incremental(param_.method_); merge_param.insert_mode_ = param_.insert_mode_; merge_param.insert_table_ctx_ = store_ctx_->insert_table_ctx_; merge_param.dml_row_handler_ = store_ctx_->error_row_handler_; @@ -398,115 +393,6 @@ int ObTableLoadMerger::build_merge_ctx() return ret; } -int ObTableLoadMerger::collect_dml_stat(ObTableLoadDmlStat &dml_stats) -{ - int ret = OB_SUCCESS; - if (store_ctx_->is_fast_heap_table_) { - ObDirectLoadMultiMap tables; - ObArray trans_store_array; - trans_store_array.set_tenant_id(MTL_ID()); - if (OB_FAIL(tables.init())) { - LOG_WARN("fail to init table", KR(ret)); - } else if (OB_FAIL(store_ctx_->get_committed_trans_stores(trans_store_array))) { - LOG_WARN("fail to get trans store", KR(ret)); - } else { - for (int i = 0; OB_SUCC(ret) && i < trans_store_array.count(); ++i) { - ObTableLoadTransStore *trans_store = trans_store_array.at(i); - for (int j = 0; OB_SUCC(ret) && j < trans_store->session_store_array_.count(); ++j) { - ObTableLoadTransStore::SessionStore * session_store = trans_store->session_store_array_.at(j); - for (int k = 0 ; OB_SUCC(ret) && k < session_store->partition_table_array_.count(); ++k) { - ObIDirectLoadPartitionTable *table = session_store->partition_table_array_.at(k); - ObDirectLoadFastHeapTable *sstable = nullptr; - if (OB_ISNULL(sstable = dynamic_cast(table))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected not heap sstable", KR(ret), KPC(table)); - } else { - const ObTabletID &tablet_id = sstable->get_tablet_id(); - if (OB_FAIL(tables.add(tablet_id, sstable))) { - LOG_WARN("fail to add tables", KR(ret), KPC(sstable)); - } - } - } - } - } - for (int i = 0; OB_SUCC(ret) && i < merge_ctx_.get_tablet_merge_ctxs().count(); ++i) { - ObDirectLoadTabletMergeCtx *tablet_ctx = merge_ctx_.get_tablet_merge_ctxs().at(i); - ObArray heap_table_array; - heap_table_array.set_tenant_id(MTL_ID()); - if (OB_FAIL(tables.get(tablet_ctx->get_tablet_id(), heap_table_array))) { - LOG_WARN("get heap sstable failed", KR(ret)); - } else if (OB_FAIL(tablet_ctx->collect_dml_stat(heap_table_array, dml_stats))) { - LOG_WARN("fail to collect sql statics", KR(ret)); - } - } - } - } else { - for (int i = 0; OB_SUCC(ret) && i < merge_ctx_.get_tablet_merge_ctxs().count(); ++i) { - ObDirectLoadTabletMergeCtx *tablet_ctx = merge_ctx_.get_tablet_merge_ctxs().at(i); - ObArray empty_heap_table_array; - if (OB_FAIL(tablet_ctx->collect_dml_stat(empty_heap_table_array, dml_stats))) { - LOG_WARN("fail to collect sql statics", KR(ret)); - } - } - } - return ret; -} - -int ObTableLoadMerger::collect_sql_statistics(ObTableLoadSqlStatistics &sql_statistics) -{ - int ret = OB_SUCCESS; - if (store_ctx_->is_fast_heap_table_) { - ObDirectLoadMultiMap tables; - ObArray trans_store_array; - trans_store_array.set_tenant_id(MTL_ID()); - if (OB_FAIL(tables.init())) { - LOG_WARN("fail to init table", KR(ret)); - } else if (OB_FAIL(store_ctx_->get_committed_trans_stores(trans_store_array))) { - LOG_WARN("fail to get trans store", KR(ret)); - } else { - for (int i = 0; OB_SUCC(ret) && i < trans_store_array.count(); ++i) { - ObTableLoadTransStore *trans_store = trans_store_array.at(i); - for (int j = 0; OB_SUCC(ret) && j < trans_store->session_store_array_.count(); ++j) { - ObTableLoadTransStore::SessionStore * session_store = trans_store->session_store_array_.at(j); - for (int k = 0 ; OB_SUCC(ret) && k < session_store->partition_table_array_.count(); ++k) { - ObIDirectLoadPartitionTable *table = session_store->partition_table_array_.at(k); - ObDirectLoadFastHeapTable *sstable = nullptr; - if (OB_ISNULL(sstable = dynamic_cast(table))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected not heap sstable", KR(ret), KPC(table)); - } else { - const ObTabletID &tablet_id = sstable->get_tablet_id(); - if (OB_FAIL(tables.add(tablet_id, sstable))) { - LOG_WARN("fail to add tables", KR(ret), KPC(sstable)); - } - } - } - } - } - for (int i = 0; OB_SUCC(ret) && i < merge_ctx_.get_tablet_merge_ctxs().count(); ++i) { - ObDirectLoadTabletMergeCtx *tablet_ctx = merge_ctx_.get_tablet_merge_ctxs().at(i); - ObArray heap_table_array; - heap_table_array.set_tenant_id(MTL_ID()); - if (OB_FAIL(tables.get(tablet_ctx->get_tablet_id(), heap_table_array))) { - LOG_WARN("get heap sstable failed", KR(ret)); - } else if (OB_FAIL(tablet_ctx->collect_sql_statistics(heap_table_array, sql_statistics))) { - LOG_WARN("fail to collect sql statics", KR(ret)); - } - } - } - } else { - for (int i = 0; OB_SUCC(ret) && i < merge_ctx_.get_tablet_merge_ctxs().count(); ++i) { - ObDirectLoadTabletMergeCtx *tablet_ctx = merge_ctx_.get_tablet_merge_ctxs().at(i); - ObArray heap_table_array; - heap_table_array.set_tenant_id(MTL_ID()); - if (OB_FAIL(tablet_ctx->collect_sql_statistics(heap_table_array, sql_statistics))) { - LOG_WARN("fail to collect sql statics", KR(ret)); - } - } - } - return ret; -} - int ObTableLoadMerger::build_rescan_ctx() { int ret = OB_SUCCESS; @@ -675,7 +561,7 @@ int ObTableLoadMerger::handle_merge_thread_finish(int ret_code) if (!store_ctx_->is_fast_heap_table_) { table_compact_ctx_.result_.release_all_table_data(); } - if (store_ctx_->ctx_->schema_.is_column_store_) { + if (store_ctx_->insert_table_ctx_->need_rescan()) { if (OB_FAIL(build_rescan_ctx())) { LOG_WARN("fail to build rescan ctx", KR(ret)); } else if (OB_FAIL(start_rescan())) { diff --git a/src/observer/table_load/ob_table_load_merger.h b/src/observer/table_load/ob_table_load_merger.h index ed9d630b0..a206b9bd4 100644 --- a/src/observer/table_load/ob_table_load_merger.h +++ b/src/observer/table_load/ob_table_load_merger.h @@ -41,8 +41,6 @@ public: int start(); void stop(); int handle_table_compact_success(); - int collect_sql_statistics(table::ObTableLoadSqlStatistics &sql_statistics); - int collect_dml_stat(table::ObTableLoadDmlStat &dml_stats); private: int build_merge_ctx(); int build_rescan_ctx(); diff --git a/src/observer/table_load/ob_table_load_schema.cpp b/src/observer/table_load/ob_table_load_schema.cpp index 63443e403..e517b4622 100644 --- a/src/observer/table_load/ob_table_load_schema.cpp +++ b/src/observer/table_load/ob_table_load_schema.cpp @@ -253,6 +253,29 @@ int ObTableLoadSchema::get_tenant_optimizer_gather_stats_on_load(const uint64_t return ret; } +int ObTableLoadSchema::get_lob_meta_tid( + const uint64_t tenant_id, + const uint64_t data_table_id, + uint64_t &lob_meta_table_id) +{ + int ret = OB_SUCCESS; + ObSchemaGetterGuard schema_guard; + const ObTableSchema *data_table_schema = nullptr; + lob_meta_table_id = OB_INVALID_ID; + if (OB_FAIL(ObTableLoadSchema::get_table_schema( + tenant_id, data_table_id, schema_guard, data_table_schema))) { + LOG_WARN("failed to get table schema", KR(ret), K(tenant_id), K(data_table_id)); + } else if (OB_ISNULL(data_table_schema)) { + ret = OB_TABLE_NOT_EXIST; + LOG_WARN("data table not exist", KR(ret), K(tenant_id), K(data_table_id)); + } else if (!data_table_schema->has_lob_aux_table()) { + // bypass + } else { + lob_meta_table_id = data_table_schema->get_aux_lob_meta_tid(); + } + return ret; +} + ObTableLoadSchema::ObTableLoadSchema() : allocator_("TLD_Schema"), is_partitioned_table_(false), @@ -264,6 +287,7 @@ ObTableLoadSchema::ObTableLoadSchema() store_column_count_(0), lob_column_cnt_(0), collation_type_(CS_TYPE_INVALID), + part_level_(PARTITION_LEVEL_ZERO), schema_version_(0), is_inited_(false) { @@ -289,6 +313,7 @@ void ObTableLoadSchema::reset() store_column_count_ = 0; lob_column_cnt_ = 0; collation_type_ = CS_TYPE_INVALID; + part_level_ = PARTITION_LEVEL_ZERO; schema_version_ = 0; column_descs_.reset(); multi_version_column_descs_.reset(); @@ -332,6 +357,7 @@ int ObTableLoadSchema::init_table_schema(const ObTableSchema *table_schema) has_autoinc_column_ = (table_schema->get_autoinc_column_id() != 0); rowkey_column_count_ = table_schema->get_rowkey_column_num(); collation_type_ = table_schema->get_collation_type(); + part_level_ = table_schema->get_part_level(); schema_version_ = table_schema->get_schema_version(); if (OB_FAIL(ObTableLoadUtils::deep_copy(table_schema->get_table_name_str(), table_name_, allocator_))) { diff --git a/src/observer/table_load/ob_table_load_schema.h b/src/observer/table_load/ob_table_load_schema.h index 88bfdee26..36223a870 100644 --- a/src/observer/table_load/ob_table_load_schema.h +++ b/src/observer/table_load/ob_table_load_schema.h @@ -47,6 +47,9 @@ public: common::ObIArray &column_idxs); static int check_has_udt_column(const share::schema::ObTableSchema *table_schema, bool &bret); static int get_tenant_optimizer_gather_stats_on_load(const uint64_t tenant_id, bool &value); + static int get_lob_meta_tid(const uint64_t tenant_id, + const uint64_t data_table_id, + uint64_t &lob_meta_table_id); public: ObTableLoadSchema(); ~ObTableLoadSchema(); @@ -78,6 +81,7 @@ public: int64_t store_column_count_; int64_t lob_column_cnt_; common::ObCollationType collation_type_; + share::schema::ObPartitionLevel part_level_; int64_t schema_version_; // if it is a heap table, it contains hidden primary key column // does not contain virtual generated columns diff --git a/src/observer/table_load/ob_table_load_service.cpp b/src/observer/table_load/ob_table_load_service.cpp index 3647d61e9..3542459de 100644 --- a/src/observer/table_load/ob_table_load_service.cpp +++ b/src/observer/table_load/ob_table_load_service.cpp @@ -32,6 +32,7 @@ namespace observer using namespace common; using namespace lib; using namespace share::schema; +using namespace storage; using namespace table; using namespace omt; @@ -476,14 +477,31 @@ int ObTableLoadService::check_support_direct_load( ret = OB_NOT_SUPPORTED; LOG_WARN("direct-load does not support table with materialized view log", KR(ret)); FORWARD_USER_ERROR_MSG(ret, "direct-load does not support table with materialized view log"); - } else if (OB_UNLIKELY(ObDirectLoadMethod::is_incremental(method))) { // incremental direct-load - ret = OB_NOT_SUPPORTED; - LOG_WARN("incremental direct-load is not supported", KR(ret)); - FORWARD_USER_ERROR_MSG(ret, "incremental direct-load is not supported"); - } else if (ObDirectLoadMethod::is_full(method)) { // full direct-load - if (OB_UNLIKELY(!ObDirectLoadInsertMode::is_valid_for_full_method(insert_mode))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected insert mode for full direct-load", KR(ret), K(method), K(insert_mode)); + } else if (ObDirectLoadMethod::is_incremental(method)) { // incremental direct-load + uint64_t compat_version = 0; + if (OB_UNLIKELY(ObDirectLoadInsertMode::INC_REPLACE != insert_mode)) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("using incremental direct-load without inc_replace is not supported", KR(ret)); + FORWARD_USER_ERROR_MSG(ret, "using incremental direct-load without inc_replace is not supported"); + } else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { + LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); + } else if (compat_version < DATA_VERSION_4_3_1_0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("version lower than 4.3.1.0 does not support incremental direct-load", KR(ret)); + FORWARD_USER_ERROR_MSG(ret, "version lower than 4.3.1.0 does not support incremental direct-load"); + } else if (table_schema->get_index_tid_count() > 0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("incremental direct-load does not support table with indexes", KR(ret)); + FORWARD_USER_ERROR_MSG(ret, "incremental direct-load does not support table with indexes"); + } else if (table_schema->get_foreign_key_infos().count() > 0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("incremental direct-load does not support table with foreign keys", KR(ret)); + FORWARD_USER_ERROR_MSG(ret, "incremental direct-load does not support table with foreign keys"); + } else if (ObDirectLoadMethod::is_full(method)) { // full direct-load + if (OB_UNLIKELY(!ObDirectLoadInsertMode::is_valid_for_full_method(insert_mode))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected insert mode for full direct-load", KR(ret), K(method), K(insert_mode)); + } } } } diff --git a/src/observer/table_load/ob_table_load_store.cpp b/src/observer/table_load/ob_table_load_store.cpp index 524f38b89..3f03f991c 100644 --- a/src/observer/table_load/ob_table_load_store.cpp +++ b/src/observer/table_load/ob_table_load_store.cpp @@ -25,8 +25,8 @@ #include "observer/table_load/ob_table_load_utils.h" #include "storage/direct_load/ob_direct_load_insert_table_ctx.h" #include "share/stat/ob_opt_stat_monitor_manager.h" -#include "share/stat/ob_dbms_stats_utils.h" #include "storage/blocksstable/ob_sstable.h" +#include "share/table/ob_table_load_dml_stat.h" namespace oceanbase { @@ -34,6 +34,7 @@ namespace observer { using namespace common; using namespace table; +using namespace transaction; ObTableLoadStore::ObTableLoadStore(ObTableLoadTableCtx *ctx) : ctx_(ctx), param_(ctx->param_), store_ctx_(ctx->store_ctx_), is_inited_(false) @@ -299,31 +300,35 @@ int ObTableLoadStore::start_merge() return ret; } -int ObTableLoadStore::commit(ObTableLoadResultInfo &result_info) +int ObTableLoadStore::commit(ObTableLoadResultInfo &result_info, + ObTableLoadSqlStatistics &sql_statistics, + ObTxExecResult &trans_result) { int ret = OB_SUCCESS; + sql_statistics.reset(); + trans_result.reset(); if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObTableLoadStore not init", KR(ret), KP(this)); } else { LOG_INFO("store commit"); + ObTransService *txs = nullptr; ObMutexGuard guard(store_ctx_->get_op_lock()); ObTableLoadDmlStat dml_stats; - ObTableLoadSqlStatistics sql_statistics; - if (OB_FAIL(store_ctx_->check_status(ObTableLoadStatusType::MERGED))) { + if (OB_ISNULL(MTL(ObTransService *))) { + ret = OB_ERR_SYS; + LOG_WARN("trans service is null", KR(ret)); + } else if (OB_FAIL(store_ctx_->check_status(ObTableLoadStatusType::MERGED))) { LOG_WARN("fail to check store status", KR(ret)); + } else if (OB_FAIL(store_ctx_->insert_table_ctx_->commit(dml_stats, sql_statistics))) { + LOG_WARN("fail to commit insert table", KR(ret)); } else if (ctx_->schema_.has_autoinc_column_ && OB_FAIL(store_ctx_->commit_autoinc_value())) { LOG_WARN("fail to commit sync auto increment value", KR(ret)); - } else if (param_.online_opt_stat_gather_ && - OB_FAIL(store_ctx_->merger_->collect_sql_statistics(sql_statistics))) { - LOG_WARN("fail to collect sql stats", KR(ret)); - } else if (param_.online_opt_stat_gather_ && - OB_FAIL(commit_sql_statistics(sql_statistics))) { - LOG_WARN("fail to commit sql stats", KR(ret)); - } else if (OB_FAIL(store_ctx_->merger_->collect_dml_stat(dml_stats))) { - LOG_WARN("fail to build dml stat", KR(ret)); } else if (OB_FAIL(ObOptStatMonitorManager::update_dml_stat_info_from_direct_load(dml_stats.dml_stat_array_))) { LOG_WARN("fail to update dml stat info", KR(ret)); + } else if (ObDirectLoadMethod::is_incremental(param_.method_) && + txs->get_tx_exec_result(*ctx_->session_info_->get_tx_desc(), trans_result)) { + LOG_WARN("fail to get tx exec result", KR(ret)); } else if (OB_FAIL(store_ctx_->set_status_commit())) { LOG_WARN("fail to set store status commit", KR(ret)); } else { @@ -334,36 +339,6 @@ int ObTableLoadStore::commit(ObTableLoadResultInfo &result_info) return ret; } -int ObTableLoadStore::commit_sql_statistics(const ObTableLoadSqlStatistics &sql_statistics) -{ - int ret = OB_SUCCESS; - const uint64_t tenant_id = MTL_ID(); - const uint64_t table_id = param_.table_id_; - ObSchemaGetterGuard schema_guard; - const ObTableSchema *table_schema = nullptr; - ObArray part_column_stats; - ObArray part_table_stats; - part_column_stats.set_tenant_id(MTL_ID()); - part_table_stats.set_tenant_id(MTL_ID()); - if (sql_statistics.is_empty()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("sql statistics is empty", K(ret)); - } else if (OB_FAIL(ObTableLoadSchema::get_table_schema(tenant_id, table_id, schema_guard, - table_schema))) { - LOG_WARN("fail to get table schema", KR(ret), K(tenant_id), K(table_id)); - } else if (OB_FAIL(sql_statistics.get_col_stat_array(part_column_stats))) { - LOG_WARN("failed to get column stat array"); - } else if (OB_FAIL(sql_statistics.get_table_stat_array(part_table_stats))) { - LOG_WARN("failed to get table stat array"); - } else if (OB_FAIL(ObDbmsStatsUtils::split_batch_write( - &schema_guard, store_ctx_->ctx_->session_info_, GCTX.sql_proxy_, part_table_stats, - part_column_stats))) { - LOG_WARN("failed to batch write stats", K(ret), K(sql_statistics.table_stat_array_), - K(sql_statistics.col_stat_array_)); - } - return ret; -} - int ObTableLoadStore::get_status(ObTableLoadStatusType &status, int &error_code) { int ret = OB_SUCCESS; diff --git a/src/observer/table_load/ob_table_load_store.h b/src/observer/table_load/ob_table_load_store.h index 84bdfb095..563ed024c 100644 --- a/src/observer/table_load/ob_table_load_store.h +++ b/src/observer/table_load/ob_table_load_store.h @@ -17,10 +17,13 @@ #include "share/table/ob_table_load_array.h" #include "share/table/ob_table_load_define.h" #include "share/table/ob_table_load_row_array.h" -#include "share/table/ob_table_load_sql_statistics.h" namespace oceanbase { +namespace table +{ +class ObTableLoadSqlStatistics; +} // namespace table namespace observer { class ObTableLoadTableCtx; @@ -46,11 +49,11 @@ public: int confirm_begin(); int pre_merge(const table::ObTableLoadArray &committed_trans_id_array); int start_merge(); - int commit(table::ObTableLoadResultInfo &result_info); + int commit(table::ObTableLoadResultInfo &result_info, + table::ObTableLoadSqlStatistics &sql_statistics, + transaction::ObTxExecResult &trans_result); int get_status(table::ObTableLoadStatusType &status, int &error_code); int heart_beat(); -private: - int commit_sql_statistics(const table::ObTableLoadSqlStatistics &sql_statistics); private: class MergeTaskProcessor; class MergeTaskCallback; diff --git a/src/observer/table_load/ob_table_load_store_ctx.cpp b/src/observer/table_load/ob_table_load_store_ctx.cpp index be8f2f983..f593978f6 100644 --- a/src/observer/table_load/ob_table_load_store_ctx.cpp +++ b/src/observer/table_load/ob_table_load_store_ctx.cpp @@ -83,14 +83,6 @@ int ObTableLoadStoreCtx::init( ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", KR(ret), K(partition_id_array), K(target_partition_id_array)); } else { - ObDirectLoadInsertTableParam insert_table_param; - insert_table_param.table_id_ = ctx_->param_.table_id_; - insert_table_param.schema_version_ = ctx_->ddl_param_.schema_version_; - insert_table_param.snapshot_version_ = ctx_->ddl_param_.snapshot_version_; - insert_table_param.ddl_task_id_ = ctx_->ddl_param_.task_id_; - insert_table_param.execution_id_ = 1; //仓氐说暂时设置为1,不然后面检测过不了 - insert_table_param.data_version_ = ctx_->ddl_param_.data_version_; - insert_table_param.reserved_parallel_ = ctx_->param_.session_count_; for (int64_t i = 0; OB_SUCC(ret) && i < partition_id_array.count(); ++i) { const ObLSID &ls_id = partition_id_array[i].ls_id_; const ObTableLoadPartitionId &part_tablet_id = partition_id_array[i].part_tablet_id_; @@ -167,10 +159,6 @@ int ObTableLoadStoreCtx::init( } } if (OB_FAIL(ret)) { - } else if (OB_FAIL(insert_table_param.ls_partition_ids_.assign(ls_partition_ids_))) { - LOG_WARN("fail to assign ls tablet ids", KR(ret)); - } else if (OB_FAIL(insert_table_param.target_ls_partition_ids_.assign(target_ls_partition_ids_))) { - LOG_WARN("fail to assign ls tablet ids", KR(ret)); } // init trans_allocator_ else if (OB_FAIL(trans_allocator_.init("TLD_STransPool", ctx_->param_.tenant_id_))) { @@ -208,12 +196,41 @@ int ObTableLoadStoreCtx::init( LOG_WARN("fail to init merger", KR(ret)); } // init insert_table_ctx_ - else if (OB_ISNULL(insert_table_ctx_ = + if (OB_SUCC(ret)) { + ObDirectLoadInsertTableParam insert_table_param; + insert_table_param.table_id_ = ctx_->ddl_param_.dest_table_id_; + insert_table_param.schema_version_ = ctx_->ddl_param_.schema_version_; + insert_table_param.snapshot_version_ = ctx_->ddl_param_.snapshot_version_; + insert_table_param.ddl_task_id_ = ctx_->ddl_param_.task_id_; + insert_table_param.data_version_ = ctx_->ddl_param_.data_version_; + insert_table_param.parallel_ = ctx_->param_.session_count_; + insert_table_param.reserved_parallel_ = is_fast_heap_table_ ? ctx_->param_.session_count_ : 0; + insert_table_param.rowkey_column_count_ = ctx_->schema_.rowkey_column_count_; + insert_table_param.column_count_ = ctx_->schema_.store_column_count_; + insert_table_param.lob_column_count_ = ctx_->schema_.lob_column_cnt_; + insert_table_param.is_partitioned_table_ = ctx_->schema_.is_partitioned_table_; + insert_table_param.is_heap_table_ = ctx_->schema_.is_heap_table_; + insert_table_param.is_column_store_ = ctx_->schema_.is_column_store_; + insert_table_param.online_opt_stat_gather_ = ctx_->param_.online_opt_stat_gather_; + insert_table_param.is_incremental_ = ObDirectLoadMethod::is_incremental(ctx_->param_.method_); + insert_table_param.datum_utils_ = &(ctx_->schema_.datum_utils_); + insert_table_param.col_descs_ = &(ctx_->schema_.column_descs_); + insert_table_param.cmp_funcs_ = &(ctx_->schema_.cmp_funcs_); + if (insert_table_param.is_incremental_ && OB_FAIL(init_trans_param(insert_table_param.trans_param_))) { + LOG_WARN("fail to init trans param", KR(ret)); + } else if (OB_FAIL(ObTableLoadSchema::get_lob_meta_tid(ctx_->param_.tenant_id_, + insert_table_param.table_id_, insert_table_param.lob_meta_tid_))) { + LOG_WARN("fail to get lob meta tid", KR(ret), + K(ctx_->param_.tenant_id_), K(insert_table_param.table_id_)); + } else if (OB_ISNULL(insert_table_ctx_ = OB_NEWx(ObDirectLoadInsertTableContext, (&allocator_)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new ObDirectLoadInsertTableContext", KR(ret)); - } else if (OB_FAIL(insert_table_ctx_->init(insert_table_param))) { - LOG_WARN("fail to init insert table ctx", KR(ret)); + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObDirectLoadInsertTableContext", KR(ret)); + } else if (OB_FAIL(insert_table_ctx_->init(insert_table_param, ls_partition_ids_, target_ls_partition_ids_))) { + LOG_WARN("fail to init insert table ctx", KR(ret)); + } + } + if (OB_FAIL(ret)) { } // init tmp_file_mgr_ else if (OB_ISNULL(tmp_file_mgr_ = OB_NEWx(ObDirectLoadTmpFileManager, (&allocator_)))) { @@ -400,6 +417,30 @@ bool ObTableLoadStoreCtx::check_heart_beat_expired(const uint64_t expired_time_u return ObTimeUtil::current_time() > (last_heart_beat_ts_ + expired_time_us); } +int ObTableLoadStoreCtx::init_trans_param(ObDirectLoadTransParam &trans_param) +{ + int ret = OB_SUCCESS; + ObSQLSessionInfo *session_info = nullptr; + transaction::ObTxDesc *tx_desc = nullptr; + trans_param.reset(); + if (OB_ISNULL(session_info = ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null session info", KR(ret)); + } else if (OB_UNLIKELY(!session_info->is_in_transaction())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected not in transaction", KR(ret)); + } else if (OB_ISNULL(tx_desc = session_info->get_tx_desc())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null tx desc", KR(ret)); + } else { + trans_param.tx_desc_ = tx_desc; + trans_param.tx_id_ = tx_desc->get_tx_id(); + trans_param.tx_seq_ = tx_desc->inc_and_get_tx_seq(0); + LOG_INFO("init trans param", K(trans_param)); + } + return ret; +} + int ObTableLoadStoreCtx::generate_autoinc_params(AutoincParam &autoinc_param) { int ret = OB_SUCCESS; diff --git a/src/observer/table_load/ob_table_load_store_ctx.h b/src/observer/table_load/ob_table_load_store_ctx.h index f88fab38c..5655e3e9f 100644 --- a/src/observer/table_load/ob_table_load_store_ctx.h +++ b/src/observer/table_load/ob_table_load_store_ctx.h @@ -26,6 +26,7 @@ namespace oceanbase { namespace storage { +class ObDirectLoadTransParam; class ObDirectLoadInsertTableContext; class ObDirectLoadTmpFileManager; } // namespace storage @@ -130,6 +131,7 @@ private: int alloc_trans_ctx(const table::ObTableLoadTransId &trans_id, ObTableLoadTransCtx *&trans_ctx); int alloc_trans(const table::ObTableLoadTransId &trans_id, ObTableLoadStoreTrans *&trans); int init_session_ctx_array(); + int init_trans_param(ObDirectLoadTransParam &trans_param); int generate_autoinc_params(share::AutoincParam &autoinc_param); int init_sequence(); public: diff --git a/src/observer/table_load/ob_table_load_struct.cpp b/src/observer/table_load/ob_table_load_struct.cpp index 293f6d300..d01fcaaac 100644 --- a/src/observer/table_load/ob_table_load_struct.cpp +++ b/src/observer/table_load/ob_table_load_struct.cpp @@ -21,7 +21,7 @@ namespace observer using namespace common; using namespace table; -OB_SERIALIZE_MEMBER_SIMPLE(ObTableLoadUniqueKey, table_id_, task_id_); +OB_SERIALIZE_MEMBER(ObTableLoadUniqueKey, table_id_, task_id_); OB_SERIALIZE_MEMBER(ObTableLoadDDLParam, dest_table_id_, diff --git a/src/observer/table_load/ob_table_load_struct.h b/src/observer/table_load/ob_table_load_struct.h index 8b64a887f..629ee4476 100644 --- a/src/observer/table_load/ob_table_load_struct.h +++ b/src/observer/table_load/ob_table_load_struct.h @@ -131,6 +131,7 @@ enum class ObTableLoadExeMode { struct ObTableLoadParam { +public: ObTableLoadParam() : tenant_id_(common::OB_INVALID_ID), table_id_(common::OB_INVALID_ID), @@ -191,6 +192,7 @@ struct ObTableLoadParam K_(session_count), K_(batch_size), K_(max_error_row_count), + K_(sql_mode), K_(column_count), K_(need_sort), K_(px_mode), @@ -241,6 +243,7 @@ public: schema_version_ = 0; snapshot_version_ = 0; data_version_ = 0; + cluster_version_ = 0; } bool is_valid() const { diff --git a/src/observer/table_load/ob_table_load_trans_bucket_writer.cpp b/src/observer/table_load/ob_table_load_trans_bucket_writer.cpp index 5261109ca..8cf6127e0 100644 --- a/src/observer/table_load/ob_table_load_trans_bucket_writer.cpp +++ b/src/observer/table_load/ob_table_load_trans_bucket_writer.cpp @@ -191,8 +191,9 @@ int ObTableLoadTransBucketWriter::write(int32_t session_id, ObTableLoadObjRowArr } } else { if (coordinator_ctx_->partition_calc_.is_partition_with_autoinc_ && - OB_FAIL(handle_partition_with_autoinc_identity(session_ctx, obj_rows, - trans_ctx_->ctx_->session_info_->get_sql_mode(), session_id))) { + OB_FAIL(handle_partition_with_autoinc_identity( + session_ctx, obj_rows, coordinator_ctx_->ctx_->session_info_->get_sql_mode(), + session_id))) { LOG_WARN("fail to handle partition column with autoincrement or identity", KR(ret)); } else if (OB_FAIL(write_for_partitioned(session_ctx, obj_rows))) { LOG_WARN("fail to write for partitioned", KR(ret)); diff --git a/src/observer/table_load/ob_table_load_trans_store.cpp b/src/observer/table_load/ob_table_load_trans_store.cpp index 0eeb3fd45..6346f9eb9 100644 --- a/src/observer/table_load/ob_table_load_trans_store.cpp +++ b/src/observer/table_load/ob_table_load_trans_store.cpp @@ -119,7 +119,10 @@ ObTableLoadTransStoreWriter::ObTableLoadTransStoreWriter(ObTableLoadTransStore * param_(trans_ctx_->ctx_->param_), allocator_("TLD_TSWriter"), table_data_desc_(nullptr), + lob_inrow_threshold_(0), ref_count_(0), + is_incremental_(false), + is_inc_replace_(false), is_inited_(false) { allocator_.set_tenant_id(MTL_ID()); @@ -158,16 +161,18 @@ int ObTableLoadTransStoreWriter::init() collation_type_ = trans_ctx_->ctx_->schema_.collation_type_; if (OB_FAIL(init_session_ctx_array())) { LOG_WARN("fail to init session ctx array", KR(ret)); - } else if (OB_FAIL(init_column_schemas())) { - LOG_WARN("fail to init column schemas", KR(ret)); + } else if (OB_FAIL(init_column_schemas_and_lob_info())) { + LOG_WARN("fail to init column schemas and lob info", KR(ret)); } else { + is_incremental_ = ObDirectLoadMethod::is_incremental(store_ctx_->ctx_->param_.method_); + is_inc_replace_ = (ObDirectLoadInsertMode::INC_REPLACE == store_ctx_->ctx_->param_.insert_mode_); is_inited_ = true; } } return ret; } -int ObTableLoadTransStoreWriter::init_column_schemas() +int ObTableLoadTransStoreWriter::init_column_schemas_and_lob_info() { int ret = OB_SUCCESS; const ObIArray &column_descs = store_ctx_->ctx_->schema_.column_descs_; @@ -184,6 +189,9 @@ int ObTableLoadTransStoreWriter::init_column_schemas() LOG_WARN("failed to push back column schema", K(ret), K(i), KPC(column_schema)); } } + if (OB_SUCC(ret)) { + lob_inrow_threshold_ = table_schema->get_lob_inrow_threshold(); + } return ret; } @@ -206,17 +214,11 @@ int ObTableLoadTransStoreWriter::init_session_ctx_array() } } ObDirectLoadTableStoreParam param; - param.snapshot_version_ = trans_ctx_->ctx_->ddl_param_.snapshot_version_; param.table_data_desc_ = *table_data_desc_; param.datum_utils_ = &(trans_ctx_->ctx_->schema_.datum_utils_); - param.col_descs_ = &(trans_ctx_->ctx_->schema_.column_descs_); - param.lob_column_cnt_ = trans_ctx_->ctx_->schema_.lob_column_cnt_; - param.cmp_funcs_ = &(trans_ctx_->ctx_->schema_.cmp_funcs_); param.file_mgr_ = trans_ctx_->ctx_->store_ctx_->tmp_file_mgr_; param.is_multiple_mode_ = trans_ctx_->ctx_->store_ctx_->is_multiple_mode_; param.is_fast_heap_table_ = trans_ctx_->ctx_->store_ctx_->is_fast_heap_table_; - param.online_opt_stat_gather_ = trans_ctx_->ctx_->param_.online_opt_stat_gather_; - param.px_mode_ = trans_ctx_->ctx_->param_.px_mode_; param.insert_table_ctx_ = trans_ctx_->ctx_->store_ctx_->insert_table_ctx_; param.dml_row_handler_ = trans_ctx_->ctx_->store_ctx_->error_row_handler_; for (int64_t i = 0; OB_SUCC(ret) && i < session_count; ++i) { @@ -334,7 +336,9 @@ int ObTableLoadTransStoreWriter::write(int32_t session_id, const ObNewRow &row = row_array.at(i); for (int64_t j = 0; OB_SUCC(ret) && (j < table_data_desc_->column_count_); ++j) { const ObObj &obj = row.cells_[j]; - if (OB_FAIL(session_ctx.datum_row_.storage_datums_[j].from_obj_enhance(obj))) { + if (OB_FAIL(check_support_obj(obj))) { + LOG_WARN("failed to check support obj", KR(ret), K(obj)); + } else if (OB_FAIL(session_ctx.datum_row_.storage_datums_[j].from_obj_enhance(obj))) { LOG_WARN("fail to from obj enhance", KR(ret), K(obj)); } } @@ -411,6 +415,8 @@ int ObTableLoadTransStoreWriter::cast_row(ObArenaAllocator &cast_allocator, if (!is_null_autoinc && OB_FAIL(ObTableLoadObjCaster::cast_obj(cast_obj_ctx, column_schema, row.cells_[i], out_obj))) { LOG_WARN("fail to cast obj and check", KR(ret), K(i), K(row.cells_[i])); + } else if (OB_FAIL(check_support_obj(out_obj))) { + LOG_WARN("failed to check support obj", KR(ret), K(out_obj)); } else if (OB_FAIL(datum_row.storage_datums_[i].from_obj_enhance(out_obj))) { LOG_WARN("fail to from obj enhance", KR(ret), K(out_obj)); } else if (column_schema->is_autoincrement() && @@ -497,5 +503,18 @@ int ObTableLoadTransStoreWriter::write_row_to_table_store(ObDirectLoadTableStore return ret; } +int ObTableLoadTransStoreWriter::check_support_obj(const ObObj &obj) +{ + int ret = OB_SUCCESS; + if (is_incremental_ && is_inc_replace_) { + if (obj.is_lob_storage() && OB_UNLIKELY(obj.get_data_length() > lob_inrow_threshold_)) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("incremental direct-load does not support outrow lob", KR(ret), K(obj)); + FORWARD_USER_ERROR_MSG(ret, "incremental direct-load does not support outrow lob"); + } + } + return ret; +} + } // namespace observer } // namespace oceanbase diff --git a/src/observer/table_load/ob_table_load_trans_store.h b/src/observer/table_load/ob_table_load_trans_store.h index c2f4d0626..d8621bf87 100644 --- a/src/observer/table_load/ob_table_load_trans_store.h +++ b/src/observer/table_load/ob_table_load_trans_store.h @@ -85,7 +85,7 @@ public: private: class SessionContext; int init_session_ctx_array(); - int init_column_schemas(); + int init_column_schemas_and_lob_info(); int cast_row(common::ObArenaAllocator &cast_allocator, ObDataTypeCastParams cast_params, const common::ObNewRow &row, blocksstable::ObDatumRow &datum_row, int32_t session_id); @@ -100,6 +100,7 @@ private: const common::ObTabletID &tablet_id, const table::ObTableLoadSequenceNo &seq_no, const blocksstable::ObDatumRow &datum_row); + int check_support_obj(const common::ObObj &obj); private: ObTableLoadTransStore *const trans_store_; ObTableLoadTransCtx *const trans_ctx_; @@ -126,7 +127,10 @@ private: int64_t extra_buf_size_; }; SessionContext *session_ctx_array_; + int64_t lob_inrow_threshold_; // for incremental direct load int64_t ref_count_ CACHE_ALIGNED; + bool is_incremental_; + bool is_inc_replace_; bool is_inited_; ObSchemaGetterGuard schema_guard_; }; diff --git a/src/observer/virtual_table/ob_all_virtual_memstore_info.cpp b/src/observer/virtual_table/ob_all_virtual_memstore_info.cpp index f1f08a59b..d91917640 100644 --- a/src/observer/virtual_table/ob_all_virtual_memstore_info.cpp +++ b/src/observer/virtual_table/ob_all_virtual_memstore_info.cpp @@ -178,7 +178,7 @@ int ObAllVirtualMemstoreInfo::get_next_memtable(memtable::ObMemtable *&mt) return ret; } -void ObAllVirtualMemstoreInfo::get_freeze_time_dist(const memtable::ObMtStat& mt_stat) +void ObAllVirtualMemstoreInfo::get_freeze_time_dist(const ObMtStat& mt_stat) { memset(freeze_time_dist_, 0, 128); int64_t ready_for_flush_cost_time = (mt_stat.ready_for_flush_time_ - mt_stat.frozen_time_) / 1000; @@ -212,7 +212,7 @@ int ObAllVirtualMemstoreInfo::process_curr_tenant(ObNewRow *&row) ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "mt shouldn't NULL here", K(ret), K(mt)); } else { - memtable::ObMtStat& mt_stat = mt->get_mt_stat(); + ObMtStat& mt_stat = mt->get_mt_stat(); const int64_t col_count = output_column_ids_.count(); for (int64_t i = 0; OB_SUCC(ret) && i < col_count; ++i) { uint64_t col_id = output_column_ids_.at(i); @@ -315,27 +315,7 @@ int ObAllVirtualMemstoreInfo::process_curr_tenant(ObNewRow *&row) break; case OB_APP_MIN_COLUMN_ID + 22: // freeze_state - switch (mt->get_freeze_state()) { - case ObMemtableFreezeState::INVALID: - cur_row_.cells_[i].set_varchar("INVALID"); - break; - case ObMemtableFreezeState::NOT_READY_FOR_FLUSH: - cur_row_.cells_[i].set_varchar("NOT_READY_FOR_FLUSH"); - break; - case ObMemtableFreezeState::READY_FOR_FLUSH: - cur_row_.cells_[i].set_varchar("READY_FOR_FLUSH"); - break; - case ObMemtableFreezeState::FLUSHED: - cur_row_.cells_[i].set_varchar("FLUSHED"); - break; - case ObMemtableFreezeState::RELEASED: - cur_row_.cells_[i].set_varchar("RELEASED"); - break; - default: - ret = OB_ERR_UNEXPECTED; - SERVER_LOG(WARN, "invalid freeze state", K(ret), K(col_id)); - break; - } + cur_row_.cells_[i].set_varchar(storage::TABLET_MEMTABLE_FREEZE_STATE_TO_STR(mt->get_freeze_state())); cur_row_.cells_[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); break; case OB_APP_MIN_COLUMN_ID + 23: diff --git a/src/observer/virtual_table/ob_all_virtual_memstore_info.h b/src/observer/virtual_table/ob_all_virtual_memstore_info.h index 2ad32b3be..d291bea1f 100644 --- a/src/observer/virtual_table/ob_all_virtual_memstore_info.h +++ b/src/observer/virtual_table/ob_all_virtual_memstore_info.h @@ -50,7 +50,7 @@ private: int get_next_ls(ObLS *&ls); int get_next_tablet(storage::ObTabletHandle &tablet_handle); int get_next_memtable(memtable::ObMemtable *&mt); - void get_freeze_time_dist(const memtable::ObMtStat& mt_stat); + void get_freeze_time_dist(const ObMtStat& mt_stat); private: common::ObAddr addr_; int64_t ls_id_; diff --git a/src/observer/virtual_table/ob_all_virtual_table_mgr.cpp b/src/observer/virtual_table/ob_all_virtual_table_mgr.cpp index ec4f37daa..8d70c5d6a 100644 --- a/src/observer/virtual_table/ob_all_virtual_table_mgr.cpp +++ b/src/observer/virtual_table/ob_all_virtual_table_mgr.cpp @@ -235,7 +235,7 @@ int ObAllVirtualTableMgr::process_curr_tenant(common::ObNewRow *&row) case SIZE: { int64_t size = 0; if (table->is_memtable()) { - size = static_cast(table)->get_occupied_size(); + size = static_cast(table)->get_occupied_size(); } else if (table->is_sstable()) { size = static_cast(table)->get_occupy_size(); } @@ -276,7 +276,7 @@ int ObAllVirtualTableMgr::process_curr_tenant(common::ObNewRow *&row) case IS_ACTIVE: { bool is_active = false; if (table->is_memtable()) { - is_active = static_cast(table)->is_active_memtable(); + is_active = static_cast(table)->is_active_memtable(); } cur_row_.cells_[i].set_varchar(is_active ? "YES" : "NO"); cur_row_.cells_[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); diff --git a/src/observer/virtual_table/ob_all_virtual_tenant_memstore_allocator_info.cpp b/src/observer/virtual_table/ob_all_virtual_tenant_memstore_allocator_info.cpp index feab54354..8a91653b4 100644 --- a/src/observer/virtual_table/ob_all_virtual_tenant_memstore_allocator_info.cpp +++ b/src/observer/virtual_table/ob_all_virtual_tenant_memstore_allocator_info.cpp @@ -38,7 +38,7 @@ public: ObLSID ls_id; item.protection_clock_ = handle->get_protection_clock(); item.is_active_ = handle->is_active(); - item.ls_id_ = (OB_SUCCESS == mt.get_ls_id(ls_id)) ? ls_id.id() : ObLSID::INVALID_LS_ID; + item.ls_id_ = mt.get_ls_id().id(); item.tablet_id_ = mt.get_key().tablet_id_.id(); item.scn_range_ = mt.get_scn_range(); item.mt_addr_ = &mt; diff --git a/src/share/inner_table/ob_inner_table_schema.21101_21150.cpp b/src/share/inner_table/ob_inner_table_schema.21101_21150.cpp index 4d8ea786e..43549a841 100644 --- a/src/share/inner_table/ob_inner_table_schema.21101_21150.cpp +++ b/src/share/inner_table/ob_inner_table_schema.21101_21150.cpp @@ -60,7 +60,7 @@ int ObInnerTableSchema::gv_ob_sstables_schema(ObTableSchema &table_schema) table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); if (OB_SUCC(ret)) { - if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT M.SVR_IP, M.SVR_PORT, (case M.TABLE_TYPE when 0 then 'MEMTABLE' when 1 then 'TX_DATA_MEMTABLE' when 2 then 'TX_CTX_MEMTABLE' when 3 then 'LOCK_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' when 12 then 'MINI' when 13 then 'META' when 14 then 'DDL_DUMP' when 15 then 'REMOTE_LOGICAL_MINOR' when 16 then 'DDL_MEM' when 17 then 'CO_MAJOR' when 18 then 'NORMAL_CG' when 19 then 'ROWKEY_CG' when 20 then 'DDL_MERGE' else 'INVALID' end) as TABLE_TYPE, M.TENANT_ID, M.LS_ID, M.TABLET_ID, M.CG_IDX, M.START_LOG_SCN, M.END_LOG_SCN, M.DATA_CHECKSUM, M.SIZE, M.REF, M.UPPER_TRANS_VERSION, M.IS_ACTIVE, M.CONTAIN_UNCOMMITTED_ROW FROM oceanbase.__all_virtual_table_mgr M )__"))) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT M.SVR_IP, M.SVR_PORT, (case M.TABLE_TYPE when 0 then 'MEMTABLE' when 1 then 'TX_DATA_MEMTABLE' when 2 then 'TX_CTX_MEMTABLE' when 3 then 'LOCK_MEMTABLE' when 4 then 'DIRECT_LOAD_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' when 12 then 'MINI' when 13 then 'META' when 14 then 'DDL_DUMP' when 15 then 'REMOTE_LOGICAL_MINOR' when 16 then 'DDL_MEM' when 17 then 'CO_MAJOR' when 18 then 'NORMAL_CG' when 19 then 'ROWKEY_CG' when 20 then 'DDL_MERGE' else 'INVALID' end) as TABLE_TYPE, M.TENANT_ID, M.LS_ID, M.TABLET_ID, M.CG_IDX, M.START_LOG_SCN, M.END_LOG_SCN, M.DATA_CHECKSUM, M.SIZE, M.REF, M.UPPER_TRANS_VERSION, M.IS_ACTIVE, M.CONTAIN_UNCOMMITTED_ROW FROM oceanbase.__all_virtual_table_mgr M )__"))) { LOG_ERROR("fail to set view_definition", K(ret)); } } diff --git a/src/share/inner_table/ob_inner_table_schema.28051_28100.cpp b/src/share/inner_table/ob_inner_table_schema.28051_28100.cpp index 0a497ba84..4eee2968e 100644 --- a/src/share/inner_table/ob_inner_table_schema.28051_28100.cpp +++ b/src/share/inner_table/ob_inner_table_schema.28051_28100.cpp @@ -310,7 +310,7 @@ int ObInnerTableSchema::gv_ob_sstables_ora_schema(ObTableSchema &table_schema) table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); if (OB_SUCC(ret)) { - if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT M.SVR_IP, M.SVR_PORT, (case M.TABLE_TYPE when 0 then 'MEMTABLE' when 1 then 'TX_DATA_MEMTABLE' when 2 then 'TX_CTX_MEMTABLE' when 3 then 'LOCK_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' when 12 then 'MINI' when 13 then 'META' when 14 then 'DDL_DUMP' when 15 then 'REMOTE_LOGICAL_MINOR' when 16 then 'IMC_SEGMENT' when 20 then 'DDL_MERGE' else 'INVALID' end) as TABLE_TYPE, M.LS_ID, M.TABLET_ID, M.START_LOG_SCN, M.END_LOG_SCN, M."SIZE", M.REF, M.UPPER_TRANS_VERSION, M.IS_ACTIVE, M.CONTAIN_UNCOMMITTED_ROW FROM SYS.ALL_VIRTUAL_TABLE_MGR M )__"))) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT M.SVR_IP, M.SVR_PORT, (case M.TABLE_TYPE when 0 then 'MEMTABLE' when 1 then 'TX_DATA_MEMTABLE' when 2 then 'TX_CTX_MEMTABLE' when 3 then 'LOCK_MEMTABLE' when 4 then 'DIRECT_LOAD_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' when 12 then 'MINI' when 13 then 'META' when 14 then 'DDL_DUMP' when 15 then 'REMOTE_LOGICAL_MINOR' when 16 then 'IMC_SEGMENT' when 20 then 'DDL_MERGE' else 'INVALID' end) as TABLE_TYPE, M.LS_ID, M.TABLET_ID, M.START_LOG_SCN, M.END_LOG_SCN, M."SIZE", M.REF, M.UPPER_TRANS_VERSION, M.IS_ACTIVE, M.CONTAIN_UNCOMMITTED_ROW FROM SYS.ALL_VIRTUAL_TABLE_MGR M )__"))) { LOG_ERROR("fail to set view_definition", K(ret)); } } diff --git a/src/share/inner_table/ob_inner_table_schema_def.py b/src/share/inner_table/ob_inner_table_schema_def.py index c5baf631e..a0f8cce9e 100644 --- a/src/share/inner_table/ob_inner_table_schema_def.py +++ b/src/share/inner_table/ob_inner_table_schema_def.py @@ -17771,7 +17771,7 @@ SELECT M.SVR_PORT, (case M.TABLE_TYPE when 0 then 'MEMTABLE' when 1 then 'TX_DATA_MEMTABLE' when 2 then 'TX_CTX_MEMTABLE' - when 3 then 'LOCK_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' + when 3 then 'LOCK_MEMTABLE' when 4 then 'DIRECT_LOAD_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' when 12 then 'MINI' when 13 then 'META' when 14 then 'DDL_DUMP' when 15 then 'REMOTE_LOGICAL_MINOR' when 16 then 'DDL_MEM' when 17 then 'CO_MAJOR' when 18 then 'NORMAL_CG' when 19 then 'ROWKEY_CG' when 20 then 'DDL_MERGE' @@ -55756,7 +55756,7 @@ SELECT M.SVR_PORT, (case M.TABLE_TYPE when 0 then 'MEMTABLE' when 1 then 'TX_DATA_MEMTABLE' when 2 then 'TX_CTX_MEMTABLE' - when 3 then 'LOCK_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' + when 3 then 'LOCK_MEMTABLE' when 4 then 'DIRECT_LOAD_MEMTABLE' when 10 then 'MAJOR' when 11 then 'MINOR' when 12 then 'MINI' when 13 then 'META' when 14 then 'DDL_DUMP' when 15 then 'REMOTE_LOGICAL_MINOR' when 16 then 'IMC_SEGMENT' when 20 then 'DDL_MERGE' else 'INVALID' diff --git a/src/share/ob_ddl_common.h b/src/share/ob_ddl_common.h index 68e612109..ae0756e9b 100644 --- a/src/share/ob_ddl_common.h +++ b/src/share/ob_ddl_common.h @@ -317,6 +317,7 @@ static inline bool is_direct_load_retry_err(const int ret) || ret == OB_NOT_MASTER || ret == OB_TASK_EXPIRED || ret == OB_REPLICA_NOT_READABLE + || ret == OB_TRANS_CTX_NOT_EXIST ; } diff --git a/src/share/ob_rpc_struct.cpp b/src/share/ob_rpc_struct.cpp index 594ae2d04..b4cb92470 100755 --- a/src/share/ob_rpc_struct.cpp +++ b/src/share/ob_rpc_struct.cpp @@ -9872,7 +9872,7 @@ ObRpcRemoteWriteDDLRedoLogArg::ObRpcRemoteWriteDDLRedoLogArg() int ObRpcRemoteWriteDDLRedoLogArg::init(const uint64_t tenant_id, const share::ObLSID &ls_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const int64_t task_id) { int ret = OB_SUCCESS; @@ -9916,6 +9916,106 @@ int ObRpcRemoteWriteDDLCommitLogArg::init(const uint64_t tenant_id, OB_SERIALIZE_MEMBER(ObRpcRemoteWriteDDLCommitLogArg, tenant_id_, ls_id_, table_key_, start_scn_, table_id_, execution_id_, ddl_task_id_); +ObRpcRemoteWriteDDLIncCommitLogArg::ObRpcRemoteWriteDDLIncCommitLogArg() + : tenant_id_(OB_INVALID_ID), ls_id_(), tablet_id_(), lob_meta_tablet_id_(), tx_desc_(nullptr), need_release_(false) +{} + +ObRpcRemoteWriteDDLIncCommitLogArg::~ObRpcRemoteWriteDDLIncCommitLogArg() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(release())) { + LOG_WARN("fail to release tx_desc", K(ret)); + } +} + +int ObRpcRemoteWriteDDLIncCommitLogArg::init(const uint64_t tenant_id, + const share::ObLSID &ls_id, + const common::ObTabletID tablet_id, + const common::ObTabletID lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(tenant_id_ = OB_INVALID_ID && !ls_id.is_valid() || !tablet_id.is_valid() || + OB_ISNULL(tx_desc) || !tx_desc->is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tablet id is not valid", K(ret), K(tenant_id), K(ls_id), K(tablet_id), K(lob_meta_tablet_id), KPC(tx_desc)); + } else if (OB_FAIL(release())) { + LOG_WARN("fail to release tx_desc", K(ret)); + } else { + tenant_id_ = tenant_id; + ls_id_ = ls_id; + tablet_id_ = tablet_id; + lob_meta_tablet_id_ = lob_meta_tablet_id; + tx_desc_ = tx_desc; + } + return ret; +} + +int ObRpcRemoteWriteDDLIncCommitLogArg::release() +{ + int ret = OB_SUCCESS; + if (tx_desc_ != nullptr && need_release_) { + ObTransService *tx_svc = MTL_WITH_CHECK_TENANT(ObTransService *, tenant_id_); + if (OB_ISNULL(tx_svc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("null tx service ptr", K(ret)); + } else if (OB_FAIL(tx_svc->release_tx(*tx_desc_))) { + LOG_WARN("release tx fail", K(ret)); + } else { + need_release_ = false; + tx_desc_ = nullptr; + } + } + + return ret; +} + +OB_DEF_SERIALIZE(ObRpcRemoteWriteDDLIncCommitLogArg) +{ + int ret = OB_SUCCESS; + LST_DO_CODE(OB_UNIS_ENCODE, tenant_id_, ls_id_, tablet_id_, lob_meta_tablet_id_); + if (OB_SUCC(ret)) { + if (OB_ISNULL(tx_desc_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tx_desc_ is nullptr", K(ret)); + } else { + LST_DO_CODE(OB_UNIS_ENCODE, *tx_desc_); + } + } + return ret; +} + +OB_DEF_DESERIALIZE(ObRpcRemoteWriteDDLIncCommitLogArg) +{ + int ret = OB_SUCCESS; + LST_DO_CODE(OB_UNIS_DECODE, tenant_id_, ls_id_, tablet_id_, lob_meta_tablet_id_); + if (OB_SUCC(ret)) { + ObTransService *tx_svc = nullptr; + if (OB_FAIL(release())) { + LOG_WARN("fail to release tx_desc", K(ret)); + } else if (OB_ISNULL(tx_svc = MTL_WITH_CHECK_TENANT(ObTransService *, tenant_id_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("null tx service ptr", KR(ret), K(tenant_id_)); + } else if (OB_FAIL(tx_svc->acquire_tx(buf, data_len, pos, tx_desc_))) { + LOG_WARN("acquire tx by deserialize fail", K(data_len), K(pos), KR(ret)); + } else { + need_release_ = true; + } + } + return ret; +} + +OB_DEF_SERIALIZE_SIZE(ObRpcRemoteWriteDDLIncCommitLogArg) +{ + int64_t len = 0; + LST_DO_CODE(OB_UNIS_ADD_LEN, tenant_id_, ls_id_, tablet_id_, lob_meta_tablet_id_); + if (tx_desc_ != nullptr) { + LST_DO_CODE(OB_UNIS_ADD_LEN, *tx_desc_); + } + return len; +} + +OB_SERIALIZE_MEMBER(ObRpcRemoteWriteDDLIncCommitLogRes, tx_result_); bool ObCheckLSCanOfflineArg::is_valid() const { diff --git a/src/share/ob_rpc_struct.h b/src/share/ob_rpc_struct.h index 0394390c2..1d01102f0 100755 --- a/src/share/ob_rpc_struct.h +++ b/src/share/ob_rpc_struct.h @@ -56,6 +56,7 @@ #include "share/ob_tenant_info_proxy.h"//ObAllTenantInfo #include "share/ob_alive_server_tracer.h"//ServerAddr #include "storage/blocksstable/ob_block_sstable_struct.h" +#include "storage/ddl/ob_ddl_struct.h" #include "storage/tx/ob_trans_define.h" #include "share/unit/ob_unit_info.h" //ObUnit* #include "share/backup/ob_backup_clean_struct.h" @@ -10042,16 +10043,15 @@ public: ~ObRpcRemoteWriteDDLRedoLogArg() = default; int init(const uint64_t tenant_id, const share::ObLSID &ls_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const int64_t task_id); bool is_valid() const { return tenant_id_ != OB_INVALID_ID && ls_id_.is_valid() && redo_info_.is_valid() && task_id_ != 0; } TO_STRING_KV(K_(tenant_id), K(ls_id_), K_(redo_info), K(task_id_)); public: uint64_t tenant_id_; share::ObLSID ls_id_; - blocksstable::ObDDLMacroBlockRedoInfo redo_info_; + storage::ObDDLMacroBlockRedoInfo redo_info_; int64_t task_id_; - private: DISALLOW_COPY_AND_ASSIGN(ObRpcRemoteWriteDDLRedoLogArg); }; @@ -10084,6 +10084,47 @@ private: DISALLOW_COPY_AND_ASSIGN(ObRpcRemoteWriteDDLCommitLogArg); }; +struct ObRpcRemoteWriteDDLIncCommitLogArg final +{ + OB_UNIS_VERSION(1); +public: + ObRpcRemoteWriteDDLIncCommitLogArg(); + ~ObRpcRemoteWriteDDLIncCommitLogArg(); + int init(const uint64_t tenant_id, + const share::ObLSID &ls_id, + const common::ObTabletID tablet_id, + const common::ObTabletID lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc); + int release(); + bool is_valid() const + { + return tenant_id_ != OB_INVALID_ID && ls_id_.is_valid() && tablet_id_.is_valid() && + OB_NOT_NULL(tx_desc_) && tx_desc_->is_valid(); + } + TO_STRING_KV(K_(tenant_id), K_(ls_id), K_(tablet_id), K_(lob_meta_tablet_id), KP_(tx_desc)); +public: + uint64_t tenant_id_; + share::ObLSID ls_id_; + common::ObTabletID tablet_id_; + common::ObTabletID lob_meta_tablet_id_; + transaction::ObTxDesc *tx_desc_; + bool need_release_; +private: + DISALLOW_COPY_AND_ASSIGN(ObRpcRemoteWriteDDLIncCommitLogArg); +}; + +struct ObRpcRemoteWriteDDLIncCommitLogRes final +{ + OB_UNIS_VERSION(1); +public: + ObRpcRemoteWriteDDLIncCommitLogRes() : tx_result_() {} + ~ObRpcRemoteWriteDDLIncCommitLogRes() {} + TO_STRING_KV(K_(tx_result)); +public: + transaction::ObTxExecResult tx_result_; +private: + DISALLOW_COPY_AND_ASSIGN(ObRpcRemoteWriteDDLIncCommitLogRes); +}; struct ObCheckLSCanOfflineArg { diff --git a/src/share/ob_srv_rpc_proxy.h b/src/share/ob_srv_rpc_proxy.h index 1774d1a11..fab5e916a 100755 --- a/src/share/ob_srv_rpc_proxy.h +++ b/src/share/ob_srv_rpc_proxy.h @@ -211,6 +211,7 @@ public: RPC_S(PR4 admin_update_lock_op, OB_UPDATE_OBJ_LOCK, (transaction::tablelock::ObAdminUpdateLockOpArg)); RPC_S(PR5 remote_write_ddl_redo_log, OB_REMOTE_WRITE_DDL_REDO_LOG, (obrpc::ObRpcRemoteWriteDDLRedoLogArg)); RPC_S(PR5 remote_write_ddl_commit_log, OB_REMOTE_WRITE_DDL_COMMIT_LOG, (obrpc::ObRpcRemoteWriteDDLCommitLogArg), obrpc::Int64); + RPC_S(PR5 remote_write_ddl_inc_commit_log, OB_REMOTE_WRITE_DDL_INC_COMMIT_LOG, (obrpc::ObRpcRemoteWriteDDLIncCommitLogArg), ObRpcRemoteWriteDDLIncCommitLogRes); RPC_S(PR5 check_ls_can_offline, OB_CHECK_LS_CAN_OFFLINE, (obrpc::ObCheckLSCanOfflineArg)); RPC_S(PR5 clean_sequence_cache, obrpc::OB_CLEAN_SEQUENCE_CACHE, (obrpc::UInt64)); RPC_S(PR5 register_tx_data, OB_REGISTER_TX_DATA, (ObRegisterTxDataArg), ObRegisterTxDataResult); diff --git a/src/share/table/ob_table_load_define.cpp b/src/share/table/ob_table_load_define.cpp index c3a5363e3..139fe7422 100644 --- a/src/share/table/ob_table_load_define.cpp +++ b/src/share/table/ob_table_load_define.cpp @@ -48,7 +48,7 @@ OB_SERIALIZE_MEMBER(ObTableLoadResultInfo, skipped_, warnings_); -OB_SERIALIZE_MEMBER(ObTableLoadSequenceNo, sequence_no_); +OB_SERIALIZE_MEMBER_SIMPLE(ObTableLoadSequenceNo, sequence_no_); } // namespace table } // namespace oceanbase diff --git a/src/share/table/ob_table_load_sql_statistics.cpp b/src/share/table/ob_table_load_sql_statistics.cpp index 8f56ad9cc..5aaa0fdee 100644 --- a/src/share/table/ob_table_load_sql_statistics.cpp +++ b/src/share/table/ob_table_load_sql_statistics.cpp @@ -13,6 +13,7 @@ #define USING_LOG_PREFIX CLIENT #include "ob_table_load_sql_statistics.h" +#include "lib/oblog/ob_log_module.h" namespace oceanbase { @@ -38,6 +39,31 @@ void ObTableLoadSqlStatistics::reset() allocator_.reset(); } +int ObTableLoadSqlStatistics::create(int64_t column_count) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(column_count <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invald args", KR(ret), K(column_count)); + } else if (OB_UNLIKELY(!is_empty())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected not empty", KR(ret)); + } else { + ObOptTableStat *table_stat = nullptr; + ObOptOSGColumnStat *osg_col_stat = nullptr; + if (OB_FAIL(allocate_table_stat(table_stat))) { + LOG_WARN("fail to allocate table stat", KR(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < column_count; ++i) { + ObOptOSGColumnStat *osg_col_stat = nullptr; + if (OB_FAIL(allocate_col_stat(osg_col_stat))) { + LOG_WARN("fail to allocate col stat", KR(ret)); + } + } + } + return ret; +} + int ObTableLoadSqlStatistics::allocate_table_stat(ObOptTableStat *&table_stat) { int ret = OB_SUCCESS; @@ -82,98 +108,189 @@ int ObTableLoadSqlStatistics::allocate_col_stat(ObOptOSGColumnStat *&col_stat) return ret; } -int ObTableLoadSqlStatistics::add(const ObTableLoadSqlStatistics& other) +int ObTableLoadSqlStatistics::merge(const ObTableLoadSqlStatistics &other) { int ret = OB_SUCCESS; - for (int64_t i = 0; OB_SUCC(ret)&& i < other.table_stat_array_.count(); ++i) { - ObOptTableStat *table_stat = other.table_stat_array_.at(i); - if (table_stat != nullptr) { + if (is_empty()) { + for (int64_t i = 0; OB_SUCC(ret) && i < other.table_stat_array_.count(); ++i) { + ObOptTableStat *table_stat = other.table_stat_array_.at(i); ObOptTableStat *copied_table_stat = nullptr; - int64_t size = table_stat->size(); - char *new_buf = nullptr; - if (OB_ISNULL(new_buf = static_cast(allocator_.alloc(size)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "fail to allocate buffer", KR(ret), K(size)); - } else if (OB_FAIL(table_stat->deep_copy(new_buf, size, copied_table_stat))) { - OB_LOG(WARN, "fail to copy table stat", KR(ret)); - } else if (OB_FAIL(table_stat_array_.push_back(copied_table_stat))) { - OB_LOG(WARN, "fail to add table stat", KR(ret)); - } - if (OB_FAIL(ret)) { - if (copied_table_stat != nullptr) { - copied_table_stat->~ObOptTableStat(); - copied_table_stat = nullptr; + if (OB_ISNULL(table_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table stat is null", KR(ret), K(i), K(other.table_stat_array_)); + } else { + int64_t size = table_stat->size(); + char *buf = nullptr; + if (OB_ISNULL(buf = static_cast(allocator_.alloc(size)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate buffer", KR(ret), K(size)); + } else if (OB_FAIL(table_stat->deep_copy(buf, size, copied_table_stat))) { + LOG_WARN("fail to copy table stat", KR(ret)); + } else if (OB_FAIL(table_stat_array_.push_back(copied_table_stat))) { + LOG_WARN("fail to add table stat", KR(ret)); } - if(new_buf != nullptr) { - allocator_.free(new_buf); - new_buf = nullptr; + if (OB_FAIL(ret)) { + if (copied_table_stat != nullptr) { + copied_table_stat->~ObOptTableStat(); + copied_table_stat = nullptr; + } + if (buf != nullptr) { + allocator_.free(buf); + buf = nullptr; + } } } } - } - for (int64_t i = 0; OB_SUCC(ret)&& i < other.col_stat_array_.count(); ++i) { - ObOptOSGColumnStat *col_stat = other.col_stat_array_.at(i); - ObOptOSGColumnStat *copied_col_stat = nullptr; - if (OB_ISNULL(col_stat)) { - ret = OB_ERR_UNEXPECTED; - OB_LOG(WARN, "get unexpected null"); - } else if (OB_ISNULL(copied_col_stat = ObOptOSGColumnStat::create_new_osg_col_stat(allocator_))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "failed to create new col stat"); - } else if (OB_FAIL(copied_col_stat->deep_copy(*col_stat))) { - OB_LOG(WARN, "fail to copy col stat", KR(ret)); - } else if (OB_FAIL(col_stat_array_.push_back(copied_col_stat))) { - OB_LOG(WARN, "fail to add col stat", KR(ret)); + for (int64_t i = 0; OB_SUCC(ret) && i < other.col_stat_array_.count(); ++i) { + ObOptOSGColumnStat *col_stat = other.col_stat_array_.at(i); + ObOptOSGColumnStat *copied_col_stat = nullptr; + if (OB_ISNULL(col_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected col stat is null", KR(ret), K(i), K(other.col_stat_array_)); + } else if (OB_FAIL(allocate_col_stat(copied_col_stat))) { + LOG_WARN("fail to allocate col stat", KR(ret)); + } else if (OB_FAIL(copied_col_stat->deep_copy(*col_stat))) { + LOG_WARN("fail to copy col stat", KR(ret)); + } } - if (OB_FAIL(ret)) { - if (copied_col_stat != nullptr) { - copied_col_stat->~ObOptOSGColumnStat(); - copied_col_stat = nullptr; + } else { + if (OB_UNLIKELY(other.table_stat_array_.count() != table_stat_array_.count() || + other.col_stat_array_.count() != col_stat_array_.count())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid args", KR(ret), KPC(this), K(other)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < other.table_stat_array_.count(); ++i) { + ObOptTableStat *table_stat = other.table_stat_array_.at(i); + if (OB_ISNULL(table_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table stat is null", KR(ret), K(i), K(other.table_stat_array_)); + } else if (OB_FAIL(table_stat_array_.at(i)->merge_table_stat(*table_stat))) { + LOG_WARN("fail to merge table stat", KR(ret)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < other.col_stat_array_.count(); ++i) { + ObOptOSGColumnStat *osg_col_stat = other.col_stat_array_.at(i); + if (OB_ISNULL(osg_col_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected col stat is null", KR(ret), K(i), K(other.col_stat_array_)); + } + // ObOptOSGColumnStat的序列化结果只序列化里面的ObOptColumnStat, + // 需要调用ObOptColumnStat的merge函数 + else if (OB_FAIL( + col_stat_array_.at(i)->col_stat_->merge_column_stat(*osg_col_stat->col_stat_))) { + LOG_WARN("fail to merge col stat", KR(ret)); } } } return ret; } -int ObTableLoadSqlStatistics::get_table_stat_array(ObIArray &table_stat_array) const +int ObTableLoadSqlStatistics::get_table_stat(int64_t idx, ObOptTableStat *&table_stat) +{ + int ret = OB_SUCCESS; + table_stat = nullptr; + if (OB_UNLIKELY(idx >= table_stat_array_.count())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid args", KR(ret), K(idx), K(table_stat_array_.count())); + } else { + table_stat = table_stat_array_.at(idx); + } + return ret; +} + +int ObTableLoadSqlStatistics::get_col_stat(int64_t idx, ObOptOSGColumnStat *&osg_col_stat) +{ + int ret = OB_SUCCESS; + osg_col_stat = nullptr; + if (OB_UNLIKELY(idx >= col_stat_array_.count())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid args", KR(ret), K(idx), K(col_stat_array_.count())); + } else { + osg_col_stat = col_stat_array_.at(idx); + } + return ret; +} + +int ObTableLoadSqlStatistics::get_table_stat_array(ObIArray &table_stat_array) const { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < table_stat_array_.count(); ++i) { - if (OB_ISNULL(table_stat_array_.at(i))) { + ObOptTableStat *table_stat = nullptr; + if (OB_ISNULL(table_stat = table_stat_array_.at(i))) { ret = OB_ERR_UNEXPECTED; - OB_LOG(WARN, "get unexpected null"); - } else if (OB_FAIL(table_stat_array.push_back(table_stat_array_.at(i)))) { - OB_LOG(WARN, "failed to push back col stat"); + LOG_WARN("unexpected table stat is null", KR(ret), K(i), K(table_stat_array_)); + } else if (OB_FAIL(table_stat_array.push_back(table_stat))) { + LOG_WARN("fail to push back table stat", KR(ret)); } } return ret; } -int ObTableLoadSqlStatistics::get_col_stat_array(ObIArray &col_stat_array) const +int ObTableLoadSqlStatistics::get_col_stat_array(ObIArray &col_stat_array) const { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < col_stat_array_.count(); ++i) { - if (OB_ISNULL(col_stat_array_.at(i))) { + ObOptOSGColumnStat *osg_col_stat = nullptr; + if (OB_ISNULL(osg_col_stat = col_stat_array_.at(i))) { ret = OB_ERR_UNEXPECTED; - OB_LOG(WARN, "get unexpected null"); - } else if (OB_FAIL(col_stat_array_.at(i)->set_min_max_datum_to_obj())) { - OB_LOG(WARN, "failed to persistence min max"); - } else if (OB_FAIL(col_stat_array.push_back(col_stat_array_.at(i)->col_stat_))) { - OB_LOG(WARN, "failed to push back col stat"); + LOG_WARN("unexpected col stat is null", KR(ret), K(i), K(col_stat_array_)); + } else if (OB_FAIL(osg_col_stat->set_min_max_datum_to_obj())) { + LOG_WARN("fail to persistence min max", KR(ret)); + } else if (OB_FAIL(col_stat_array.push_back(osg_col_stat->col_stat_))) { + LOG_WARN("fail to push back col stat", KR(ret)); } } return ret; } -int ObTableLoadSqlStatistics::persistence_col_stats() +int ObTableLoadSqlStatistics::get_table_stats(TabStatIndMap &table_stats) const { int ret = OB_SUCCESS; - for (int64_t i = 0; OB_SUCC(ret) && i < col_stat_array_.count(); ++i) { - if (OB_ISNULL(col_stat_array_.at(i))) { + const uint64_t tenant_id = MTL_ID(); + ObOptTableStat *table_stat = nullptr; + for (int64_t i = 0; OB_SUCC(ret) && i < table_stat_array_.count(); ++i) { + if (OB_ISNULL(table_stat = table_stat_array_.at(i))) { ret = OB_ERR_UNEXPECTED; - OB_LOG(WARN, "get unexpected null"); - } else if (OB_FAIL(col_stat_array_.at(i)->set_min_max_datum_to_obj())) { - OB_LOG(WARN, "failed to persistence min max"); + LOG_WARN("unexpected table stat is null", KR(ret)); + } else { + ObOptTableStat::Key key(tenant_id, + table_stat->get_table_id(), + table_stat->get_partition_id()); + if (OB_FAIL(table_stats.set_refactored(key, table_stat))) { + LOG_WARN("fail to set table stat", KR(ret), K(key), KPC(table_stat)); + if (OB_HASH_EXIST == ret) { + ret = OB_ENTRY_EXIST; + } + } + } + } + return ret; +} + +int ObTableLoadSqlStatistics::get_col_stats(ColStatIndMap &col_stats) const +{ + int ret = OB_SUCCESS; + const uint64_t tenant_id = MTL_ID(); + ObOptOSGColumnStat *osg_col_stat = nullptr; + ObOptColumnStat *col_stat = nullptr; + for (int64_t i = 0; OB_SUCC(ret) && i < col_stat_array_.count(); ++i) { + if (OB_ISNULL(osg_col_stat = col_stat_array_.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected osg col stat is null", KR(ret)); + } else if (OB_ISNULL(col_stat = osg_col_stat->col_stat_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected col stat is null", KR(ret)); + } else { + ObOptColumnStat::Key key(tenant_id, + col_stat->get_table_id(), + col_stat->get_partition_id(), + col_stat->get_column_id()); + if (OB_FAIL(col_stats.set_refactored(key, col_stat))) { + LOG_WARN("fail to set col stat", KR(ret), K(key), KPC(col_stat)); + if (OB_HASH_EXIST == ret) { + ret = OB_ENTRY_EXIST; + } + } } } return ret; @@ -275,5 +392,5 @@ OB_DEF_SERIALIZE_SIZE(ObTableLoadSqlStatistics) return len; } -} // namespace table -} // namespace oceanbase +} // namespace table +} // namespace oceanbase diff --git a/src/share/table/ob_table_load_sql_statistics.h b/src/share/table/ob_table_load_sql_statistics.h index 9eb963bf8..5e0b4965d 100644 --- a/src/share/table/ob_table_load_sql_statistics.h +++ b/src/share/table/ob_table_load_sql_statistics.h @@ -12,9 +12,10 @@ #pragma once -#include "share/stat/ob_opt_table_stat.h" #include "share/stat/ob_opt_column_stat.h" #include "share/stat/ob_opt_osg_column_stat.h" +#include "share/stat/ob_opt_table_stat.h" +#include "share/stat/ob_stat_define.h" namespace oceanbase { @@ -33,17 +34,21 @@ public: } ~ObTableLoadSqlStatistics() { reset(); } void reset(); - bool is_empty() const - { - return table_stat_array_.count() == 0 || col_stat_array_.count() == 0; - } + OB_INLINE int64_t get_table_stat_count() const { return table_stat_array_.count(); } + OB_INLINE int64_t get_col_stat_count() const { return col_stat_array_.count(); } + OB_INLINE bool is_empty() const { return table_stat_array_.empty() && col_stat_array_.empty(); } + int create(int64_t column_count); + int merge(const ObTableLoadSqlStatistics &other); + int get_table_stat(int64_t idx, ObOptTableStat *&table_stat); + int get_col_stat(int64_t idx, ObOptOSGColumnStat *&osg_col_stat); + int get_table_stat_array(ObIArray &table_stat_array) const; + int get_col_stat_array(ObIArray &col_stat_array) const; + int get_table_stats(TabStatIndMap &table_stats) const; + int get_col_stats(ColStatIndMap &col_stats) const; + TO_STRING_KV(K_(col_stat_array), K_(table_stat_array)); +private: int allocate_table_stat(ObOptTableStat *&table_stat); int allocate_col_stat(ObOptOSGColumnStat *&col_stat); - int add(const ObTableLoadSqlStatistics& other); - int get_table_stat_array(ObIArray &table_stat_array) const; - int get_col_stat_array(ObIArray &col_stat_array) const; - int persistence_col_stats(); - TO_STRING_KV(K_(col_stat_array), K_(table_stat_array)); public: common::ObArray table_stat_array_; common::ObArray col_stat_array_; diff --git a/src/share/throttle/ob_share_throttle_define.cpp b/src/share/throttle/ob_share_throttle_define.cpp index 9107a6ff8..c79a4a0f6 100644 --- a/src/share/throttle/ob_share_throttle_define.cpp +++ b/src/share/throttle/ob_share_throttle_define.cpp @@ -88,7 +88,6 @@ void FakeAllocatorForTxShare::adaptive_update_limit(const int64_t tenant_id, usable_remain_memory = std::max(usable_remain_memory, remain_memory - MAX_UNUSABLE_MEMORY); } - is_updated = false; if (holding_size + usable_remain_memory < config_specify_resource_limit) { resource_limit = holding_size + usable_remain_memory; diff --git a/src/sql/code_generator/ob_static_engine_cg.cpp b/src/sql/code_generator/ob_static_engine_cg.cpp index 0d7247577..0d8aead82 100644 --- a/src/sql/code_generator/ob_static_engine_cg.cpp +++ b/src/sql/code_generator/ob_static_engine_cg.cpp @@ -6378,8 +6378,11 @@ int ObStaticEngineCG::generate_spec(ObLogInsert &op, spec.table_location_uncertain_ = op.is_table_location_uncertain(); // row-movement target table spec.is_pdml_update_split_ = op.is_pdml_update_split(); if (GCONF._ob_enable_direct_load) { + const ObGlobalHint &global_hint = op.get_plan()->get_optimizer_context().get_global_hint(); spec.plan_->set_append_table_id(op.get_append_table_id()); - spec.plan_->set_enable_append(op.get_plan()->get_optimizer_context().get_global_hint().has_append()); + spec.plan_->set_enable_append(global_hint.has_direct_load()); + spec.plan_->set_enable_inc_direct_load(global_hint.has_inc_direct_load()); + spec.plan_->set_enable_replace(global_hint.has_replace()); } int64_t partition_expr_idx = OB_INVALID_INDEX; if (OB_FAIL(get_pdml_partition_id_column_idx(spec.get_child(0)->output_, partition_expr_idx))) { diff --git a/src/sql/engine/cmd/ob_load_data_direct_impl.cpp b/src/sql/engine/cmd/ob_load_data_direct_impl.cpp index dc36c97e0..2f41c7326 100644 --- a/src/sql/engine/cmd/ob_load_data_direct_impl.cpp +++ b/src/sql/engine/cmd/ob_load_data_direct_impl.cpp @@ -57,7 +57,6 @@ ObLoadDataDirectImpl::LoadExecuteParam::LoadExecuteParam() : tenant_id_(OB_INVALID_ID), database_id_(OB_INVALID_ID), table_id_(OB_INVALID_ID), - sql_mode_(0), parallel_(0), thread_count_(0), batch_row_count_(0), @@ -66,7 +65,9 @@ ObLoadDataDirectImpl::LoadExecuteParam::LoadExecuteParam() online_opt_stat_gather_(false), max_error_rows_(-1), ignore_row_num_(-1), - dup_action_(ObLoadDupActionType::LOAD_INVALID_MODE) + dup_action_(ObLoadDupActionType::LOAD_INVALID_MODE), + method_(ObDirectLoadMethod::INVALID_METHOD), + insert_mode_(ObDirectLoadInsertMode::INVALID_INSERT_MODE) { store_column_idxs_.set_tenant_id(MTL_ID()); } @@ -77,8 +78,19 @@ bool ObLoadDataDirectImpl::LoadExecuteParam::is_valid() const OB_INVALID_ID != table_id_ && !database_name_.empty() && !table_name_.empty() && !combined_name_.empty() && parallel_ > 0 && thread_count_ > 0 && batch_row_count_ > 0 && data_mem_usage_limit_ > 0 && max_error_rows_ >= 0 && ignore_row_num_ >= 0 && - ObLoadDupActionType::LOAD_INVALID_MODE != dup_action_ && data_access_param_.is_valid() && - !store_column_idxs_.empty(); + ObLoadDupActionType::LOAD_INVALID_MODE != dup_action_ && + ObDirectLoadMethod::is_type_valid(method_) && + ObDirectLoadInsertMode::is_type_valid(insert_mode_) && + (storage::ObDirectLoadMethod::is_full(method_) + ? storage::ObDirectLoadInsertMode::is_valid_for_full_method(insert_mode_) + : true) && + (storage::ObDirectLoadMethod::is_incremental(method_) + ? storage::ObDirectLoadInsertMode::is_valid_for_incremental_method(insert_mode_) + : true) && + (storage::ObDirectLoadInsertMode::INC_REPLACE == insert_mode_ + ? sql::ObLoadDupActionType::LOAD_REPLACE == dup_action_ + : true) && + data_access_param_.is_valid() && !store_column_idxs_.empty(); } /** @@ -1831,10 +1843,10 @@ int ObLoadDataDirectImpl::execute(ObExecContext &ctx, ObLoadDataStmt &load_stmt) } if (OB_SUCC(ret)) { - ObTableLoadResultInfo result_info; - if (OB_FAIL(direct_loader_.commit(result_info))) { + if (OB_FAIL(direct_loader_.commit())) { LOG_WARN("fail to commit direct loader", KR(ret)); } else { + const ObTableLoadResultInfo &result_info = direct_loader_.get_result_info(); ObPhysicalPlanCtx *phy_plan_ctx = ctx.get_physical_plan_ctx(); phy_plan_ctx->set_affected_rows(result_info.rows_affected_); phy_plan_ctx->set_row_matched_count(total_line_count); @@ -1889,31 +1901,36 @@ int ObLoadDataDirectImpl::init_execute_param() hint_batch_size > 0 ? hint_batch_size : DEFAULT_BUFFERRED_ROW_COUNT; } } - // need_sort_ + // direct load hint if (OB_SUCC(ret)) { - int64_t enable_direct = 0; - int64_t hint_need_sort = 0; - if (OB_FAIL(hint.get_value(ObLoadDataHint::ENABLE_DIRECT, enable_direct))) { - LOG_WARN("fail to get value of ENABLE_DIRECT", K(ret)); - } else if (OB_FAIL(hint.get_value(ObLoadDataHint::NEED_SORT, hint_need_sort))) { - LOG_WARN("fail to get value of NEED_SORT", KR(ret), K(hint)); - } else if (enable_direct != 0) { - execute_param_.need_sort_ = hint_need_sort > 0 ? true : false; - } else { + const ObDirectLoadHint &direct_load_hint = hint.get_direct_load_hint(); + if (direct_load_hint.is_enable()) { + execute_param_.need_sort_ = direct_load_hint.need_sort(); + execute_param_.max_error_rows_ = direct_load_hint.get_max_error_row_count(); + execute_param_.method_ = + (direct_load_hint.is_inc_direct_load() ? ObDirectLoadMethod::INCREMENTAL + : ObDirectLoadMethod::FULL); + execute_param_.insert_mode_ = ObDirectLoadInsertMode::NORMAL; + if (OB_UNLIKELY(direct_load_hint.is_inc_load_method())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc load method not supported", KR(ret), K(direct_load_hint)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "inc load method in direct load is"); + } else if (direct_load_hint.is_inc_replace_load_method()) { + if (OB_UNLIKELY(ObLoadDupActionType::LOAD_STOP_ON_DUP != load_args.dupl_action_)) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("replace or ignore for inc_replace load method not supported", KR(ret), + K(direct_load_hint), K(load_args.dupl_action_)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "replace or ignore for inc_replace load method in direct load is"); + } else { + execute_param_.dup_action_ = ObLoadDupActionType::LOAD_REPLACE; // rewrite dup action + execute_param_.insert_mode_ = ObDirectLoadInsertMode::INC_REPLACE; + } + } + } else { // append execute_param_.need_sort_ = true; - } - } - // sql_mode_ - if (OB_SUCC(ret)) { - ObSQLSessionInfo *session = nullptr; - uint64_t sql_mode; - if (OB_ISNULL(session = ctx_->get_my_session())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("session is null", KR(ret)); - } else if (OB_FAIL(session->get_sys_variable(SYS_VAR_SQL_MODE, sql_mode))) { - LOG_WARN("fail to get sys variable", K(ret)); - } else { - execute_param_.sql_mode_ = sql_mode; + execute_param_.max_error_rows_ = 0; + execute_param_.method_ = ObDirectLoadMethod::FULL; + execute_param_.insert_mode_ = ObDirectLoadInsertMode::NORMAL; } } // online_opt_stat_gather_ @@ -1934,23 +1951,6 @@ int ObLoadDataDirectImpl::init_execute_param() execute_param_.online_opt_stat_gather_ = false; } } - // max_error_rows_ - if (OB_SUCC(ret)) { - int64_t append = 0; - int64_t enable_direct = 0; - int64_t hint_error_rows = 0; - if (OB_FAIL(hint.get_value(ObLoadDataHint::APPEND, append))) { - LOG_WARN("fail to get value of APPEND", K(ret)); - } else if (OB_FAIL(hint.get_value(ObLoadDataHint::ENABLE_DIRECT, enable_direct))) { - LOG_WARN("fail to get value of ENABLE_DIRECT", K(ret)); - } else if (OB_FAIL(hint.get_value(ObLoadDataHint::ERROR_ROWS, hint_error_rows))) { - LOG_WARN("fail to get value of ERROR_ROWS", KR(ret), K(hint)); - } else if (enable_direct != 0) { - execute_param_.max_error_rows_ = hint_error_rows; - } else { - execute_param_.max_error_rows_ = 0; - } - } // data_access_param_ if (OB_SUCC(ret)) { DataAccessParam &data_access_param = execute_param_.data_access_param_; @@ -2040,11 +2040,10 @@ int ObLoadDataDirectImpl::init_execute_context() load_param.column_count_ = execute_param_.store_column_idxs_.count(); load_param.need_sort_ = execute_param_.need_sort_; load_param.dup_action_ = execute_param_.dup_action_; - load_param.sql_mode_ = execute_param_.sql_mode_; load_param.px_mode_ = false; load_param.online_opt_stat_gather_ = execute_param_.online_opt_stat_gather_; - load_param.method_ = ObDirectLoadMethod::FULL; - load_param.insert_mode_ = ObDirectLoadInsertMode::NORMAL; + load_param.method_ = execute_param_.method_; + load_param.insert_mode_ = execute_param_.insert_mode_; if (OB_FAIL(direct_loader_.init(load_param, execute_param_.store_column_idxs_, &execute_ctx_.exec_ctx_))) { LOG_WARN("fail to init direct loader", KR(ret)); diff --git a/src/sql/engine/cmd/ob_load_data_direct_impl.h b/src/sql/engine/cmd/ob_load_data_direct_impl.h index a77c7092b..27b7168fc 100644 --- a/src/sql/engine/cmd/ob_load_data_direct_impl.h +++ b/src/sql/engine/cmd/ob_load_data_direct_impl.h @@ -23,6 +23,7 @@ #include "common/storage/ob_io_device.h" #include "observer/table_load/ob_table_load_exec_ctx.h" #include "observer/table_load/ob_table_load_instance.h" +#include "storage/direct_load/ob_direct_load_struct.h" namespace oceanbase { @@ -75,14 +76,27 @@ private: public: LoadExecuteParam(); bool is_valid() const; - TO_STRING_KV(K_(tenant_id), K_(database_id), K_(table_id), K_(combined_name), K_(parallel), K_(thread_count), - K_(batch_row_count), K_(data_mem_usage_limit), K_(need_sort), K_(online_opt_stat_gather), - K_(max_error_rows), K_(ignore_row_num), K_(data_access_param), K_(store_column_idxs)); + TO_STRING_KV(K_(tenant_id), + K_(database_id), + K_(table_id), + K_(combined_name), + K_(parallel), + K_(thread_count), + K_(batch_row_count), + K_(data_mem_usage_limit), + K_(need_sort), + K_(online_opt_stat_gather), + K_(max_error_rows), + K_(ignore_row_num), + K_(dup_action), + "method", storage::ObDirectLoadMethod::get_type_string(method_), + "insert_mode", storage::ObDirectLoadInsertMode::get_type_string(insert_mode_), + K_(data_access_param), + K_(store_column_idxs)); public: uint64_t tenant_id_; uint64_t database_id_; uint64_t table_id_; - uint64_t sql_mode_; common::ObString database_name_; common::ObString table_name_; common::ObString combined_name_; // database name + table name @@ -95,6 +109,8 @@ private: int64_t max_error_rows_; // max allowed error rows int64_t ignore_row_num_; // number of rows to ignore per file sql::ObLoadDupActionType dup_action_; + storage::ObDirectLoadMethod::Type method_; + storage::ObDirectLoadInsertMode::Type insert_mode_; DataAccessParam data_access_param_; common::ObArray store_column_idxs_; // Mapping of stored columns to source data columns }; diff --git a/src/sql/engine/cmd/ob_load_data_executor.cpp b/src/sql/engine/cmd/ob_load_data_executor.cpp index 97d80b6be..5aebbde9a 100644 --- a/src/sql/engine/cmd/ob_load_data_executor.cpp +++ b/src/sql/engine/cmd/ob_load_data_executor.cpp @@ -27,16 +27,17 @@ namespace sql int ObLoadDataExecutor::check_is_direct_load(ObTableDirectInsertCtx &ctx, const ObLoadDataHint &load_hint) { int ret = OB_SUCCESS; - int64_t enable_direct = 0; - int64_t append = 0; - if (OB_FAIL(load_hint.get_value(ObLoadDataHint::ENABLE_DIRECT, enable_direct))) { - LOG_WARN("fail to get value of ENABLE_DIRECT", K(ret)); - } else if (OB_FAIL(load_hint.get_value(ObLoadDataHint::APPEND, append))) { - LOG_WARN("fail to get value of APPEND", K(ret)); - } else if ((enable_direct != 0 || append != 0) && GCONF._ob_enable_direct_load) { - ctx.set_is_direct(true); - } else { - ctx.set_is_direct(false); + ctx.set_is_direct(false); + if (GCONF._ob_enable_direct_load) { + const bool enable_direct = load_hint.get_direct_load_hint().is_enable(); + int64_t append = 0; + if (enable_direct) { // direct + ctx.set_is_direct(true); + } else if (OB_FAIL(load_hint.get_value(ObLoadDataHint::APPEND, append))) { + LOG_WARN("fail to get APPEND", KR(ret)); + } else if (append != 0) { // append + ctx.set_is_direct(true); + } } LOG_INFO("check load data is direct done.", K(ctx.get_is_direct())); return ret; diff --git a/src/sql/engine/cmd/ob_table_direct_insert_ctx.cpp b/src/sql/engine/cmd/ob_table_direct_insert_ctx.cpp index bbfa91877..b9d24cbd8 100644 --- a/src/sql/engine/cmd/ob_table_direct_insert_ctx.cpp +++ b/src/sql/engine/cmd/ob_table_direct_insert_ctx.cpp @@ -34,8 +34,12 @@ ObTableDirectInsertCtx::~ObTableDirectInsertCtx() destroy(); } -int ObTableDirectInsertCtx::init(ObExecContext *exec_ctx, - const uint64_t table_id, const int64_t parallel) +int ObTableDirectInsertCtx::init( + ObExecContext *exec_ctx, + const uint64_t table_id, + const int64_t parallel, + const bool is_incremental, + const bool enable_inc_replace) { int ret = OB_SUCCESS; if (IS_INIT) { @@ -57,7 +61,11 @@ int ObTableDirectInsertCtx::init(ObExecContext *exec_ctx, load_exec_ctx_->exec_ctx_ = exec_ctx; ObSEArray store_column_idxs; omt::ObTenant *tenant = nullptr; - if (OB_FAIL(GCTX.omt_->get_tenant(MTL_ID(), tenant))) { + ObSQLSessionInfo *sesssion_info = exec_ctx->get_my_session(); + if (OB_UNLIKELY(sesssion_info->get_ddl_info().is_mview_complete_refresh() && enable_inc_replace)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected mview complete refresh enable inc replace", KR(ret)); + } else if (OB_FAIL(GCTX.omt_->get_tenant(MTL_ID(), tenant))) { LOG_WARN("fail to get tenant handle", KR(ret), K(MTL_ID())); } else if (OB_FAIL(init_store_column_idxs(MTL_ID(), table_id, store_column_idxs))) { LOG_WARN("failed to init store column idxs", KR(ret)); @@ -73,12 +81,17 @@ int ObTableDirectInsertCtx::init(ObExecContext *exec_ctx, param.online_opt_stat_gather_ = true; param.need_sort_ = true; param.max_error_row_count_ = 0; - param.dup_action_ = sql::ObLoadDupActionType::LOAD_STOP_ON_DUP; + param.dup_action_ = (enable_inc_replace ? sql::ObLoadDupActionType::LOAD_REPLACE + : sql::ObLoadDupActionType::LOAD_STOP_ON_DUP); param.online_opt_stat_gather_ = is_online_gather_statistics_; - param.method_ = ObDirectLoadMethod::FULL; - param.insert_mode_ = (exec_ctx->get_my_session()->get_ddl_info().is_mview_complete_refresh() - ? ObDirectLoadInsertMode::OVERWRITE - : ObDirectLoadInsertMode::NORMAL); + param.method_ = (is_incremental ? ObDirectLoadMethod::INCREMENTAL : ObDirectLoadMethod::FULL); + if (sesssion_info->get_ddl_info().is_mview_complete_refresh()) { + param.insert_mode_ = ObDirectLoadInsertMode::OVERWRITE; + } else if (enable_inc_replace) { + param.insert_mode_ = ObDirectLoadInsertMode::INC_REPLACE; + } else { + param.insert_mode_ = ObDirectLoadInsertMode::NORMAL; + } if (OB_FAIL(table_load_instance_->init(param, store_column_idxs, load_exec_ctx_))) { LOG_WARN("failed to init direct loader", KR(ret)); } else { @@ -114,7 +127,6 @@ int ObTableDirectInsertCtx::finish() } else if (OB_FAIL(table_load_instance_->px_commit_ddl())) { LOG_WARN("failed to do px_commit_ddl", KR(ret)); } else { - table_load_instance_->destroy(); LOG_DEBUG("succeeded to finish direct loader"); } return ret; @@ -130,6 +142,9 @@ void ObTableDirectInsertCtx::destroy() load_exec_ctx_->~ObTableLoadSqlExecCtx(); load_exec_ctx_ = nullptr; } + is_inited_ = false; + is_direct_ = false; + is_online_gather_statistics_ = false; } int ObTableDirectInsertCtx::init_store_column_idxs(const uint64_t tenant_id, diff --git a/src/sql/engine/cmd/ob_table_direct_insert_ctx.h b/src/sql/engine/cmd/ob_table_direct_insert_ctx.h index 4ee8894fc..ce965c803 100644 --- a/src/sql/engine/cmd/ob_table_direct_insert_ctx.h +++ b/src/sql/engine/cmd/ob_table_direct_insert_ctx.h @@ -39,7 +39,11 @@ public: ~ObTableDirectInsertCtx(); TO_STRING_KV(K_(is_inited)); public: - int init(sql::ObExecContext *exec_ctx, const uint64_t table_id, const int64_t parallel); + int init(sql::ObExecContext *exec_ctx, + const uint64_t table_id, + const int64_t parallel, + const bool is_incremental, + const bool enable_inc_replace); int commit(); int finish(); void destroy(); diff --git a/src/sql/engine/cmd/ob_table_direct_insert_service.cpp b/src/sql/engine/cmd/ob_table_direct_insert_service.cpp index b7dcb0c81..a59396958 100644 --- a/src/sql/engine/cmd/ob_table_direct_insert_service.cpp +++ b/src/sql/engine/cmd/ob_table_direct_insert_service.cpp @@ -38,22 +38,30 @@ int ObTableDirectInsertService::start_direct_insert(ObExecContext &ctx, int ret = OB_SUCCESS; if (!GCONF._ob_enable_direct_load) { // recheck phy_plan.set_enable_append(false); + phy_plan.set_enable_inc_direct_load(false); + phy_plan.set_enable_replace(false); phy_plan.set_append_table_id(0); } else { + const bool is_inc_direct_load = phy_plan.get_enable_inc_direct_load(); + const bool is_inc_replace = phy_plan.get_enable_replace(); ObSQLSessionInfo *session = GET_MY_SESSION(ctx); - CK (OB_NOT_NULL(session)); bool auto_commit = false; - if (OB_FAIL(session->get_autocommit(auto_commit))) { + CK (OB_NOT_NULL(session)); + if (OB_FAIL(ret)) { + } else if (OB_FAIL(session->get_autocommit(auto_commit))) { LOG_WARN("failed to get auto commit", KR(ret)); - } else if (!auto_commit || session->is_in_transaction()) { + } else if (!is_inc_direct_load + && (!auto_commit || session->is_in_transaction())) { ret = OB_NOT_SUPPORTED; - LOG_USER_ERROR(OB_NOT_SUPPORTED, "using direct-insert within a transaction is"); + LOG_WARN("using full direct-insert with a transaction is not supported", KR(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "using full direct-insert within a transaction is"); } else { ObTableDirectInsertCtx &table_direct_insert_ctx = ctx.get_table_direct_insert_ctx(); uint64_t table_id = phy_plan.get_append_table_id(); int64_t parallel = phy_plan.get_px_dop(); - if (OB_FAIL(table_direct_insert_ctx.init(&ctx, table_id, parallel))) { - LOG_WARN("failed to init table direct insert ctx", KR(ret), K(table_id), K(parallel)); + if (OB_FAIL(table_direct_insert_ctx.init(&ctx, table_id, parallel, is_inc_direct_load, is_inc_replace))) { + LOG_WARN("failed to init table direct insert ctx", + KR(ret), K(table_id), K(parallel), K(is_inc_direct_load), K(is_inc_replace)); } } } @@ -72,13 +80,14 @@ int ObTableDirectInsertService::commit_direct_insert(ObExecContext &ctx, } int ObTableDirectInsertService::finish_direct_insert(ObExecContext &ctx, - ObPhysicalPlan &phy_plan) + ObPhysicalPlan &phy_plan, const bool commit) { int ret = OB_SUCCESS; ObTableDirectInsertCtx &table_direct_insert_ctx = ctx.get_table_direct_insert_ctx(); - if (OB_FAIL(table_direct_insert_ctx.finish())) { + if (commit && OB_FAIL(table_direct_insert_ctx.finish())) { LOG_WARN("failed to finish table direct insert ctx", KR(ret)); } + table_direct_insert_ctx.destroy(); return ret; } diff --git a/src/sql/engine/cmd/ob_table_direct_insert_service.h b/src/sql/engine/cmd/ob_table_direct_insert_service.h index 5695d1f5c..ad77af5df 100644 --- a/src/sql/engine/cmd/ob_table_direct_insert_service.h +++ b/src/sql/engine/cmd/ob_table_direct_insert_service.h @@ -34,7 +34,7 @@ public: // all insert-tasks within an insert into select clause are wrapped by a single direct insert instance static int start_direct_insert(ObExecContext &ctx, ObPhysicalPlan &plan); static int commit_direct_insert(ObExecContext &ctx, ObPhysicalPlan &plan); - static int finish_direct_insert(ObExecContext &ctx, ObPhysicalPlan &plan); + static int finish_direct_insert(ObExecContext &ctx, ObPhysicalPlan &plan, const bool commit); // each insert-task is processed in a single thread and is wrapped by a table load trans static int open_task(const uint64_t table_id, const int64_t task_id, diff --git a/src/sql/ob_result_set.cpp b/src/sql/ob_result_set.cpp index 615e7510f..993bd6f43 100644 --- a/src/sql/ob_result_set.cpp +++ b/src/sql/ob_result_set.cpp @@ -577,14 +577,6 @@ OB_INLINE int ObResultSet::do_open_plan(ObExecContext &ctx) } } - // for insert /*+ append */ into select clause - if (OB_SUCC(ret) - && (stmt::T_INSERT == get_stmt_type()) - && (ObTableDirectInsertService::is_direct_insert(*physical_plan_))) { - if (OB_FAIL(ObTableDirectInsertService::start_direct_insert(ctx, *physical_plan_))) { - LOG_WARN("fail to start direct insert", KR(ret)); - } - } if (OB_FAIL(ret)) { } else if (OB_FAIL(start_stmt())) { @@ -598,12 +590,20 @@ OB_INLINE int ObResultSet::do_open_plan(ObExecContext &ctx) ctx.get_physical_plan_ctx()->get_last_refresh_scns()))) { LOG_WARN("fail to set last_refresh_scns", K(ret), K(physical_plan_->get_mview_ids())); } else { + // for insert /*+ append */ into select clause + if ((stmt::T_INSERT == get_stmt_type()) + && (ObTableDirectInsertService::is_direct_insert(*physical_plan_))) { + if (OB_FAIL(ObTableDirectInsertService::start_direct_insert(ctx, *physical_plan_))) { + LOG_WARN("fail to start direct insert", KR(ret)); + } + } /* 将exec_result_设置到executor的运行时环境中,用于返回数据 */ /* 执行plan, * 无论是本地、远程、还是分布式plan,除RootJob外,其余都会在execute_plan函数返回之前执行完毕 * exec_result_负责执行最后一个Job: RootJob **/ - if (OB_FAIL(executor_.init(physical_plan_))) { + if OB_FAIL(ret) { + } else if (OB_FAIL(executor_.init(physical_plan_))) { SQL_LOG(WARN, "fail to init executor", K(ret), K(physical_plan_)); } else if (OB_FAIL(executor_.execute_plan(ctx))) { SQL_LOG(WARN, "fail execute plan", K(ret)); @@ -838,13 +838,14 @@ OB_INLINE int ObResultSet::do_close_plan(int errcode, ObExecContext &ctx) ObPxAdmission::exit_query_admission(my_session_, get_exec_context(), get_stmt_type(), *get_physical_plan()); // Finishing direct-insert must be executed after ObPxTargetMgr::release_target() - if ((OB_SUCCESS == close_ret) - && (OB_SUCCESS == errcode || OB_ITER_END == errcode) - && (stmt::T_INSERT == get_stmt_type()) - && (ObTableDirectInsertService::is_direct_insert(*physical_plan_))) { + if ((stmt::T_INSERT == get_stmt_type()) && + (ObTableDirectInsertService::is_direct_insert(*physical_plan_))) { // for insert /*+ append */ into select clause int tmp_ret = OB_SUCCESS; - if (OB_TMP_FAIL(ObTableDirectInsertService::finish_direct_insert(ctx, *physical_plan_))) { + if (OB_TMP_FAIL(ObTableDirectInsertService::finish_direct_insert( + ctx, + *physical_plan_, + (OB_SUCCESS == close_ret) && (OB_SUCCESS == errcode || OB_ITER_END == errcode)))) { errcode_ = tmp_ret; // record error code errcode = tmp_ret; LOG_WARN("fail to finish direct insert", KR(tmp_ret)); diff --git a/src/sql/ob_sql_trans_control.cpp b/src/sql/ob_sql_trans_control.cpp index a568102fc..bd2b25101 100644 --- a/src/sql/ob_sql_trans_control.cpp +++ b/src/sql/ob_sql_trans_control.cpp @@ -41,6 +41,7 @@ #include "storage/tablet/ob_tablet.h" #include "sql/das/ob_das_dml_ctx_define.h" #include "share/deadlock/ob_deadlock_detector_mgr.h" +#include "sql/engine/cmd/ob_table_direct_insert_ctx.h" #ifdef CHECK_SESSION #error "redefine macro CHECK_SESSION" @@ -1181,6 +1182,15 @@ int ObSqlTransControl::end_stmt(ObExecContext &exec_ctx, const bool rollback) OZ (txs->abort_tx(*tx_desc, ObTxAbortCause::TX_RESULT_INCOMPLETE)); ret = OB_TRANS_NEED_ROLLBACK; LOG_WARN("trans result incomplete, trans aborted", K(ret)); + } else if (plan->get_enable_append() + && plan->get_enable_inc_direct_load() + && OB_UNLIKELY(OB_SUCCESS != exec_errcode)) { + if (!rollback) { + LOG_ERROR("direct load failed, but rollback not issued"); + } + OZ (txs->abort_tx(*tx_desc, ObTxAbortCause::TX_RESULT_INCOMPLETE)); + ret = OB_TRANS_NEED_ROLLBACK; + LOG_WARN("direct load failed, trans aborted", KR(ret)); } else if (rollback) { auto stmt_expire_ts = get_stmt_expire_ts(plan_ctx, *session); auto &touched_ls = tx_result.get_touched_ls(); diff --git a/src/sql/optimizer/ob_insert_log_plan.cpp b/src/sql/optimizer/ob_insert_log_plan.cpp index a05f8c2f3..4bdc5c1a1 100644 --- a/src/sql/optimizer/ob_insert_log_plan.cpp +++ b/src/sql/optimizer/ob_insert_log_plan.cpp @@ -270,8 +270,8 @@ int ObInsertLogPlan::generate_osg_share_info(OSGShareInfo *&info) // 1. pdml insert // 2. _ob_enable_direct_load // 3. insert into select clause -// 4. append hint -// 5. auto_commit, not in a transaction +// 4. append hint or direct_load hint +// 5. full_direct_load(auto_commit, not in a transaction) or inc_direct_load int ObInsertLogPlan::set_is_direct_insert() { int ret = OB_SUCCESS; is_direct_insert_ = false; @@ -281,14 +281,17 @@ int ObInsertLogPlan::set_is_direct_insert() { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(get_stmt()), K(session_info)); } else if (!get_stmt()->value_from_select() - || !get_optimizer_context().get_global_hint().has_append() - || !GCONF._ob_enable_direct_load - || session_info->is_in_transaction()) { - /* is not direct insert */ - } else if (OB_FAIL(session_info->get_autocommit(auto_commit))) { - LOG_WARN("failed to get auto commit", KR(ret)); + || !get_optimizer_context().get_global_hint().has_direct_load() + || !GCONF._ob_enable_direct_load) { + } else if (get_optimizer_context().get_global_hint().has_inc_direct_load()) { + is_direct_insert_ = true; } else { - is_direct_insert_ = auto_commit; + // full direct load + if (OB_FAIL(session_info->get_autocommit(auto_commit))) { + LOG_WARN("failed to get auto commit", KR(ret)); + } else if (auto_commit && !session_info->is_in_transaction()){ + is_direct_insert_ = true; + } } return ret; } diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index 7e67d52de..7a51ec4b3 100644 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -10365,7 +10365,11 @@ READ_CONSISTENCY '(' consistency_level ')' } | DIRECT '(' BOOL_VALUE ',' INTNUM ')' { - malloc_non_terminal_node($$, result->malloc_pool_, T_DIRECT, 2, $3, $5); + malloc_non_terminal_node($$, result->malloc_pool_, T_DIRECT, 3, $3, $5, NULL); +} +| DIRECT '(' BOOL_VALUE ',' INTNUM ',' STRING_VALUE ')' +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_DIRECT, 3, $3, $5, $7); } | APPEND { diff --git a/src/sql/resolver/cmd/ob_load_data_resolver.cpp b/src/sql/resolver/cmd/ob_load_data_resolver.cpp index 0a225b3a7..f2b14860c 100644 --- a/src/sql/resolver/cmd/ob_load_data_resolver.cpp +++ b/src/sql/resolver/cmd/ob_load_data_resolver.cpp @@ -126,20 +126,14 @@ int ObLoadDataResolver::resolve(const ParseNode &parse_tree) if (OB_SUCC(ret)) { /* 2. opt_duplicate */ ObLoadArgument &load_args = load_stmt->get_load_arguments(); - ObLoadDupActionType dupl_action = ObLoadDupActionType::LOAD_STOP_ON_DUP; + ObLoadDupActionType dupl_action = ObLoadDupActionType::LOAD_INVALID_MODE; if (NULL == node->children_[ENUM_DUPLICATE_ACTION]) { - if (ObLoadFileLocation::CLIENT_DISK == load_args.load_file_storage_ && - lib::is_mysql_mode()) { - // https://dev.mysql.com/doc/refman/8.0/en/load-data.html - // In MySQL, LOCAL modifier has the same effect as the IGNORE modifier. - dupl_action = ObLoadDupActionType::LOAD_IGNORE; - } + dupl_action = ObLoadDupActionType::LOAD_STOP_ON_DUP; } else if (T_IGNORE == node->children_[ENUM_DUPLICATE_ACTION]->type_) { dupl_action = ObLoadDupActionType::LOAD_IGNORE; } else if (T_REPLACE == node->children_[ENUM_DUPLICATE_ACTION]->type_) { dupl_action = ObLoadDupActionType::LOAD_REPLACE; } else { - dupl_action = ObLoadDupActionType::LOAD_INVALID_MODE; ret = OB_ERR_UNEXPECTED; //should not be here, parser will put error before this LOG_WARN("unknown dumplicate settings", K(ret)); @@ -351,6 +345,19 @@ int ObLoadDataResolver::resolve(const ParseNode &parse_tree) } } + if (OB_SUCC(ret)) { + ObLoadArgument &load_args = load_stmt->get_load_arguments(); + const ObDirectLoadHint &direct_load_hint = load_stmt->get_hints().get_direct_load_hint(); + if (ObLoadDupActionType::LOAD_STOP_ON_DUP == load_args.dupl_action_ && + ObLoadFileLocation::CLIENT_DISK == load_args.load_file_storage_ && + lib::is_mysql_mode() && + (!direct_load_hint.is_enable() || !direct_load_hint.is_inc_replace_load_method())) { + // https://dev.mysql.com/doc/refman/8.0/en/load-data.html + // In MySQL, LOCAL modifier has the same effect as the IGNORE modifier. + load_args.dupl_action_ = ObLoadDupActionType::LOAD_IGNORE; + } + } + if (OB_SUCC(ret)) { if (OB_FAIL(validate_stmt(load_stmt))) { LOG_WARN("failed to validate stmt"); @@ -397,24 +404,9 @@ int ObLoadDataResolver::resolve_hints(const ParseNode &node) switch (hint_node->type_) { case T_DIRECT: { - if (hint_node->num_child_ != 2) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected hint node", K(ret), K(hint_node->num_child_)); - } else { - int64_t need_sort = hint_node->children_[0]->value_; - int64_t error_rows_value = hint_node->children_[1]->value_; - if (error_rows_value < 0) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid error rows value", K(ret), K(error_rows_value)); - } else if (OB_FAIL(stmt_hints.set_value( - ObLoadDataHint::ENABLE_DIRECT, 1))) { - LOG_WARN("fail to enable direct", K(ret)); - } else if (OB_FAIL(stmt_hints.set_value( - ObLoadDataHint::NEED_SORT, need_sort))) { - LOG_WARN("fail to enable sort", K(ret)); - } else if (OB_FAIL(stmt_hints.set_value(ObLoadDataHint::ERROR_ROWS, error_rows_value))) { - LOG_WARN("fail to set error rows", K(ret), K(error_rows_value)); - } + ObDirectLoadHint &direct_load_hint = stmt_hints.get_direct_load_hint(); + if (OB_FAIL(ObDMLResolver::resolve_direct_load_hint(*hint_node, direct_load_hint))) { + LOG_WARN("fail to resolve direct load hint", KR(ret)); } break; } diff --git a/src/sql/resolver/cmd/ob_load_data_stmt.h b/src/sql/resolver/cmd/ob_load_data_stmt.h index eb3b82e33..2e495e062 100644 --- a/src/sql/resolver/cmd/ob_load_data_stmt.h +++ b/src/sql/resolver/cmd/ob_load_data_stmt.h @@ -15,6 +15,7 @@ #include "sql/resolver/cmd/ob_cmd_stmt.h" #include "sql/resolver/dml/ob_del_upd_stmt.h" +#include "sql/resolver/dml/ob_hint.h" #include "share/backup/ob_backup_struct.h" namespace oceanbase { @@ -181,9 +182,6 @@ public: BATCH_SIZE, QUERY_TIMEOUT, APPEND, - ENABLE_DIRECT, - NEED_SORT, - ERROR_ROWS, GATHER_OPTIMIZER_STATISTICS, NO_GATHER_OPTIMIZER_STATISTICS, TOTAL_INT_ITEM @@ -199,19 +197,23 @@ public: for (int64_t i = 0; i < TOTAL_STRING_ITEM; ++i) { string_values_[i].reset(); } + direct_load_hint_.reset(); } int set_value(IntHintItem item, int64_t value); int get_value(IntHintItem item, int64_t &value) const; int set_value(StringHintItem item, const ObString &value); int get_value(StringHintItem item, ObString &value) const; + ObDirectLoadHint &get_direct_load_hint() { return direct_load_hint_; } + const ObDirectLoadHint &get_direct_load_hint() const { return direct_load_hint_; } TO_STRING_KV("Int Hint Item", common::ObArrayWrap(integer_values_, TOTAL_INT_ITEM), "String Hint Item", - common::ObArrayWrap(string_values_, TOTAL_STRING_ITEM)); + common::ObArrayWrap(string_values_, TOTAL_STRING_ITEM), + K_(direct_load_hint)); private: int64_t integer_values_[TOTAL_INT_ITEM]; ObString string_values_[TOTAL_STRING_ITEM]; - + ObDirectLoadHint direct_load_hint_; }; class ObLoadDataStmt : public ObCMDStmt diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 86fa9ef62..48dfae9e6 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -14161,6 +14161,15 @@ int ObDMLResolver::resolve_global_hint(const ParseNode &hint_node, } break; } + case T_DIRECT: { + ObDirectLoadHint direct_load_hint; + if (OB_FAIL(resolve_direct_load_hint(hint_node, direct_load_hint))) { + LOG_WARN("fail to resolve direct load hint", KR(ret)); + } else { + global_hint.merge_direct_load_hint(direct_load_hint); + } + break; + } default: { resolved_hint = false; break; @@ -16637,6 +16646,47 @@ int ObDMLResolver::resolve_table_dynamic_sampling_hint(const ParseNode &hint_nod return ret; } +int ObDMLResolver::resolve_direct_load_hint(const ParseNode &hint_node, ObDirectLoadHint &hint) +{ + int ret = OB_SUCCESS; + ParseNode *child0 = nullptr; // need_sort + ParseNode *child1 = nullptr; // max_error_row_count + ParseNode *child2 = nullptr; // load_method + hint.reset(); + if (OB_UNLIKELY(3 != hint_node.num_child_) || + OB_ISNULL(child0 = hint_node.children_[0]) || + OB_ISNULL(child1 = hint_node.children_[1])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected hint node", K(ret), K(hint_node.num_child_), K(child0), K(child1)); + } else { + const int64_t need_sort_value = child0->value_; + const int64_t error_rows_value = hint_node.children_[1]->value_; + ObString load_method_str; + ObDirectLoadHint::LoadMethod load_method_value = ObDirectLoadHint::INVALID_LOAD_METHOD; + if (OB_NOT_NULL(child2 = hint_node.children_[2])) { + load_method_str.assign_ptr(child2->str_value_, child2->str_len_); + load_method_value = ObDirectLoadHint::get_load_method_value(load_method_str); + } else { + load_method_value = ObDirectLoadHint::FULL; + } + if (OB_UNLIKELY(error_rows_value < 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid error rows value", KR(ret), K(error_rows_value)); + LOG_USER_ERROR(OB_INVALID_ARGUMENT, "error rows in direct hint"); + } else if (OB_UNLIKELY(ObDirectLoadHint::INVALID_LOAD_METHOD == load_method_value)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid load method value", KR(ret), K(load_method_str)); + LOG_USER_ERROR(OB_INVALID_ARGUMENT, "load method in direct hint"); + } else { + hint.is_enable_ = true; + hint.need_sort_ = (need_sort_value != 0); + hint.max_error_row_count_ = error_rows_value; + hint.load_method_ = load_method_value; + } + } + return ret; +} + int ObDMLResolver::resolve_values_table_item(const ParseNode &table_node, TableItem *&table_item) { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/dml/ob_dml_resolver.h b/src/sql/resolver/dml/ob_dml_resolver.h index 95b981dc1..987bb4114 100644 --- a/src/sql/resolver/dml/ob_dml_resolver.h +++ b/src/sql/resolver/dml/ob_dml_resolver.h @@ -950,9 +950,11 @@ private: ObWindowDistHint::WinDistOption &dist_option, bool &is_valid); int resolve_table_dynamic_sampling_hint(const ParseNode &hint_node, ObOptHint *&opt_hint); +public: + static int resolve_direct_load_hint(const ParseNode &hint_node, ObDirectLoadHint &hint); //////////end of functions for sql hint///////////// - +private: int resolve_table_check_constraint_items(const TableItem *table_item, const ObTableSchema *table_schema); int resolve_table_constraint_items(const TableItem *table_item, diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index a57681bb5..c569c2fbe 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -308,6 +308,14 @@ void ObGlobalHint::merge_opt_features_version_hint(uint64_t opt_features_version } } +void ObGlobalHint::merge_direct_load_hint(const ObDirectLoadHint &other) +{ + direct_load_hint_.flags_ |= other.flags_; + direct_load_hint_.max_error_row_count_ = + std::max(direct_load_hint_.max_error_row_count_, other.max_error_row_count_); + direct_load_hint_.load_method_ = other.load_method_; +} + // zhanyue todo: try remove this later bool ObGlobalHint::has_hint_exclude_concurrent() const { @@ -337,7 +345,8 @@ bool ObGlobalHint::has_hint_exclude_concurrent() const || has_gather_opt_stat_hint() || false != has_dbms_stats_hint_ || -1 != dynamic_sampling_ - || flashback_read_tx_uncommitted_; + || flashback_read_tx_uncommitted_ + || has_direct_load(); } void ObGlobalHint::reset() @@ -368,6 +377,7 @@ void ObGlobalHint::reset() flashback_read_tx_uncommitted_ = false; dynamic_sampling_ = ObGlobalHint::UNSET_DYNAMIC_SAMPLING; alloc_op_hints_.reuse(); + direct_load_hint_.reset(); dblink_hints_.reset(); } @@ -396,6 +406,7 @@ int ObGlobalHint::merge_global_hint(const ObGlobalHint &other) flashback_read_tx_uncommitted_ |= other.flashback_read_tx_uncommitted_; dblink_hints_ = other.dblink_hints_; merge_dynamic_sampling_hint(other.dynamic_sampling_); + merge_direct_load_hint(other.direct_load_hint_); if (OB_FAIL(merge_alloc_op_hints(other.alloc_op_hints_))) { LOG_WARN("failed to merge alloc op hints", K(ret)); } else if (OB_FAIL(merge_dop_hint(other.dops_))) { @@ -576,6 +587,9 @@ int ObGlobalHint::print_global_hint(PlanText &plan_text) const if (OB_SUCC(ret) && get_flashback_read_tx_uncommitted()) { PRINT_GLOBAL_HINT_STR("FLASHBACK_READ_TX_UNCOMMITTED"); } + if (OB_SUCC(ret) && OB_FAIL(direct_load_hint_.print_direct_load_hint(plan_text))) { + LOG_WARN("failed to print direct load hint", KR(ret)); + } return ret; } @@ -2954,5 +2968,41 @@ int ObAllocOpHint::assign(const ObAllocOpHint& other) { return ret; } +DEFINE_ENUM_FUNC(ObDirectLoadHint::LoadMethod, load_method, DIRECT_LOAD_METHOD_DEF, ObDirectLoadHint::); + +void ObDirectLoadHint::reset() +{ + flags_ = 0; + max_error_row_count_ = 0; + load_method_ = INVALID_LOAD_METHOD; +} + +int ObDirectLoadHint::assign(const ObDirectLoadHint &other) +{ + int ret = OB_SUCCESS; + flags_ = other.flags_; + max_error_row_count_ = other.max_error_row_count_; + load_method_ = other.load_method_; + return ret; +} + +int ObDirectLoadHint::print_direct_load_hint(PlanText &plan_text) const +{ + int ret = OB_SUCCESS; + const char* outline_indent = ObQueryHint::get_outline_indent(plan_text.is_oneline_); + char *buf = plan_text.buf_; + int64_t &buf_len = plan_text.buf_len_; + int64_t &pos = plan_text.pos_; + if (is_enable_) { + const char *need_sort_str = need_sort_ ? "TRUE" : "FALSE"; + const char *load_method_str = get_load_method_string(load_method_); + if (OB_FAIL(BUF_PRINTF("%sDIRECT(%s, %ld, '%s')", + outline_indent, need_sort_str, max_error_row_count_, load_method_str))) { + LOG_WARN("failed to print direct load hint", KR(ret)); + } + } + return ret; +} + }//end of namespace sql }//end of namespace oceanbase diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index 8710f366e..ae1c05119 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -89,6 +89,53 @@ struct ObOptimizerStatisticsGatheringHint int print_osg_hint(PlanText &plan_text) const; }; +struct ObDirectLoadHint +{ +public: +#define DIRECT_LOAD_METHOD_DEF(DEF) \ + DEF(INVALID_LOAD_METHOD, = 0) \ + DEF(FULL, = 1) \ + DEF(INC, = 2) \ + DEF(INC_REPLACE, = 3) \ + DEF(MAX_LOAD_METHOD, ) + + DECLARE_ENUM(LoadMethod, load_method, DIRECT_LOAD_METHOD_DEF, static); + +public: + ObDirectLoadHint() : flags_(0), max_error_row_count_(0), load_method_(INVALID_LOAD_METHOD) {} + ~ObDirectLoadHint() = default; + + void reset(); + int assign(const ObDirectLoadHint &other); + int print_direct_load_hint(PlanText &plan_text) const; + + OB_INLINE bool is_enable() const { return is_enable_; } + OB_INLINE bool need_sort() const { return need_sort_; } + OB_INLINE int64_t get_max_error_row_count() const { return max_error_row_count_; } + OB_INLINE bool is_full_load_method() const { return LoadMethod::FULL == load_method_; } + OB_INLINE bool is_inc_load_method() const { return LoadMethod::INC == load_method_; } + OB_INLINE bool is_inc_replace_load_method() const { return LoadMethod::INC_REPLACE == load_method_; } + OB_INLINE bool is_full_direct_load() const { return is_full_load_method(); } + OB_INLINE bool is_inc_direct_load() const { return is_inc_load_method() || is_inc_replace_load_method(); } + + TO_STRING_KV(K_(is_enable), + K_(need_sort), + K_(flags), + K_(max_error_row_count), + "load_method", get_load_method_string(load_method_)); +public: + union { + struct { + uint64_t is_enable_ : 1; + uint64_t need_sort_ : 1; + uint64_t reserved_ : 62; + }; + uint64_t flags_; + }; + int64_t max_error_row_count_; + LoadMethod load_method_; +}; + struct ObOptParamHint { ObOptParamHint() {}; @@ -201,6 +248,7 @@ struct ObGlobalHint { void merge_opt_features_version_hint(uint64_t opt_features_version); void merge_osg_hint(int8_t flag); void merge_dynamic_sampling_hint(int64_t dynamic_sampling); + void merge_direct_load_hint(const ObDirectLoadHint &other); bool has_hint_exclude_concurrent() const; int print_global_hint(PlanText &plan_text) const; @@ -234,7 +282,18 @@ struct ObGlobalHint { merge_osg_hint(ObOptimizerStatisticsGatheringHint::OB_APPEND_HINT); } } - + bool has_direct_load() const + { + return (has_append() || direct_load_hint_.is_enable()); + } + bool has_inc_direct_load() const + { + return (direct_load_hint_.is_enable() && direct_load_hint_.is_inc_direct_load()); + } + bool has_replace() const + { + return (direct_load_hint_.is_enable() && direct_load_hint_.is_inc_replace_load_method()); + } // wether should generate optimizer_statistics_operator. bool should_generate_osg_operator () const { @@ -310,6 +369,7 @@ struct ObGlobalHint { bool flashback_read_tx_uncommitted_; int64_t dynamic_sampling_; common::ObSArray alloc_op_hints_; + ObDirectLoadHint direct_load_hint_; ObDBLinkHit dblink_hints_; }; diff --git a/src/sql/resolver/dml/ob_insert_resolver.cpp b/src/sql/resolver/dml/ob_insert_resolver.cpp index 94ebfcabb..dc78d6e7f 100644 --- a/src/sql/resolver/dml/ob_insert_resolver.cpp +++ b/src/sql/resolver/dml/ob_insert_resolver.cpp @@ -120,7 +120,7 @@ int ObInsertResolver::resolve(const ParseNode &parse_tree) ObQueryCtx *query_ctx = insert_stmt->get_query_ctx(); if (OB_ISNULL(query_ctx)) { LOG_WARN("query ctx should not be NULL", KR(ret), KP(query_ctx)); - } else if (query_ctx->get_query_hint().get_global_hint().has_append()) { + } else if (query_ctx->get_query_hint().get_global_hint().has_direct_load()) { // For insert into select clause with direct-insert mode, plan cache is disabled query_ctx->get_query_hint_for_update().global_hint_.merge_plan_cache_hint(OB_USE_PLAN_CACHE_NONE); } diff --git a/src/storage/CMakeLists.txt b/src/storage/CMakeLists.txt index 5cf2bf81c..82727852b 100644 --- a/src/storage/CMakeLists.txt +++ b/src/storage/CMakeLists.txt @@ -354,6 +354,7 @@ ob_set_subtarget(ob_storage tx tx/ob_trans_stat.cpp tx/ob_tx_stat.cpp tx/ob_tx_retain_ctx_mgr.cpp + tx/ob_direct_load_tx_ctx_define.cpp tx/ob_ls_tx_ctx_mgr_stat.cpp tx/ob_trans_submit_log_cb.cpp tx/ob_trans_timer.cpp @@ -531,6 +532,7 @@ ob_set_subtarget(ob_storage ddl ddl/ob_ddl_struct.cpp ddl/ob_direct_load_struct.cpp ddl/ob_direct_insert_sstable_ctx_new.cpp + ddl/ob_ddl_redo_log_row_iterator.cpp ddl/ob_tablet_barrier_log.cpp ddl/ob_tablet_ddl_kv.cpp ddl/ob_tablet_ddl_kv_mgr.cpp @@ -538,6 +540,9 @@ ob_set_subtarget(ob_storage ddl ddl/ob_ddl_replay_executor.cpp ddl/ob_ddl_heart_beat_task.cpp ddl/ob_ddl_server_client.cpp + ddl/ob_ddl_inc_clog.cpp + ddl/ob_ddl_inc_clog_callback.cpp + ddl/ob_ddl_inc_redo_log_writer.cpp ) ob_set_subtarget(ob_storage common @@ -550,8 +555,8 @@ ob_set_subtarget(ob_storage common ob_i_memtable_mgr.cpp ob_i_store.cpp ob_i_table.cpp + ob_i_tablet_memtable.cpp ob_locality_manager.cpp - ob_partition_component_factory.cpp ob_partition_range_spliter.cpp ob_query_iterator_factory.cpp ob_relative_table.cpp @@ -574,6 +579,7 @@ ob_set_subtarget(ob_storage common ob_tablet_autoinc_seq_rpc_handler.cpp ob_value_row_iterator.cpp ob_common_id_utils.cpp + ob_direct_load_table_guard.cpp ob_tenant_tablet_stat_mgr.cpp ob_protected_memtable_mgr_handle.cpp ) diff --git a/src/storage/access/ob_multiple_merge.cpp b/src/storage/access/ob_multiple_merge.cpp index 92cc1e687..642494c20 100644 --- a/src/storage/access/ob_multiple_merge.cpp +++ b/src/storage/access/ob_multiple_merge.cpp @@ -31,6 +31,7 @@ #include "storage/column_store/ob_column_oriented_sstable.h" #include "storage/tablet/ob_tablet.h" #include "storage/tx/ob_trans_part_ctx.h" +#include "storage/ddl/ob_tablet_ddl_kv.h" namespace oceanbase { @@ -1315,16 +1316,29 @@ int ObMultipleMerge::prepare_tables_from_iterator(ObTableStoreIterator &table_it } } if (OB_SUCC(ret) && need_table) { + ObITable *target_table_ptr = table_ptr; if (table_ptr->no_data_to_read()) { LOG_DEBUG("cur table is empty", K(ret), KPC(table_ptr)); continue; } else if (table_ptr->is_memtable()) { read_released_memtable = read_released_memtable || - memtable::ObMemtableFreezeState::RELEASED == (static_cast(table_ptr))->get_freeze_state(); + TabletMemtableFreezeState::RELEASED == (static_cast(table_ptr))->get_freeze_state(); ++memtable_cnt; + if (table_ptr->is_direct_load_memtable()) { + ObDDLMemtable *ddl_memtable = nullptr; + if (OB_FAIL((static_cast(table_ptr)->get_ddl_memtable(0, ddl_memtable)))) { + LOG_WARN("fail to get ddl memtable but ignore the failure, return nullpoint", K(ret)); + } else if (OB_ISNULL(ddl_memtable)) { + continue; + } else { + target_table_ptr = ddl_memtable; + } + } } - if (OB_FAIL(tables_.push_back(table_ptr))) { - LOG_WARN("add table fail", K(ret), K(*table_ptr)); + if (OB_SUCC(ret)) { + if (OB_FAIL(tables_.push_back(target_table_ptr))) { + LOG_WARN("add table fail", K(ret), K(*table_ptr)); + } } } } // end while diff --git a/src/storage/access/ob_multiple_merge.h b/src/storage/access/ob_multiple_merge.h index 02b0ad3b0..26617c32b 100644 --- a/src/storage/access/ob_multiple_merge.h +++ b/src/storage/access/ob_multiple_merge.h @@ -35,6 +35,8 @@ namespace oceanbase namespace storage { class ObBlockRowStore; +class ObDDLKV; +class ObDDLMemtable; class ObMultipleMerge : public ObQueryRowIterator { public: diff --git a/src/storage/blocksstable/ob_block_sstable_struct.cpp b/src/storage/blocksstable/ob_block_sstable_struct.cpp index b1963bf08..348c0d461 100644 --- a/src/storage/blocksstable/ob_block_sstable_struct.cpp +++ b/src/storage/blocksstable/ob_block_sstable_struct.cpp @@ -797,37 +797,6 @@ int ObRecordHeaderV3::deserialize(const char *buf, int64_t buf_len, int64_t &pos return ret; } -ObDDLMacroBlockRedoInfo::ObDDLMacroBlockRedoInfo() - : table_key_(), data_buffer_(), block_type_(ObDDLMacroBlockType::DDL_MB_INVALID_TYPE), start_scn_(SCN::min_scn()), - data_format_version_(0/*for compatibility*/), end_row_id_(-1) -{ -} - -void ObDDLMacroBlockRedoInfo::reset() -{ - table_key_.reset(); - data_buffer_.reset(); - block_type_ = ObDDLMacroBlockType::DDL_MB_INVALID_TYPE; - logic_id_.reset(); - start_scn_ = SCN::min_scn(); - data_format_version_ = 0; - end_row_id_ = -1; -} - -bool ObDDLMacroBlockRedoInfo::is_valid() const -{ - return table_key_.is_valid() && data_buffer_.ptr() != nullptr && block_type_ != ObDDLMacroBlockType::DDL_MB_INVALID_TYPE - && logic_id_.is_valid() && start_scn_.is_valid_and_not_min() && data_format_version_ >= 0; -} - -bool ObDDLMacroBlockRedoInfo::is_column_group_info_valid() const -{ - return table_key_.is_column_store_sstable() && end_row_id_ >= 0; -} - -OB_SERIALIZE_MEMBER(ObDDLMacroBlockRedoInfo, table_key_, data_buffer_, block_type_, logic_id_, - start_scn_, data_format_version_, end_row_id_); - constexpr uint8_t ObColClusterInfoMask::BYTES_TYPE_TO_LEN[]; } diff --git a/src/storage/blocksstable/ob_block_sstable_struct.h b/src/storage/blocksstable/ob_block_sstable_struct.h index b1fb070aa..b5918ee56 100644 --- a/src/storage/blocksstable/ob_block_sstable_struct.h +++ b/src/storage/blocksstable/ob_block_sstable_struct.h @@ -1094,34 +1094,6 @@ public: const char *encrypt_key_; }; -enum ObDDLMacroBlockType -{ - DDL_MB_INVALID_TYPE = 0, - DDL_MB_DATA_TYPE = 1, - DDL_MB_INDEX_TYPE = 2, -}; - -struct ObDDLMacroBlockRedoInfo final -{ - OB_UNIS_VERSION(1); -public: - ObDDLMacroBlockRedoInfo(); - ~ObDDLMacroBlockRedoInfo() = default; - bool is_valid() const; - bool is_column_group_info_valid() const; - void reset(); - TO_STRING_KV(K_(table_key), K_(data_buffer), K_(block_type), K_(logic_id), - K_(start_scn), K_(data_format_version), K_(end_row_id)); -public: - storage::ObITable::TableKey table_key_; - ObString data_buffer_; - ObDDLMacroBlockType block_type_; - ObLogicMacroBlockId logic_id_; - share::SCN start_scn_; - uint64_t data_format_version_; - int64_t end_row_id_; -}; - }//end namespace blocksstable }//end namespace oceanbase #endif diff --git a/src/storage/blocksstable/ob_datum_row.h b/src/storage/blocksstable/ob_datum_row.h index 199e1dbd9..17cb7655b 100644 --- a/src/storage/blocksstable/ob_datum_row.h +++ b/src/storage/blocksstable/ob_datum_row.h @@ -96,11 +96,15 @@ public: { whole_flag_ = 0; } - OB_INLINE void set_flag(ObDmlFlag row_flag) + OB_INLINE void set_flag(ObDmlFlag row_flag, ObDmlRowFlagType flag_type = DF_TYPE_NORMAL) { + reset(); if (OB_LIKELY(row_flag >= DF_NOT_EXIST && row_flag < DF_MAX)) { flag_ = row_flag; } + if (OB_LIKELY(flag_type >= DF_TYPE_NORMAL && flag_type < DF_TYPE_MAX)) { + flag_type_ = flag_type; + } } OB_INLINE bool is_delete() const { @@ -133,7 +137,7 @@ public: OB_INLINE bool is_valid() const { return (DF_TYPE_NORMAL == flag_type_ && DF_DELETE >= flag_) - || (DF_TYPE_INSERT_DELETE == flag_type_ && DF_DELETE == flag_); + || (DF_TYPE_INSERT_DELETE == flag_type_ && (DF_INSERT == flag_ || DF_DELETE == flag_)); } OB_INLINE bool is_extra_delete() const { @@ -143,6 +147,10 @@ public: { return DF_TYPE_INSERT_DELETE == flag_type_ && DF_DELETE == flag_; } + OB_INLINE bool is_delete_insert() const + { + return DF_TYPE_INSERT_DELETE == flag_type_ && DF_INSERT == flag_; + } OB_INLINE void fuse_flag(const ObDmlRowFlag input_flag) { if (OB_LIKELY(input_flag.is_valid())) { diff --git a/src/storage/blocksstable/ob_macro_block_bare_iterator.cpp b/src/storage/blocksstable/ob_macro_block_bare_iterator.cpp index e3503a721..36a36f8f2 100644 --- a/src/storage/blocksstable/ob_macro_block_bare_iterator.cpp +++ b/src/storage/blocksstable/ob_macro_block_bare_iterator.cpp @@ -24,8 +24,9 @@ namespace oceanbase namespace blocksstable { -ObMicroBlockBareIterator::ObMicroBlockBareIterator() - : allocator_(), macro_block_buf_(nullptr), macro_block_buf_size_(0), common_header_(), +ObMicroBlockBareIterator::ObMicroBlockBareIterator(const uint64_t tenant_id) + : allocator_(), macro_block_buf_(nullptr), macro_block_buf_size_(0), + macro_reader_(tenant_id), index_reader_(tenant_id), common_header_(), macro_block_header_(), reader_(nullptr), micro_reader_helper_(), index_rowkey_cnt_(0), begin_idx_(0), end_idx_(0), iter_idx_(0), read_pos_(0), @@ -484,8 +485,8 @@ int ObMicroBlockBareIterator::set_reader(const ObRowStoreType store_type) return ret; } -ObMacroBlockRowBareIterator::ObMacroBlockRowBareIterator(common::ObIAllocator &allocator) - : row_(), micro_iter_(), column_types_(nullptr), column_checksums_(nullptr), +ObMacroBlockRowBareIterator::ObMacroBlockRowBareIterator(common::ObIAllocator &allocator, const uint64_t tenant_id) + : row_(tenant_id), micro_iter_(tenant_id), column_types_(nullptr), column_checksums_(nullptr), rowkey_descs_(allocator), allocator_(&allocator), micro_reader_(nullptr), curr_micro_block_data_(), curr_block_row_idx_(-1), curr_block_row_cnt_(0), is_inited_(false) { diff --git a/src/storage/blocksstable/ob_macro_block_bare_iterator.h b/src/storage/blocksstable/ob_macro_block_bare_iterator.h index d48948458..40460ccbc 100644 --- a/src/storage/blocksstable/ob_macro_block_bare_iterator.h +++ b/src/storage/blocksstable/ob_macro_block_bare_iterator.h @@ -26,7 +26,7 @@ namespace blocksstable class ObMicroBlockBareIterator { public: - ObMicroBlockBareIterator(); + ObMicroBlockBareIterator(const uint64_t tenant_id = MTL_ID()); virtual ~ObMicroBlockBareIterator(); void reset(); void reuse(); @@ -96,9 +96,8 @@ private: class ObMacroBlockRowBareIterator { public: - ObMacroBlockRowBareIterator(common::ObIAllocator &allocator); + ObMacroBlockRowBareIterator(common::ObIAllocator &allocator, const uint64_t tenant_id = MTL_ID()); virtual ~ObMacroBlockRowBareIterator(); - void reset(); int open( const char *macro_block_buf, diff --git a/src/storage/blocksstable/ob_macro_block_reader.cpp b/src/storage/blocksstable/ob_macro_block_reader.cpp index f237ca13a..def1620f5 100644 --- a/src/storage/blocksstable/ob_macro_block_reader.cpp +++ b/src/storage/blocksstable/ob_macro_block_reader.cpp @@ -34,13 +34,13 @@ using namespace compaction; namespace blocksstable { -ObMacroBlockReader::ObMacroBlockReader() +ObMacroBlockReader::ObMacroBlockReader(const uint64_t tenant_id) :compressor_(NULL), uncomp_buf_(NULL), uncomp_buf_size_(0), decrypt_buf_(NULL), decrypt_buf_size_(0), - allocator_(ObModIds::OB_CS_SSTABLE_READER, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()), + allocator_(ObModIds::OB_CS_SSTABLE_READER, OB_MALLOC_NORMAL_BLOCK_SIZE, tenant_id), encryption_(nullptr) { if (share::is_reserve_mode()) { diff --git a/src/storage/blocksstable/ob_macro_block_reader.h b/src/storage/blocksstable/ob_macro_block_reader.h index 3e20f64cb..08d60b853 100644 --- a/src/storage/blocksstable/ob_macro_block_reader.h +++ b/src/storage/blocksstable/ob_macro_block_reader.h @@ -42,7 +42,7 @@ class ObMacroBlockRowBareIterator; class ObMacroBlockReader { public: - ObMacroBlockReader(); + ObMacroBlockReader(const uint64_t tenant_id = MTL_ID()); virtual ~ObMacroBlockReader(); int decompress_data( const common::ObCompressorType compressor_type, @@ -125,7 +125,6 @@ public: const char *&decrypt_buf, int64_t &decrypt_size); #endif - private: int alloc_buf(const int64_t req_size, char *&buf, int64_t &buf_size); int alloc_buf(ObIAllocator &allocator, const int64_t buf_size, char *&buf); diff --git a/src/storage/blocksstable/ob_sstable_meta.cpp b/src/storage/blocksstable/ob_sstable_meta.cpp index cfa921099..8a5b9da0b 100644 --- a/src/storage/blocksstable/ob_sstable_meta.cpp +++ b/src/storage/blocksstable/ob_sstable_meta.cpp @@ -382,6 +382,7 @@ ObSSTableMeta::ObSSTableMeta() cg_sstables_(), column_checksums_(nullptr), column_checksum_count_(0), + tx_ids_(), is_inited_(false) { } @@ -414,6 +415,7 @@ void ObSSTableMeta::reset() basic_meta_.reset(); column_checksums_ = nullptr; column_checksum_count_ = 0; + tx_ids_.reset(); is_inited_ = false; } @@ -545,6 +547,12 @@ int ObSSTableMeta::init( } } + if (OB_SUCC(ret) && transaction::ObTransID(param.uncommitted_tx_id_).is_valid()) { + if (OB_FAIL(tx_ids_.push_back(param.uncommitted_tx_id_))) { + LOG_WARN("failed to alloc memory for tx_ids_", K(ret), K(param)); + } + } + if (OB_SUCC(ret)) { if (param.is_ready_for_read_) { basic_meta_.status_ = SSTABLE_READY_FOR_READ; @@ -609,6 +617,8 @@ int ObSSTableMeta::serialize_(char *buf, const int64_t buf_len, int64_t &pos) co LOG_WARN("fail to serialize macro info", K(ret), K(buf_len), K(pos), K(macro_info_)); } else if (OB_FAIL(cg_sstables_.serialize(buf, buf_len, pos))) { LOG_WARN("fail to serialize cg sstables", K(ret), K(buf_len), K(pos), K(cg_sstables_)); + } else if (OB_FAIL(tx_ids_.serialize(buf, buf_len, pos))) { + LOG_WARN("fail to serialize tx ids", K(ret), K(buf_len), K(pos), K(tx_ids_)); } } return ret; @@ -684,6 +694,8 @@ int ObSSTableMeta::deserialize_( LOG_WARN("fail to deserialize macro info", K(ret), K(data_len), K(pos), K(des_meta)); } else if (pos < data_len && OB_FAIL(cg_sstables_.deserialize(allocator, buf, data_len, pos))) { LOG_WARN("fail to deserialize cg sstables", K(ret), K(data_len), K(pos)); + } else if (pos < data_len && OB_FAIL(tx_ids_.deserialize(buf, data_len, pos))) { + LOG_WARN("fail to deserialize tx ids", K(ret), K(data_len), K(pos)); } } return ret; @@ -708,6 +720,7 @@ int64_t ObSSTableMeta::get_serialize_size_() const len += data_root_info_.get_serialize_size(); len += macro_info_.get_serialize_size(); len += cg_sstables_.get_serialize_size(); + len += tx_ids_.get_serialize_size(); return len; } @@ -746,6 +759,8 @@ int ObSSTableMeta::deep_copy( LOG_WARN("fail to deep copy macro info", K(ret), KP(buf), K(buf_len), K(pos), K(macro_info_)); } else if (OB_FAIL(cg_sstables_.deep_copy(buf, buf_len, pos, dest->cg_sstables_))) { LOG_WARN("fail to deep copy cg sstables", K(ret), KP(buf), K(buf_len), K(pos), K(cg_sstables_)); + } else if (OB_FAIL(dest->tx_ids_.assign(tx_ids_))) { + LOG_WARN("fail to deep copy cg sstables", K(ret), K(tx_ids_)); } else { dest->is_inited_ = is_inited_; } diff --git a/src/storage/blocksstable/ob_sstable_meta.h b/src/storage/blocksstable/ob_sstable_meta.h index d95b82b7a..43cfe3ef1 100644 --- a/src/storage/blocksstable/ob_sstable_meta.h +++ b/src/storage/blocksstable/ob_sstable_meta.h @@ -154,6 +154,8 @@ public: OB_INLINE const ObSSTableBasicMeta &get_basic_meta() const { return basic_meta_; } OB_INLINE int64_t get_col_checksum_cnt() const { return column_checksum_count_; } OB_INLINE int64_t *get_col_checksum() const { return column_checksums_; } + OB_INLINE int64_t get_tx_id_count() const { return tx_ids_.count(); } + OB_INLINE int64_t get_tx_ids(int64_t idx) const { return tx_ids_.at(idx); } OB_INLINE int64_t get_data_checksum() const { return basic_meta_.data_checksum_; } OB_INLINE int64_t get_rowkey_column_count() const { return basic_meta_.rowkey_column_count_; } OB_INLINE int64_t get_column_count() const { return basic_meta_.column_cnt_; } @@ -243,7 +245,7 @@ public: const int64_t buf_len, int64_t &pos, ObSSTableMeta *&dest) const; - TO_STRING_KV(K_(basic_meta), KP_(column_checksums), K_(column_checksum_count), K_(data_root_info), K_(macro_info), K_(cg_sstables)); + TO_STRING_KV(K_(basic_meta), KP_(column_checksums), K_(column_checksum_count), K_(data_root_info), K_(macro_info), K_(cg_sstables), K_(tx_ids), K_(is_inited)); private: bool check_meta() const; int init_base_meta(const ObTabletCreateSSTableParam ¶m, common::ObArenaAllocator &allocator); @@ -263,6 +265,7 @@ private: private: friend class ObSSTable; static const int64_t SSTABLE_META_VERSION = 1; + static const int64_t MAX_TX_IDS_COUNT = 16; private: ObSSTableBasicMeta basic_meta_; ObRootBlockInfo data_root_info_; @@ -270,6 +273,7 @@ private: ObSSTableArray cg_sstables_; int64_t *column_checksums_; int64_t column_checksum_count_; + ObSEArray tx_ids_; // The following fields don't to persist bool is_inited_; DISALLOW_COPY_AND_ASSIGN(ObSSTableMeta); diff --git a/src/storage/checkpoint/ob_data_checkpoint.cpp b/src/storage/checkpoint/ob_data_checkpoint.cpp index e1b5365ea..53e1ca08a 100644 --- a/src/storage/checkpoint/ob_data_checkpoint.cpp +++ b/src/storage/checkpoint/ob_data_checkpoint.cpp @@ -439,15 +439,16 @@ void ObDataCheckpoint::ls_frozen_to_active_(int64_t &last_time) if (ob_freeze_checkpoint->is_active_checkpoint()) { // avoid new active ob_freeze_checkpoint block minor merge // push back to new_create_list and wait next freeze - if(OB_FAIL(transfer_from_ls_frozen_to_new_created_without_src_lock_(ob_freeze_checkpoint))) { - STORAGE_LOG(WARN, "ob_freeze_checkpoint move to new_created_list failed", - K(ret), K(*ob_freeze_checkpoint)); + if (OB_FAIL(transfer_from_ls_frozen_to_new_created_without_src_lock_(ob_freeze_checkpoint))) { + STORAGE_LOG( + WARN, "ob_freeze_checkpoint move to new_created_list failed", K(ret), K(*ob_freeze_checkpoint)); } - } else { - if (ob_freeze_checkpoint->rec_scn_is_stable() - && OB_FAIL(transfer_from_ls_frozen_to_active_without_src_lock_(ob_freeze_checkpoint))) { + } else if (ob_freeze_checkpoint->rec_scn_is_stable()) { + if (OB_FAIL(transfer_from_ls_frozen_to_active_without_src_lock_(ob_freeze_checkpoint))) { STORAGE_LOG(WARN, "check can freeze failed", K(ret), K(*ob_freeze_checkpoint)); } + } else { + // wait rec scn stable } } ls_frozen_list_is_empty = ls_frozen_list_.is_empty(); @@ -470,7 +471,7 @@ void ObDataCheckpoint::ls_frozen_to_active_(int64_t &last_time) } } while (true); - last_time = common::ObTimeUtility::fast_current_time(); + last_time = ObClockGenerator::getClock(); } void ObDataCheckpoint::ls_frozen_to_prepare_(int64_t &last_time) @@ -496,7 +497,7 @@ void ObDataCheckpoint::ls_frozen_to_prepare_(int64_t &last_time) ls_frozen_list_.get_iterator(iterator); while (iterator.has_next()) { int tmp_ret = OB_SUCCESS; - auto ob_freeze_checkpoint = iterator.get_next(); + ObFreezeCheckpoint *ob_freeze_checkpoint = iterator.get_next(); if (ob_freeze_checkpoint->ready_for_flush()) { if (OB_FAIL(ob_freeze_checkpoint->finish_freeze())) { STORAGE_LOG(WARN, "finish freeze failed", K(ret)); @@ -578,7 +579,7 @@ int ObDataCheckpoint::decide_freeze_clock_(ObFreezeCheckpoint *ob_freeze_checkpo { int ret = OB_SUCCESS; ObFreezer *freezer = nullptr; - memtable::ObMemtable *memtable = nullptr; + ObITabletMemtable *tablet_memtable = nullptr; if (OB_ISNULL(ls_) || OB_ISNULL(ob_freeze_checkpoint)) { ret = OB_ERR_UNEXPECTED; @@ -587,12 +588,12 @@ int ObDataCheckpoint::decide_freeze_clock_(ObFreezeCheckpoint *ob_freeze_checkpo } else if (OB_ISNULL(freezer)) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "freezer cannot be null", K(ret)); - } else if (FALSE_IT(memtable = static_cast(ob_freeze_checkpoint))) { + } else if (FALSE_IT(tablet_memtable = static_cast(ob_freeze_checkpoint))) { } else { // freeze_snapshot_version requires that two memtables of a tablet // cannot join in the same logstream_freeze task // otherwise freeze_snapshot_version of the old memtable will be too large - (void)memtable->set_freeze_clock(freezer->get_freeze_clock()); + (void)tablet_memtable->set_freeze_clock(freezer->get_freeze_clock()); } return ret; @@ -650,12 +651,12 @@ int ObDataCheckpoint::traversal_flush_() && iterator.has_next() && MAX_DATA_CHECKPOINT_FLUSH_COUNT >= flush_tasks.count()) { ObFreezeCheckpoint *ob_freeze_checkpoint = iterator.get_next(); - memtable::ObMemtable *memtable = static_cast(ob_freeze_checkpoint); + ObITabletMemtable *tablet_memtable = static_cast(ob_freeze_checkpoint); ObTableHandleV2 handle; - if (OB_FAIL(handle.set_table(memtable, t3m, ObITable::TableType::DATA_MEMTABLE))) { - STORAGE_LOG(WARN, "set table handle fail", K(ret), KPC(memtable)); - } else if (!memtable->get_is_flushed() && OB_FAIL(flush_tasks.push_back(handle))) { - TRANS_LOG(WARN, "add table to flush tasks failed", KPC(memtable)); + if (OB_FAIL(handle.set_table(tablet_memtable, t3m, tablet_memtable->get_table_type()))) { + STORAGE_LOG(WARN, "set table handle fail", K(ret), KPC(tablet_memtable)); + } else if (!tablet_memtable->get_is_flushed() && OB_FAIL(flush_tasks.push_back(handle))) { + TRANS_LOG(WARN, "add table to flush tasks failed", KPC(tablet_memtable)); } } } @@ -665,9 +666,9 @@ int ObDataCheckpoint::traversal_flush_() if (0 < flush_tasks.count()) { for (int64_t i = 0; OB_SIZE_OVERFLOW != tmp_ret && i < flush_tasks.count(); i++) { ObITable *table = flush_tasks[i].get_table(); - memtable::ObMemtable *memtable = static_cast(table); + ObITabletMemtable *tablet_memtable = static_cast(table); // Even if flush failed, we can continue to flush the next one except OB_SIZE_OVERFLOW - if (OB_TMP_FAIL(memtable->flush(ls_->get_ls_id())) + if (OB_TMP_FAIL(tablet_memtable->flush(ls_->get_ls_id())) && tmp_ret != OB_NO_NEED_UPDATE) { STORAGE_LOG(WARN, "memtable flush failed", K(tmp_ret), K(ls_->get_ls_id())); } diff --git a/src/storage/checkpoint/ob_freeze_checkpoint.h b/src/storage/checkpoint/ob_freeze_checkpoint.h index 2028141ad..547e00587 100644 --- a/src/storage/checkpoint/ob_freeze_checkpoint.h +++ b/src/storage/checkpoint/ob_freeze_checkpoint.h @@ -97,9 +97,9 @@ public: // Whether the dump conditions are met virtual bool ready_for_flush() = 0; // avoid active checkpoint block minor merge - virtual bool is_frozen_checkpoint() const = 0; + virtual bool is_frozen_checkpoint() = 0; // active checkpoint no need to flush - virtual bool is_active_checkpoint() const = 0; + virtual bool is_active_checkpoint() = 0; // for checkpoint_virtual_table virtual ObTabletID get_tablet_id() const = 0; // register into ObDataCheckpoint diff --git a/src/storage/compaction/ob_basic_tablet_merge_ctx.cpp b/src/storage/compaction/ob_basic_tablet_merge_ctx.cpp index 750bec2d0..5f12eb883 100644 --- a/src/storage/compaction/ob_basic_tablet_merge_ctx.cpp +++ b/src/storage/compaction/ob_basic_tablet_merge_ctx.cpp @@ -60,6 +60,7 @@ ObStaticMergeParam::ObStaticMergeParam(ObTabletMergeDagParam &dag_param) schema_(nullptr), report_(nullptr), snapshot_info_(), + tx_id_(0), multi_version_column_descs_() { merge_scn_.set_max(); @@ -79,6 +80,7 @@ void ObStaticMergeParam::reset() co_major_merge_type_ = ObCOMajorMergePolicy::INVALID_CO_MAJOR_MERGE_TYPE; multi_version_column_descs_.reset(); ls_handle_.reset(); // ls_handle could release before tablet_handle + tx_id_ = 0; } bool ObStaticMergeParam::is_valid() const diff --git a/src/storage/compaction/ob_basic_tablet_merge_ctx.h b/src/storage/compaction/ob_basic_tablet_merge_ctx.h index 6cc5a841c..956cabf1b 100644 --- a/src/storage/compaction/ob_basic_tablet_merge_ctx.h +++ b/src/storage/compaction/ob_basic_tablet_merge_ctx.h @@ -92,6 +92,7 @@ public: const ObStorageSchema *schema_; observer::ObIMetaReport *report_; ObStorageSnapshotInfo snapshot_info_; + int64_t tx_id_; common::ObSEArray multi_version_column_descs_; DISALLOW_COPY_AND_ASSIGN(ObStaticMergeParam); }; diff --git a/src/storage/compaction/ob_compaction_diagnose.cpp b/src/storage/compaction/ob_compaction_diagnose.cpp index d2c64eefa..3f895f10d 100644 --- a/src/storage/compaction/ob_compaction_diagnose.cpp +++ b/src/storage/compaction/ob_compaction_diagnose.cpp @@ -1285,7 +1285,7 @@ int ObCompactionDiagnoseMgr::diagnose_tablet_mini_merge( } else if (nullptr != first_frozen_memtable) { // have frozen memtable bool diagnose_flag = false; ObSSTable *latest_sstable = nullptr; - memtable::ObIMemtable *frozen_memtable = static_cast(first_frozen_memtable); + ObIMemtable *frozen_memtable = static_cast(first_frozen_memtable); if (OB_ISNULL(latest_sstable = static_cast( table_store_wrapper.get_member()->get_minor_sstables().get_boundary_table(true/*last*/)))) { diagnose_flag = true; diff --git a/src/storage/compaction/ob_partition_merge_iter.cpp b/src/storage/compaction/ob_partition_merge_iter.cpp index e3d169cac..2e8af02dd 100644 --- a/src/storage/compaction/ob_partition_merge_iter.cpp +++ b/src/storage/compaction/ob_partition_merge_iter.cpp @@ -1731,7 +1731,7 @@ int ObPartitionMinorRowMergeIter::collect_tnode_dml_stat( /* *ObPartitionMinorMacroMergeIter */ -ObPartitionMinorMacroMergeIter::ObPartitionMinorMacroMergeIter(common::ObIAllocator &allocator) +ObPartitionMinorMacroMergeIter::ObPartitionMinorMacroMergeIter(common::ObIAllocator &allocator, bool reuse_uncommit_row) : ObPartitionMinorRowMergeIter(allocator), macro_block_iter_(nullptr), curr_block_desc_(), @@ -1740,7 +1740,8 @@ ObPartitionMinorMacroMergeIter::ObPartitionMinorMacroMergeIter(common::ObIAlloca last_macro_block_reused_(-1), last_macro_block_recycled_(false), last_mvcc_row_already_output_(true), - have_macro_output_row_(false) + have_macro_output_row_(false), + reuse_uncommit_row_(reuse_uncommit_row) { curr_block_desc_.macro_meta_ = &curr_block_meta_; } @@ -1822,12 +1823,13 @@ int ObPartitionMinorMacroMergeIter::check_need_open_curr_macro_block(bool &need) { int ret = OB_SUCCESS; need = false; - if (curr_block_desc_.contain_uncommitted_row_) { + if (!reuse_uncommit_row_ && curr_block_desc_.contain_uncommitted_row_) { need = true; LOG_INFO("need rewrite one dirty macro", K_(curr_block_desc)); - } else if ((last_macro_block_recycled_ && !last_mvcc_row_already_output_) || - (!curr_block_desc_.contain_uncommitted_row_ && - curr_block_desc_.max_merged_trans_version_ <= access_context_.trans_version_range_.base_version_)) { + //TODO:only for recyle multi version row + // } else if ((last_macro_block_recycled_ && !last_mvcc_row_already_output_) || + // (!curr_block_desc_.contain_uncommitted_row_ && + // curr_block_desc_.max_merged_trans_version_ <= access_context_.trans_version_range_.base_version_)) { // 1. last_macro_recycled and current_macro can not be recycled: // need to open to recycle left rows of the last rowkey in recycled macro block // 2. last_macro_reused and current can be recycled: need to open to recycle micro blocks diff --git a/src/storage/compaction/ob_partition_merge_iter.h b/src/storage/compaction/ob_partition_merge_iter.h index 7976f03af..af26b095e 100644 --- a/src/storage/compaction/ob_partition_merge_iter.h +++ b/src/storage/compaction/ob_partition_merge_iter.h @@ -331,7 +331,7 @@ protected: class ObPartitionMinorMacroMergeIter : public ObPartitionMinorRowMergeIter { public: - ObPartitionMinorMacroMergeIter(common::ObIAllocator &allocator); + ObPartitionMinorMacroMergeIter(common::ObIAllocator &allocator, bool reuse_uncommit_row = false); virtual ~ObPartitionMinorMacroMergeIter(); virtual void reset() override; virtual int next() override; @@ -348,7 +348,7 @@ public: INHERIT_TO_STRING_KV("ObPartitionMinorMacroMergeIter", ObPartitionMinorRowMergeIter, K_(macro_block_opened), K_(curr_block_desc), K_(curr_block_meta), K_(macro_block_iter), - K_(last_macro_block_reused), K_(last_macro_block_recycled), K_(last_mvcc_row_already_output), K_(have_macro_output_row)); + K_(last_macro_block_reused), K_(last_macro_block_recycled), K_(last_mvcc_row_already_output), K_(have_macro_output_row), K_(reuse_uncommit_row)); protected: virtual int inner_init(const ObMergeParameter &merge_param) override; virtual bool inner_check(const ObMergeParameter &merge_param) override; @@ -369,6 +369,7 @@ private: bool last_macro_block_recycled_; bool last_mvcc_row_already_output_; bool have_macro_output_row_; + const bool reuse_uncommit_row_; }; static const int64_t DEFAULT_ITER_COUNT = 16; diff --git a/src/storage/compaction/ob_partition_merge_policy.cpp b/src/storage/compaction/ob_partition_merge_policy.cpp index 7b8946e11..e35c19e24 100644 --- a/src/storage/compaction/ob_partition_merge_policy.cpp +++ b/src/storage/compaction/ob_partition_merge_policy.cpp @@ -286,17 +286,23 @@ int ObPartitionMergePolicy::find_mini_merge_tables( // Freezing in the restart phase may not satisfy end >= last_max_sstable, // so the memtable cannot be filtered by scn // can only take out all frozen memtable - ObIMemtable *memtable = nullptr; + ObITabletMemtable *memtable = nullptr; const ObTabletID &tablet_id = tablet.get_tablet_meta().tablet_id_; bool has_release_memtable = false; for (int64_t i = 0; OB_SUCC(ret) && i < memtable_handles.count(); ++i) { - if (OB_ISNULL(memtable = static_cast(memtable_handles.at(i).get_table()))) { + if (OB_ISNULL(memtable = static_cast(memtable_handles.at(i).get_table()))) { ret = OB_ERR_SYS; LOG_ERROR("memtable must not null", K(ret), K(tablet)); + } else if (memtable->is_direct_load_memtable()) { + FLOG_INFO("mini merge only flush data memtables", K(i), K(memtable_handles), KP(memtable)); + break; } else if (OB_UNLIKELY(memtable->is_active_memtable())) { LOG_DEBUG("skip active memtable", K(i), KPC(memtable), K(memtable_handles)); break; + } else if (OB_UNLIKELY(memtable->is_direct_load_memtable())) { + LOG_DEBUG("skip direct load memtable", K(i), KPC(memtable), K(memtable_handles)); + break; } else if (!memtable->can_be_minor_merged()) { FLOG_INFO("memtable cannot mini merge now", K(ret), K(i), KPC(memtable), K(max_snapshot_version), K(memtable_handles), K(param)); break; diff --git a/src/storage/compaction/ob_partition_merge_progress.cpp b/src/storage/compaction/ob_partition_merge_progress.cpp index fedb7ad36..afb80f3b5 100644 --- a/src/storage/compaction/ob_partition_merge_progress.cpp +++ b/src/storage/compaction/ob_partition_merge_progress.cpp @@ -149,7 +149,7 @@ int ObPartitionMergeProgress::estimate_mini_merge( ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null data memtable", K(ret), KPC(tables.at(0))); } else { - const memtable::ObMtStat &mt_stat = data_memtable->get_mt_stat(); + const ObMtStat &mt_stat = data_memtable->get_mt_stat(); estimate_row_cnt_ = MAX(1, mt_stat.insert_row_count_ + mt_stat.update_row_count_ + mt_stat.delete_row_count_); for (int64_t i = tables.count() - 1; OB_SUCC(ret) && i >= 0; --i) { diff --git a/src/storage/compaction/ob_partition_parallel_merge_ctx.cpp b/src/storage/compaction/ob_partition_parallel_merge_ctx.cpp index a003f1f66..c8dc8b9c4 100644 --- a/src/storage/compaction/ob_partition_parallel_merge_ctx.cpp +++ b/src/storage/compaction/ob_partition_parallel_merge_ctx.cpp @@ -263,7 +263,7 @@ int ObParallelMergeCtx::init_parallel_major_merge(compaction::ObBasicTabletMerge int ObParallelMergeCtx::init_parallel_mini_merge(compaction::ObBasicTabletMergeCtx &merge_ctx) { int ret = OB_SUCCESS; - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; int64_t total_bytes = 0; int64_t total_rows = 0; // placeholder diff --git a/src/storage/compaction/ob_partition_rows_merger.cpp b/src/storage/compaction/ob_partition_rows_merger.cpp index 6ffe4054c..bb35002a4 100644 --- a/src/storage/compaction/ob_partition_rows_merger.cpp +++ b/src/storage/compaction/ob_partition_rows_merger.cpp @@ -970,6 +970,7 @@ ObPartitionMergeIter *ObPartitionMinorMergeHelper::alloc_merge_iter(const ObMerg const bool is_small_sstable, const ObITable *table) { + int ret = OB_SUCCESS; UNUSEDx(is_base_iter); const ObStaticMergeParam &static_param = merge_param.static_param_; ObPartitionMergeIter *merge_iter = nullptr; @@ -979,7 +980,22 @@ ObPartitionMergeIter *ObPartitionMinorMergeHelper::alloc_merge_iter(const ObMerg && !is_mini_merge(static_param.get_merge_type()) && !static_param.is_full_merge_ && static_param.sstable_logic_seq_ < ObMacroDataSeq::MAX_SSTABLE_SEQ) { - merge_iter = alloc_helper(allocator_, allocator_); + ObSSTableMetaHandle meta_handle; + bool reuse_uncommit_row = false; + if (!transaction::ObTransID(static_param.tx_id_).is_valid() || !static_cast(table)->contain_uncommitted_row()) { + reuse_uncommit_row = false; + }else if (OB_FAIL(static_cast(table)->get_meta(meta_handle))) { + STORAGE_LOG(ERROR, "fail to get meta", K(ret), KPC(table)); + } else if (meta_handle.get_sstable_meta().get_tx_id_count() > 0) { + const int64_t tx_id = meta_handle.get_sstable_meta().get_tx_ids(0); + if (OB_UNLIKELY(meta_handle.get_sstable_meta().get_tx_id_count() != 1)) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "unexpected tx id count", K(ret), KPC(table), KPC(meta_handle.meta_)); + } else { + reuse_uncommit_row = tx_id == static_param.tx_id_; + } + } + merge_iter = alloc_helper(allocator_, allocator_, reuse_uncommit_row); } else { merge_iter = alloc_helper(allocator_, allocator_); } diff --git a/src/storage/compaction/ob_tablet_merge_ctx.cpp b/src/storage/compaction/ob_tablet_merge_ctx.cpp index 280307544..7f0d00d88 100644 --- a/src/storage/compaction/ob_tablet_merge_ctx.cpp +++ b/src/storage/compaction/ob_tablet_merge_ctx.cpp @@ -338,6 +338,73 @@ int ObTabletExeMergeCtx::get_merge_tables(ObGetMergeTablesResult &get_merge_tabl return ret; } +int ObTabletExeMergeCtx::cal_merge_param() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(static_param_.cal_minor_merge_param())) { + LOG_WARN("failed to cal_major_merge_param", KR(ret)); + } else if (is_minor_merge(static_param_.get_merge_type())) { + if (OB_FAIL(init_static_param_tx_id())) { + LOG_WARN("failed to init_static_param_tx_id", KR(ret)); + } + } + return ret; +} + +int ObTabletExeMergeCtx::init_static_param_tx_id() +{ + int ret = OB_SUCCESS; + ObTxTableGuard tx_table_guard; + const storage::ObTablesHandleArray &tables_handle = static_param_.tables_handle_; + const int64_t table_cnt = tables_handle.get_count(); + ObITable *table = nullptr; + ObLS *ls = nullptr; + ObSSTableMetaHandle meta_handle; + int64_t &static_param_tx_id = static_param_.tx_id_; + + if (OB_ISNULL(ls = static_param_.ls_handle_.get_ls())) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "ls is null", K(ret)); + } else if (OB_FAIL(ls->get_tx_table_guard(tx_table_guard))) { + STORAGE_LOG(WARN, "get_tx_table_guard from log stream fail.", K(ret), K(*ls)); + } + + static_param_tx_id = 0; + for (int64_t i = 0; i < table_cnt && OB_SUCC(ret); i++) { + if (OB_ISNULL(table = tables_handle.get_table(i)) || OB_UNLIKELY(!table->is_sstable())) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "unexpected null table", K(ret), K(i), KPC(table)); + } else if (!static_cast(table)->contain_uncommitted_row()) { + //continue + } else if (OB_FAIL(static_cast(table)->get_meta(meta_handle))) { + STORAGE_LOG(WARN, "fail to get meta", K(ret), K(i), KPC(table)); + } else if (meta_handle.get_sstable_meta().get_tx_id_count() > 0) { + const int64_t tx_id = meta_handle.get_sstable_meta().get_tx_ids(0); + int64_t state = 0; + share::SCN trans_version; + if (OB_UNLIKELY(meta_handle.get_sstable_meta().get_tx_id_count() != 1)) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "unexpected tx id count", K(ret), K(i), KPC(table), KPC(meta_handle.meta_)); + } else if (tx_id == static_param_tx_id) { + //continue + } else if (OB_FAIL(tx_table_guard.get_tx_state_with_scn(transaction::ObTransID(tx_id), + static_param_.merge_scn_, state, trans_version))) { + STORAGE_LOG(WARN, "fail to get tx state", K(ret), K(tx_id), K(static_param_.merge_scn_)); + } else if (state == ObTxData::RUNNING) { + if (OB_UNLIKELY(transaction::ObTransID(static_param_tx_id).is_valid())) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "unexpected tx id", K(ret), K(static_param_tx_id), K(tx_id), K(tables_handle)); + } else { + static_param_tx_id = tx_id; + } + } + } + } + + STORAGE_LOG(INFO, "finish tx id init", K(ret), K(static_param_tx_id)); + return ret; +} + int ObTabletExeMergeCtx::get_tables_by_key(ObGetMergeTablesResult &get_merge_table_result) { int ret = OB_SUCCESS; diff --git a/src/storage/compaction/ob_tablet_merge_ctx.h b/src/storage/compaction/ob_tablet_merge_ctx.h index d1f44379e..257c7bb77 100644 --- a/src/storage/compaction/ob_tablet_merge_ctx.h +++ b/src/storage/compaction/ob_tablet_merge_ctx.h @@ -83,9 +83,11 @@ struct ObTabletExeMergeCtx : public ObTabletMergeCtx DEFAULT_CONSTRUCTOR(ObTabletExeMergeCtx, ObTabletMergeCtx); protected: virtual int get_merge_tables(ObGetMergeTablesResult &get_merge_table_result) override; + virtual int cal_merge_param() override; private: int get_tables_by_key(ObGetMergeTablesResult &get_merge_table_result); int prepare_compaction_filter(); // for tx_minor + int init_static_param_tx_id(); }; struct ObTabletMajorMergeCtx : public ObTabletMergeCtx diff --git a/src/storage/compaction/ob_tenant_tablet_scheduler.cpp b/src/storage/compaction/ob_tenant_tablet_scheduler.cpp index 7acedb939..4079d2287 100644 --- a/src/storage/compaction/ob_tenant_tablet_scheduler.cpp +++ b/src/storage/compaction/ob_tenant_tablet_scheduler.cpp @@ -130,7 +130,7 @@ int ObFastFreezeChecker::check_need_fast_freeze( } void ObFastFreezeChecker::check_hotspot_need_fast_freeze( - const memtable::ObMemtable &memtable, + memtable::ObMemtable &memtable, bool &need_fast_freeze) { need_fast_freeze = false; @@ -141,7 +141,7 @@ void ObFastFreezeChecker::check_hotspot_need_fast_freeze( void ObFastFreezeChecker::check_tombstone_need_fast_freeze( const ObTablet &tablet, - const memtable::ObMemtable &memtable, + memtable::ObMemtable &memtable, bool &need_fast_freeze) { need_fast_freeze = false; @@ -149,7 +149,7 @@ void ObFastFreezeChecker::check_tombstone_need_fast_freeze( const common::ObTabletID &tablet_id = tablet.get_tablet_meta().tablet_id_; if (memtable.is_active_memtable()) { - const memtable::ObMtStat &mt_stat = memtable.get_mt_stat(); // dirty read + const ObMtStat &mt_stat = memtable.get_mt_stat(); // dirty read int64_t adaptive_threshold = TOMBSTONE_DEFAULT_ROW_COUNT; try_update_tablet_threshold(ObTabletStatKey(ls_id, tablet_id), mt_stat, memtable.get_timestamp(), adaptive_threshold); @@ -173,7 +173,7 @@ void ObFastFreezeChecker::check_tombstone_need_fast_freeze( void ObFastFreezeChecker::try_update_tablet_threshold( const ObTabletStatKey &key, - const memtable::ObMtStat &mt_stat, + const ObMtStat &mt_stat, const int64_t memtable_create_timestamp, int64_t &adaptive_threshold) { diff --git a/src/storage/compaction/ob_tenant_tablet_scheduler.h b/src/storage/compaction/ob_tenant_tablet_scheduler.h index 089898489..1c5fab072 100644 --- a/src/storage/compaction/ob_tenant_tablet_scheduler.h +++ b/src/storage/compaction/ob_tenant_tablet_scheduler.h @@ -36,7 +36,6 @@ class MacroBlockId; namespace memtable { class ObMemtable; -struct ObMtStat; } namespace storage { @@ -62,15 +61,15 @@ public: TO_STRING_KV(K_(enable_fast_freeze)); private: void check_hotspot_need_fast_freeze( - const memtable::ObMemtable &memtable, + memtable::ObMemtable &memtable, bool &need_fast_freeze); void check_tombstone_need_fast_freeze( const storage::ObTablet &tablet, - const memtable::ObMemtable &memtable, + memtable::ObMemtable &memtable, bool &need_fast_freeze); void try_update_tablet_threshold( const storage::ObTabletStatKey &key, - const memtable::ObMtStat &mt_stat, + const storage::ObMtStat &mt_stat, const int64_t memtable_create_timestamp, int64_t &adaptive_threshold); private: diff --git a/src/storage/ddl/ob_complement_data_task.cpp b/src/storage/ddl/ob_complement_data_task.cpp index 523425ea7..d75815b8d 100644 --- a/src/storage/ddl/ob_complement_data_task.cpp +++ b/src/storage/ddl/ob_complement_data_task.cpp @@ -1333,7 +1333,6 @@ int ObComplementWriteTask::append_row(ObScan *scan) HEAP_VAR(ObWholeDataStoreDesc, data_desc, true) { ObArray report_col_checksums; ObArray report_col_ids; - ObDDLRedoLogWriter sstable_redo_writer; ObDDLRedoLogWriterCallback callback; ObITable::TableKey hidden_table_key; ObMacroDataSeq macro_start_seq(0); @@ -1407,8 +1406,6 @@ int ObComplementWriteTask::append_row(ObScan *scan) } else if (OB_UNLIKELY(!hidden_table_key.is_valid())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("hidden table key is invalid", K(ret), K(hidden_table_key)); - } else if (OB_FAIL(sstable_redo_writer.init(param_->dest_ls_id_, param_->dest_tablet_id_))) { - LOG_WARN("fail to init sstable redo writer", K(ret)); } else if (OB_ISNULL(current_dag = static_cast(get_dag()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("the dag of this task is null", K(ret)); @@ -1430,12 +1427,13 @@ int ObComplementWriteTask::append_row(ObScan *scan) } else if (OB_UNLIKELY(context_->start_scn_ != direct_load_hdl.get_full_obj()->get_start_scn())) { ret = OB_TASK_EXPIRED; LOG_WARN("task expired", K(ret), K(context_->start_scn_), "start_scn", direct_load_hdl.get_full_obj()->get_start_scn()); - } else if (OB_FAIL(callback.init(DDL_MB_DATA_TYPE, + } else if (OB_FAIL(callback.init(param_->dest_ls_id_, + param_->dest_tablet_id_, + DDL_MB_DATA_TYPE, hidden_table_key, param_->task_id_, context_->start_scn_, - param_->data_format_version_, - &sstable_redo_writer))) { + param_->data_format_version_))) { LOG_WARN("fail to init data callback", K(ret), K(hidden_table_key)); } else if (OB_FAIL(writer.open(data_desc.get_desc(), macro_start_seq, &callback))) { LOG_WARN("fail to open macro block writer", K(ret), K(data_desc)); diff --git a/src/storage/ddl/ob_ddl_clog.cpp b/src/storage/ddl/ob_ddl_clog.cpp index 25466cb2d..524516f95 100644 --- a/src/storage/ddl/ob_ddl_clog.cpp +++ b/src/storage/ddl/ob_ddl_clog.cpp @@ -26,6 +26,7 @@ namespace oceanbase using namespace blocksstable; using namespace share; +using namespace common; namespace storage { @@ -170,7 +171,7 @@ ObDDLMacroBlockClogCb::~ObDDLMacroBlockClogCb() } int ObDDLMacroBlockClogCb::init(const share::ObLSID &ls_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const blocksstable::MacroBlockId ¯o_block_id, ObTabletHandle &tablet_handle) { @@ -429,7 +430,7 @@ ObDDLRedoLog::ObDDLRedoLog() { } -int ObDDLRedoLog::init(const blocksstable::ObDDLMacroBlockRedoInfo &redo_info) +int ObDDLRedoLog::init(const storage::ObDDLMacroBlockRedoInfo &redo_info) { int ret = OB_SUCCESS; if (!redo_info.is_valid()) { @@ -467,7 +468,6 @@ int ObDDLCommitLog::init(const ObITable::TableKey &table_key, OB_SERIALIZE_MEMBER(ObDDLCommitLog, table_key_, start_scn_, lob_meta_tablet_id_); - ObTabletSchemaVersionChangeLog::ObTabletSchemaVersionChangeLog() : tablet_id_(), schema_version_(-1) { diff --git a/src/storage/ddl/ob_ddl_clog.h b/src/storage/ddl/ob_ddl_clog.h index cc7fe3b71..7625b2d38 100644 --- a/src/storage/ddl/ob_ddl_clog.h +++ b/src/storage/ddl/ob_ddl_clog.h @@ -114,7 +114,7 @@ public: ObDDLMacroBlockClogCb(); virtual ~ObDDLMacroBlockClogCb(); int init(const share::ObLSID &ls_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const blocksstable::MacroBlockId ¯o_block_id, ObTabletHandle &tablet_handle); virtual int on_success() override; @@ -128,7 +128,7 @@ private: bool is_inited_; ObDDLClogCbStatus status_; share::ObLSID ls_id_; - blocksstable::ObDDLMacroBlockRedoInfo redo_info_; + storage::ObDDLMacroBlockRedoInfo redo_info_; blocksstable::MacroBlockId macro_block_id_; ObSpinLock data_buffer_lock_; bool is_data_buffer_freed_; @@ -217,13 +217,13 @@ class ObDDLRedoLog final public: ObDDLRedoLog(); ~ObDDLRedoLog() = default; - int init(const blocksstable::ObDDLMacroBlockRedoInfo &redo_info); + int init(const storage::ObDDLMacroBlockRedoInfo &redo_info); bool is_valid() const { return redo_info_.is_valid(); } - blocksstable::ObDDLMacroBlockRedoInfo get_redo_info() const { return redo_info_; } + storage::ObDDLMacroBlockRedoInfo get_redo_info() const { return redo_info_; } TO_STRING_KV(K_(redo_info)); OB_UNIS_VERSION_V(1); private: - blocksstable::ObDDLMacroBlockRedoInfo redo_info_; + storage::ObDDLMacroBlockRedoInfo redo_info_; }; class ObDDLCommitLog final diff --git a/src/storage/ddl/ob_ddl_inc_clog.cpp b/src/storage/ddl/ob_ddl_inc_clog.cpp new file mode 100644 index 000000000..ff55d306a --- /dev/null +++ b/src/storage/ddl/ob_ddl_inc_clog.cpp @@ -0,0 +1,104 @@ +/** + * 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. + */ + +#define USING_LOG_PREFIX STORAGE + +#include "storage/ddl/ob_ddl_inc_clog.h" +#include "lib/hash/ob_link_hashmap.h" +#include "lib/oblog/ob_log_module.h" + +namespace oceanbase +{ +namespace storage +{ + +using namespace blocksstable; +using namespace share; +using namespace common; + +ObDDLIncLogBasic::ObDDLIncLogBasic() + : tablet_id_(), lob_meta_tablet_id_() +{ +} + +int ObDDLIncLogBasic::init(const ObTabletID &tablet_id, const ObTabletID &lob_meta_tablet_id) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!tablet_id.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KR(ret), K(tablet_id)); + } else { + tablet_id_ = tablet_id; + lob_meta_tablet_id_ = lob_meta_tablet_id; + } + + return ret; +} + +uint64_t ObDDLIncLogBasic::hash() const +{ + uint64_t hash_val = 0; + hash_val = common::murmurhash(&tablet_id_, sizeof(tablet_id_), hash_val); + hash_val = common::murmurhash(&lob_meta_tablet_id_, sizeof(lob_meta_tablet_id_), hash_val); + return hash_val; +} + +int ObDDLIncLogBasic::hash(uint64_t &hash_val) const +{ + hash_val = hash(); + return OB_SUCCESS; +} + +OB_SERIALIZE_MEMBER(ObDDLIncLogBasic, tablet_id_, lob_meta_tablet_id_); + +ObDDLIncStartLog::ObDDLIncStartLog() + : log_basic_() +{ +} + +int ObDDLIncStartLog::init(const ObDDLIncLogBasic &log_basic) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!log_basic.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KR(ret), K(log_basic)); + } else { + log_basic_ = log_basic; + } + + return ret; +} + +OB_SERIALIZE_MEMBER(ObDDLIncStartLog, log_basic_); + +ObDDLIncCommitLog::ObDDLIncCommitLog() + : log_basic_() +{ +} + +int ObDDLIncCommitLog::init(const ObDDLIncLogBasic &log_basic) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!log_basic.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KR(ret), K(log_basic)); + } else { + log_basic_ = log_basic; + } + + return ret; +} + +OB_SERIALIZE_MEMBER(ObDDLIncCommitLog, log_basic_); + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_inc_clog.h b/src/storage/ddl/ob_ddl_inc_clog.h new file mode 100644 index 000000000..b2a0c2032 --- /dev/null +++ b/src/storage/ddl/ob_ddl_inc_clog.h @@ -0,0 +1,79 @@ +/** + * 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. + */ + +#pragma once + +#include "lib/oblog/ob_log_print_kv.h" +#include "common/ob_tablet_id.h" + +namespace oceanbase +{ +namespace storage +{ +class ObDDLIncLogBasic final +{ + OB_UNIS_VERSION_V(1); +public: + ObDDLIncLogBasic(); + ~ObDDLIncLogBasic() = default; + int init(const ObTabletID &tablet_id, + const ObTabletID &lob_meta_tablet_id); + uint64_t hash() const; + int hash(uint64_t &hash_val) const; + void reset() + { + tablet_id_.reset(); + lob_meta_tablet_id_.reset(); + } + bool operator ==(const ObDDLIncLogBasic &other) const + { + return tablet_id_ == other.get_tablet_id() && lob_meta_tablet_id_ == other.get_lob_meta_tablet_id(); + } + bool is_valid() const { return tablet_id_.is_valid(); } + const ObTabletID &get_tablet_id() const { return tablet_id_; } + const ObTabletID &get_lob_meta_tablet_id() const { return lob_meta_tablet_id_; } + TO_STRING_KV(K_(tablet_id), K_(lob_meta_tablet_id)); +private: + ObTabletID tablet_id_; + ObTabletID lob_meta_tablet_id_; +}; + +class ObDDLIncStartLog final +{ + OB_UNIS_VERSION_V(1); +public: + ObDDLIncStartLog(); + ~ObDDLIncStartLog() = default; + int init(const ObDDLIncLogBasic &log_basic); + bool is_valid() const { return log_basic_.is_valid(); } + const ObDDLIncLogBasic &get_log_basic() const { return log_basic_; } + TO_STRING_KV(K_(log_basic)); +private: + ObDDLIncLogBasic log_basic_; +}; + +class ObDDLIncCommitLog final +{ + OB_UNIS_VERSION_V(1); +public: + ObDDLIncCommitLog(); + ~ObDDLIncCommitLog() = default; + int init(const ObDDLIncLogBasic &log_basic); + bool is_valid() const { return log_basic_.is_valid(); } + const ObDDLIncLogBasic &get_log_basic() const { return log_basic_; } + TO_STRING_KV(K_(log_basic)); +private: + ObDDLIncLogBasic log_basic_; +}; + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_inc_clog_callback.cpp b/src/storage/ddl/ob_ddl_inc_clog_callback.cpp new file mode 100644 index 000000000..635f933c5 --- /dev/null +++ b/src/storage/ddl/ob_ddl_inc_clog_callback.cpp @@ -0,0 +1,241 @@ +/** + * 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. + */ + +#define USING_LOG_PREFIX STORAGE + +#include "lib/allocator/ob_malloc.h" +#include "storage/ddl/ob_ddl_inc_clog_callback.h" +#include "storage/tx_storage/ob_ls_service.h" + +namespace oceanbase +{ +namespace storage +{ + +using namespace blocksstable; +using namespace share; +using namespace common; + +ObDDLIncStartClogCb::ObDDLIncStartClogCb() + : is_inited_(false), log_basic_(), scn_(SCN::min_scn()) +{ +} + +int ObDDLIncStartClogCb::init(const ObDDLIncLogBasic& log_basic) +{ + int ret = OB_SUCCESS; + if (IS_INIT) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", K(ret)); + } else if (OB_UNLIKELY(!log_basic.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(log_basic)); + } else { + log_basic_ = log_basic; + is_inited_ = true; + } + + return ret; +} + +int ObDDLIncStartClogCb::on_success() +{ + int ret = OB_SUCCESS; + common::ObTimeGuard timeguard("ObDDLIncStartClogCb::on_success", 1 * 1000 * 1000); // 1s + scn_ = __get_scn(); + status_.set_ret_code(ret); + status_.set_state(STATE_SUCCESS); + try_release(); + + return OB_SUCCESS; +} + +int ObDDLIncStartClogCb::on_failure() +{ + int ret = OB_SUCCESS; + status_.set_state(STATE_FAILED); + try_release(); + + return OB_SUCCESS; +} + +void ObDDLIncStartClogCb::try_release() +{ + if (status_.try_set_release_flag()) { + } else { + ObDDLIncStartClogCb *cb = this; + ob_delete(cb); + } +} + +ObDDLIncRedoClogCb::ObDDLIncRedoClogCb() + : is_inited_(false), ls_id_(), redo_info_(), macro_block_id_(), + data_buffer_lock_(), is_data_buffer_freed_(false) +{ + +} + +ObDDLIncRedoClogCb::~ObDDLIncRedoClogCb() +{ + int ret = OB_SUCCESS; + if (macro_block_id_.is_valid() && OB_FAIL(OB_SERVER_BLOCK_MGR.dec_ref(macro_block_id_))) { + LOG_ERROR("dec ref failed", K(ret), K(macro_block_id_), K(common::lbt())); + } + macro_block_id_.reset(); +} + +int ObDDLIncRedoClogCb::init(const share::ObLSID &ls_id, + const storage::ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + ObTabletHandle &tablet_handle) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", K(ret)); + } else if (OB_UNLIKELY(!ls_id.is_valid() || !redo_info.is_valid() || !macro_block_id.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(ls_id), K(redo_info), K(macro_block_id)); + } else if (OB_FAIL(OB_SERVER_BLOCK_MGR.inc_ref(macro_block_id))) { + LOG_WARN("inc reference count failed", K(ret), K(macro_block_id)); + } else { + redo_info_ = redo_info; + ls_id_ = ls_id; + macro_block_id_ = macro_block_id; + tablet_handle_ = tablet_handle; + } + return ret; +} + +void ObDDLIncRedoClogCb::try_release() +{ + { + ObSpinLockGuard data_buffer_guard(data_buffer_lock_); + is_data_buffer_freed_ = true; + } + if (status_.try_set_release_flag()) { + } else { + ObDDLIncRedoClogCb *cb = this; + ob_delete(cb); + } +} + +int ObDDLIncRedoClogCb::on_success() +{ + int ret = OB_SUCCESS; + common::ObTimeGuard timeguard("ObDDLIncRedoClogCb::on_success", 1 * 1000 * 1000); // 1s + ObDDLMacroBlock macro_block; + { + ObSpinLockGuard data_buffer_guard(data_buffer_lock_); + if (is_data_buffer_freed_) { + LOG_INFO("data buffer is freed, do not need to callback"); + } else if (OB_FAIL(macro_block.block_handle_.set_block_id(macro_block_id_))) { + LOG_WARN("set macro block id failed", K(ret), K(macro_block_id_)); + } else { + macro_block.block_type_ = redo_info_.block_type_; + macro_block.logic_id_ = redo_info_.logic_id_; + macro_block.scn_ = __get_scn(); + macro_block.buf_ = redo_info_.data_buffer_.ptr(); + macro_block.size_ = redo_info_.data_buffer_.length(); + macro_block.ddl_start_scn_ = redo_info_.start_scn_; + macro_block.table_key_ = redo_info_.table_key_; + macro_block.end_row_id_ = redo_info_.end_row_id_; + macro_block.trans_id_ = redo_info_.trans_id_; + const int64_t snapshot_version = redo_info_.table_key_.get_snapshot_version(); + const uint64_t data_format_version = redo_info_.data_format_version_; + if (OB_FAIL(tablet_handle_.get_obj()->set_macro_block(macro_block, snapshot_version, data_format_version))) { + LOG_WARN("fail to set macro block", K(ret)); + } + } + } + status_.set_ret_code(ret); + status_.set_state(STATE_SUCCESS); + try_release(); + + return OB_SUCCESS; // force return success +} + +int ObDDLIncRedoClogCb::on_failure() +{ + status_.set_state(STATE_FAILED); + try_release(); + return OB_SUCCESS; +} + +ObDDLIncCommitClogCb::ObDDLIncCommitClogCb() + : is_inited_(false), ls_id_(), log_basic_(), scn_(SCN::min_scn()) +{ +} + +int ObDDLIncCommitClogCb::init(const share::ObLSID &ls_id, const ObDDLIncLogBasic &log_basic) +{ + int ret = OB_SUCCESS; + if (IS_INIT) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", K(ret)); + } else if (OB_UNLIKELY(!ls_id.is_valid() || !log_basic.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(ls_id), K(log_basic)); + } else { + ls_id_ = ls_id; + log_basic_ = log_basic; + is_inited_ = true; + } + + return ret; +} + +int ObDDLIncCommitClogCb::on_success() +{ + int ret = OB_SUCCESS; + common::ObTimeGuard timeguard("ObDDLIncCommitClogCb::on_success", 1 * 1000 * 1000); // 1s + ObLS *ls = nullptr; + ObLSHandle ls_handle; + if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { + LOG_WARN("get ls failed", K(ret), K(ls_id_)); + } else if (OB_ISNULL(ls = ls_handle.get_ls())) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("ls should not be null", K(ret), K(log_basic_.get_tablet_id())); + } else { + (void)ls->async_tablet_freeze_for_direct_load(log_basic_.get_tablet_id()); + if (log_basic_.get_lob_meta_tablet_id().is_valid()) { + (void)ls->async_tablet_freeze_for_direct_load(log_basic_.get_lob_meta_tablet_id()); + } + } + + status_.set_ret_code(ret); + status_.set_state(STATE_SUCCESS); + try_release(); + + return OB_SUCCESS; +} + +int ObDDLIncCommitClogCb::on_failure() +{ + int ret = OB_SUCCESS; + status_.set_state(STATE_FAILED); + try_release(); + + return OB_SUCCESS; +} + +void ObDDLIncCommitClogCb::try_release() +{ + if (status_.try_set_release_flag()) { + } else { + ObDDLIncCommitClogCb *cb = this; + ob_delete(cb); + } +} + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_inc_clog_callback.h b/src/storage/ddl/ob_ddl_inc_clog_callback.h new file mode 100644 index 000000000..a08f9407b --- /dev/null +++ b/src/storage/ddl/ob_ddl_inc_clog_callback.h @@ -0,0 +1,100 @@ +/** + * 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. + */ + +#pragma once + +#include "storage/ddl/ob_ddl_clog.h" +#include "storage/ddl/ob_ddl_struct.h" +#include "storage/ddl/ob_ddl_inc_clog.h" +#include "storage/meta_mem/ob_tablet_handle.h" + +namespace oceanbase +{ +namespace storage +{ + +class ObDDLIncClogCb : public logservice::AppendCb +{ +public: + ObDDLIncClogCb() + : status_() {} + virtual ~ObDDLIncClogCb() = default; + virtual int on_success() override = 0; + virtual int on_failure() override = 0; + virtual void try_release() = 0; + inline bool is_success() const { return status_.is_success(); } + inline bool is_failed() const { return status_.is_failed(); } + inline bool is_finished() const { return status_.is_finished(); } + int get_ret_code() const { return status_.get_ret_code(); } +protected: + ObDDLClogCbStatus status_; +}; + +class ObDDLIncStartClogCb : public ObDDLIncClogCb +{ +public: + ObDDLIncStartClogCb(); + virtual ~ObDDLIncStartClogCb() = default; + int init(const ObDDLIncLogBasic &log_basic); + virtual int on_success() override; + virtual int on_failure() override; + virtual void try_release() override; + share::SCN get_scn() const { return scn_; } + TO_STRING_KV(K(is_inited_), K(log_basic_)); +private: + bool is_inited_; + ObDDLIncLogBasic log_basic_; + share::SCN scn_; +}; + +class ObDDLIncRedoClogCb : public ObDDLIncClogCb +{ +public: + ObDDLIncRedoClogCb(); + virtual ~ObDDLIncRedoClogCb(); + int init(const share::ObLSID &ls_id, + const storage::ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + storage::ObTabletHandle &tablet_handle); + virtual int on_success() override; + virtual int on_failure() override; + virtual void try_release() override; +private: + bool is_inited_; + share::ObLSID ls_id_; + storage::ObDDLMacroBlockRedoInfo redo_info_; + blocksstable::MacroBlockId macro_block_id_; + ObSpinLock data_buffer_lock_; + bool is_data_buffer_freed_; + storage::ObTabletHandle tablet_handle_; +}; + +class ObDDLIncCommitClogCb : public ObDDLIncClogCb +{ +public: + ObDDLIncCommitClogCb(); + virtual ~ObDDLIncCommitClogCb() = default; + int init(const share::ObLSID &ls_id, const ObDDLIncLogBasic &log_basic); + virtual int on_success() override; + virtual int on_failure() override; + virtual void try_release() override; + share::SCN get_scn() const { return scn_; } + TO_STRING_KV(K(is_inited_), K(log_basic_)); +private: + bool is_inited_; + share::ObLSID ls_id_; + ObDDLIncLogBasic log_basic_; + share::SCN scn_; +}; + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_inc_redo_log_writer.cpp b/src/storage/ddl/ob_ddl_inc_redo_log_writer.cpp new file mode 100644 index 000000000..3ec83735e --- /dev/null +++ b/src/storage/ddl/ob_ddl_inc_redo_log_writer.cpp @@ -0,0 +1,747 @@ +/** + * 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. + */ + +#define USING_LOG_PREFIX STORAGE + +#include "storage/ddl/ob_ddl_inc_redo_log_writer.h" +#include "storage/ls/ob_ls_tx_service.h" +#include "storage/tx/ob_trans_part_ctx.h" +#include "storage/tx/ob_trans_service.h" +#include "storage/tx_storage/ob_ls_service.h" + +using namespace oceanbase::common; +using namespace oceanbase::storage; +using namespace oceanbase::archive; +using namespace oceanbase::logservice; +using namespace oceanbase::share; +using namespace oceanbase::blocksstable; +using namespace oceanbase::transaction; + +ObDDLIncLogHandle::ObDDLIncLogHandle() + : cb_(nullptr), scn_(SCN::min_scn()) +{ +} + +ObDDLIncLogHandle::~ObDDLIncLogHandle() +{ + reset(); +} + +void ObDDLIncLogHandle::reset() +{ + if (nullptr != cb_) { + cb_->try_release(); + cb_ = nullptr; + } +} + +int ObDDLIncLogHandle::wait(const int64_t timeout) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(cb_)) { + } else { + bool finish = false; + const int64_t start_time = ObTimeUtility::current_time(); + while (OB_SUCC(ret) && !finish) { + if (OB_FAIL(THIS_WORKER.check_status())) { + LOG_WARN("check status failed", K(ret)); + } else if (cb_->is_success()) { + finish = true; + } else if (cb_->is_failed()) { + ret = OB_NOT_MASTER; + } + if (OB_SUCC(ret) && !finish) { + const int64_t current_time = ObTimeUtility::current_time(); + if (current_time - start_time > timeout) { + ret = OB_TIMEOUT; + LOG_WARN("write ddl redo log timeout", K(ret), K(current_time), K(start_time)); + } else { + if (REACH_TIME_INTERVAL(10L * 1000L * 1000L)) { //10s + LOG_INFO("wait ddl redo log callback", K(ret), K(finish), K(current_time), K(start_time)); + } + ob_usleep(CHECK_DDL_INC_LOG_FINISH_INTERVAL); + } + } + } + } + + return ret; +} + +ObDDLIncRedoLogWriter::ObDDLIncRedoLogWriter() + : is_inited_(false), remote_write_(false), + ls_id_(), tablet_id_(), ddl_inc_log_handle_(), leader_addr_(), leader_ls_id_(), buffer_(nullptr) +{ +} + +ObDDLIncRedoLogWriter::~ObDDLIncRedoLogWriter() +{ + if (nullptr != buffer_) { + ob_free(buffer_); + buffer_ = nullptr; + } +} + +int ObDDLIncRedoLogWriter::init(const ObLSID &ls_id, const ObTabletID &tablet_id) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + LOG_WARN("inited twice", K(ret)); + } else if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(ls_id), K(tablet_id)); + } else { + ls_id_ = ls_id; + tablet_id_ = tablet_id; + is_inited_ = true; + } + return ret; +} + +void ObDDLIncRedoLogWriter::reset() +{ + is_inited_ = false; + remote_write_ = false; + ls_id_.reset(); + tablet_id_.reset(); + ddl_inc_log_handle_.reset(); + leader_addr_.reset(); + leader_ls_id_.reset(); +} + +bool ObDDLIncRedoLogWriter::need_retry(int ret_code, bool allow_remote_write) +{ + return OB_TX_NOLOGCB == ret_code || (allow_remote_write && OB_NOT_MASTER == ret_code); +} + +int ObDDLIncRedoLogWriter::write_inc_start_log( + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc, + SCN &start_scn) +{ + int ret = OB_SUCCESS; + ObDDLIncLogBasic log_basic; + ObDDLIncStartLog log; + start_scn.set_min(); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("not inited", K(ret)); + } else if (OB_UNLIKELY(tx_desc == nullptr)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), KP(tx_desc)); + } else if (OB_FAIL(log_basic.init(tablet_id_, lob_meta_tablet_id))) { + LOG_WARN("fail to init log_basic", K(ret), K(tablet_id_), K(lob_meta_tablet_id)); + } else if (OB_FAIL(log.init(log_basic))) { + LOG_WARN("fail to init DDLIncStartLog", K(ret), K(log_basic)); + } else if (OB_FAIL(local_write_inc_start_log(log, tx_desc, start_scn))) { + LOG_WARN("local write inc start log fail", K(ret)); + } + + return ret; +} + +int ObDDLIncRedoLogWriter::write_inc_redo_log( + const ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + const int64_t task_id, + ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + ObLS *ls = nullptr; + const int64_t BUF_SIZE = 2 * 1024 * 1024 + 16 * 1024; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("not inited", K(ret)); + } else if (OB_UNLIKELY(!redo_info.is_valid() || !macro_block_id.is_valid() || task_id == 0 || OB_ISNULL(tx_desc))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(redo_info), K(macro_block_id), K(task_id), KP(tx_desc)); + } else if (buffer_ == nullptr && OB_ISNULL(buffer_ = static_cast(ob_malloc(BUF_SIZE, ObMemAttr(MTL_ID(), "DDL_REDO_LOG"))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory failed", K(ret), K(BUF_SIZE)); + } else if (OB_FAIL(local_write_inc_redo_log(redo_info, macro_block_id, task_id, tx_desc))) { + LOG_WARN("local write inc redo log fail", K(ret), K(redo_info)); + } else { + LOG_INFO("local write inc redo log success", K(macro_block_id)); + } + + return ret; +} + +int ObDDLIncRedoLogWriter::write_inc_commit_log( + const bool allow_remote_write, + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("not inited", K(ret)); + } else if (OB_UNLIKELY(tx_desc == nullptr)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), KP(tx_desc)); + } else if (!remote_write_) { + ObDDLIncLogBasic log_basic; + ObDDLIncCommitLog log; + if (OB_FAIL(log_basic.init(tablet_id_, lob_meta_tablet_id))) { + LOG_WARN("fail to init log_basic", K(ret), K(tablet_id_), K(lob_meta_tablet_id)); + } else if (OB_FAIL(log.init(log_basic))) { + LOG_WARN("fail to init DDLIncCommitLog", K(ret), K(log_basic)); + } else if (OB_FAIL(local_write_inc_commit_log(log, tx_desc))) { + if (ObDDLUtil::need_remote_write(ret) && allow_remote_write) { + if (OB_FAIL(switch_to_remote_write())) { + LOG_WARN("fail to switch to remote write", K(ret), K(tablet_id_)); + } + } else { + LOG_WARN("local write inc commit log fail", K(ret), K(tablet_id_)); + } + } + } + if (OB_SUCC(ret) && remote_write_) { + if (OB_FAIL(retry_remote_write_inc_commit_log(lob_meta_tablet_id, tx_desc))) { + LOG_WARN("remote write inc commit log fail", K(ret), K(tablet_id_)); + } else { + LOG_INFO("remote write inc commit log success", K(tablet_id_)); + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::wait_inc_redo_log_finish() +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("not inited", K(ret)); + } else if (remote_write_) { + // remote write no need to wait local handle + } else if (OB_UNLIKELY(!ddl_inc_log_handle_.is_valid())) { + // no redo log has been written yet + } else { + common::ObTimeGuard timeguard("write_inc_redo_log wait", 5 * 1000 * 1000); // 5s + if (OB_FAIL(ddl_inc_log_handle_.wait())) { + LOG_WARN("fail to wait io finish", K(ret)); + } else if (OB_FAIL(ddl_inc_log_handle_.cb_->get_ret_code())) { + LOG_WARN("ddl redo callback executed failed", K(ret)); + } else { + ddl_inc_log_handle_.reset(); + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::write_inc_start_log_with_retry( + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc, + share::SCN &start_scn) +{ + int ret = OB_SUCCESS; + int64_t start_ts = ObTimeUtility::fast_current_time(); + const int64_t timeout_us = ObDDLIncRedoLogWriter::DEFAULT_RETRY_TIMEOUT_US; + int64_t retry_count = 0; + do { + if (OB_FAIL(THIS_WORKER.check_status())) { + LOG_WARN("check status failed", K(ret)); + } else if (OB_FAIL(write_inc_start_log(lob_meta_tablet_id, tx_desc, start_scn))) { + LOG_WARN("write inc ddl start log failed", K(ret)); + } + if (ObDDLIncRedoLogWriter::need_retry(ret, false/*allow_remote_write*/)) { + usleep(1000L * 1000L); // 1s + ++retry_count; + LOG_INFO("retry write ddl inc start log", K(ret), K(ls_id_), K(tablet_id_), K(retry_count)); + } else { + break; + } + } while (ObTimeUtility::fast_current_time() - start_ts < timeout_us); + + return ret; +} + +int ObDDLIncRedoLogWriter::write_inc_redo_log_with_retry( + const storage::ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + const int64_t task_id, + transaction::ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + int64_t start_ts = ObTimeUtility::fast_current_time(); + const int64_t timeout_us = ObDDLIncRedoLogWriter::DEFAULT_RETRY_TIMEOUT_US; + int64_t retry_count = 0; + do { + if (OB_FAIL(THIS_WORKER.check_status())) { + LOG_WARN("check status failed", K(ret)); + } else if (OB_FAIL(write_inc_redo_log(redo_info, macro_block_id, task_id, tx_desc))) { + LOG_WARN("write inc ddl redo log failed", K(ret)); + } + if (ObDDLIncRedoLogWriter::need_retry(ret, false/*allow_remote_write*/)) { + usleep(1000L * 1000L); // 1s + ++retry_count; + LOG_INFO("retry write ddl inc start log", K(ret), K(ls_id_), K(tablet_id_), K(retry_count)); + } else { + break; + } + } while (ObTimeUtility::fast_current_time() - start_ts < timeout_us); + + return ret; +} + +int ObDDLIncRedoLogWriter::write_inc_commit_log_with_retry( + const bool allow_remote_write, + const ObTabletID &lob_meta_tablet_id, + ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + int64_t start_ts = ObTimeUtility::fast_current_time(); + const int64_t timeout_us = ObDDLIncRedoLogWriter::DEFAULT_RETRY_TIMEOUT_US; + int64_t retry_count = 0; + do { + if (OB_FAIL(THIS_WORKER.check_status())) { + LOG_WARN("check status failed", K(ret)); + } else if (OB_FAIL(write_inc_commit_log(allow_remote_write, lob_meta_tablet_id, tx_desc))) { + LOG_WARN("write inc ddl commit log failed", K(ret)); + } + if (ObDDLIncRedoLogWriter::need_retry(ret, allow_remote_write)) { + usleep(1000L * 1000L); // 1s + ++retry_count; + LOG_INFO("retry write ddl commit log", K(ret), K(ls_id_), K(tablet_id_), K(retry_count)); + } else { + break; + } + } while (ObTimeUtility::fast_current_time() - start_ts < timeout_us); + + return ret; +} + +int ObDDLIncRedoLogWriter::get_write_store_ctx_guard( + ObTxDesc *tx_desc, + ObStoreCtxGuard &ctx_guard, + storage::ObLS *&ls) +{ + int ret = OB_SUCCESS; + ObStoreCtx &ctx = ctx_guard.get_store_ctx(); + if (OB_NOT_NULL(ls)) { + ls->reset(); + ls = nullptr; + } + if (OB_FAIL(ctx_guard.init(ls_id_))) { + LOG_WARN("ctx_guard init fail", K(ret), K(ls_id_)); + } else if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id_, ctx_guard.get_ls_handle(), ObLSGetMod::DAS_MOD))) { + LOG_WARN("get ls failed", K(ret), K(ls_id_)); + } else if (OB_ISNULL(ls = ctx_guard.get_ls_handle().get_ls())) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("ls should not be null", K(ret), K(ls_id_)); + } else { + ctx.ls_ = ls; + ctx.timeout_ = DEFAULT_RETRY_TIMEOUT_US; + ObDMLBaseParam dml_param; + dml_param.snapshot_.init_none_read(); + dml_param.spec_seq_no_ = ObTxSEQ(1, 1); + if (OB_FAIL(ls->get_write_store_ctx(*tx_desc, + dml_param.snapshot_, + dml_param.write_flag_, + ctx_guard.get_store_ctx(), + dml_param.spec_seq_no_))) { + LOG_WARN("can not get write store ctx", K(ret), K(ls_id_), K(*tx_desc)); + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::switch_to_remote_write() +{ + int ret = OB_SUCCESS; + const uint64_t tenant_id = MTL_ID(); + share::ObLocationService *location_service = nullptr; + bool is_cache_hit = false; + if (OB_ISNULL(location_service = GCTX.location_service_)) { + ret = OB_ERR_SYS; + LOG_WARN("location service is null", K(ret), KP(location_service)); + } else if (OB_FAIL(location_service->get(tenant_id, + tablet_id_, + INT64_MAX/*expire_renew_time*/, + is_cache_hit, + leader_ls_id_))) { + LOG_WARN("fail to get log stream id", K(ret), K_(tablet_id)); + } else if (OB_FAIL(location_service->get_leader(GCONF.cluster_id, + tenant_id, + leader_ls_id_, + true, /*force_renew*/ + leader_addr_))) { + LOG_WARN("get leader failed", K(ret), K(leader_ls_id_)); + } else { + remote_write_ = true; + LOG_INFO("switch to remote write", K(ret), K_(tablet_id), K_(leader_ls_id), K_(leader_addr)); + } + return ret; +} + +int ObDDLIncRedoLogWriter::local_write_inc_start_log( + ObDDLIncStartLog &log, + ObTxDesc *tx_desc, + SCN &start_scn) +{ + int ret = OB_SUCCESS; + ObStoreCtxGuard ctx_guard; + ObLS *ls = nullptr; + ObTabletID lob_meta_tablet_id = log.get_log_basic().get_lob_meta_tablet_id(); + ObDDLIncStartClogCb *cb = nullptr; + ObPartTransCtx *trans_ctx = nullptr; + ObDDLIncLogHandle handle; + + ObDDLRedoLockGuard guard(tablet_id_.hash()); + if (OB_UNLIKELY(!log.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(log)); + } else if (OB_FAIL(get_write_store_ctx_guard(tx_desc, ctx_guard, ls))) { + LOG_WARN("fail to get_write_store_ctx_guard", K(ret), K(ls_id_)); + } else if (OB_ISNULL(ls) || !tablet_id_.is_valid()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KP(ls), K(tablet_id_)); + } else if (OB_FAIL(ls->sync_tablet_freeze_for_direct_load(tablet_id_, DEFAULT_RETRY_TIMEOUT_US))) { + LOG_WARN("sync tablet freeze failed", K(ret), K(tablet_id_)); + } else if (lob_meta_tablet_id.is_valid() && + OB_FAIL(ls->sync_tablet_freeze_for_direct_load(lob_meta_tablet_id, DEFAULT_RETRY_TIMEOUT_US))) { + LOG_WARN("sync tablet freeze failed", K(ret), K(lob_meta_tablet_id)); + } else if (OB_ISNULL(cb = OB_NEW(ObDDLIncStartClogCb, ObMemAttr(MTL_ID(), "DDL_IRLW")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory", K(ret)); + } else if (OB_FAIL(cb->init(log.get_log_basic()))) { + LOG_WARN("failed to init cb", K(ret)); + } else if (OB_ISNULL(trans_ctx = ctx_guard.get_store_ctx().mvcc_acc_ctx_.tx_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("trans_ctx should not be null", K(ret)); + } else if (OB_FAIL(trans_ctx->submit_direct_load_inc_start_log(log, cb, start_scn))) { + LOG_WARN("fail to submit ddl inc start log", K(ret), K(log)); + } else { + common::ObTimeGuard timeguard("write_inc_start_log wait", 5 * 1000 * 1000); // 5s + if (OB_SUCC(ret)) { + handle.cb_ = cb; + cb = nullptr; + if (OB_FAIL(handle.wait())) { + LOG_WARN("wait inc start log finish failed", K(ret), K(tablet_id_)); + } + } + } + if (OB_FAIL(ret)) { + if (nullptr != cb) { + ob_delete(cb); + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::local_write_inc_redo_log( + const ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + const int64_t task_id, + ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + ObDDLRedoLog log; + ObStoreCtxGuard ctx_guard; + ObLS *ls = nullptr; + ObTabletHandle tablet_handle; + ObTablet *tablet = nullptr; + ObDDLIncRedoClogCb *cb = nullptr; + ObDDLMacroBlockRedoInfo tmp_redo_info; + int64_t pos = 0; + int64_t buffer_size = 0; + + if (OB_UNLIKELY(!redo_info.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(redo_info)); + } else if (OB_FAIL(log.init(redo_info))) { + LOG_WARN("fail to init DDLRedoLog", K(ret), K(redo_info)); + } else if (OB_FAIL(get_write_store_ctx_guard(tx_desc, ctx_guard, ls))) { + LOG_WARN("fail to get_write_store_ctx_guard", K(ret), K(ls_id_)); + } else if (OB_FAIL(ls->get_tablet(redo_info.table_key_.tablet_id_, tablet_handle, ObTabletCommon::DEFAULT_GET_TABLET_NO_WAIT, ObMDSGetTabletMode::READ_ALL_COMMITED))) { + LOG_WARN("get tablet_handle failed", K(ret), K(redo_info)); + } else if (OB_ISNULL(tablet = tablet_handle.get_obj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tablet is null", K(ret), K(tablet_handle)); + } else { + ObDDLIncNeedStopWriteChecker checker(*tablet); + int tmp_ret = OB_SUCCESS; + int64_t real_sleep_us = 0; + buffer_size = log.get_serialize_size(); + if (OB_TMP_FAIL(ObDDLCtrlSpeedHandle::get_instance().limit_and_sleep(MTL_ID(), ls_id_, buffer_size, task_id, checker, real_sleep_us))) { + LOG_WARN("fail to limit and sleep", K(tmp_ret), K(MTL_ID()), K(task_id), K(ls_id_), K(buffer_size), K(real_sleep_us)); + } + } + + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(cb = OB_NEW(ObDDLIncRedoClogCb, ObMemAttr(MTL_ID(), "DDL_IRLW")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory", K(ret)); + } else if (FALSE_IT(buffer_size = redo_info.get_serialize_size())) { + } else if (OB_FAIL(redo_info.serialize(buffer_, buffer_size, pos))) { + LOG_WARN("fail to seriaize ddl redo log", K(ret)); + } else if (FALSE_IT(pos = 0)) { + } else if (OB_FAIL(tmp_redo_info.deserialize(buffer_, buffer_size, pos))) { + LOG_WARN("fail to deserialize ddl redo log", K(ret)); + } else if (OB_FAIL(cb->init(ls_id_, tmp_redo_info, macro_block_id, tablet_handle))) { + LOG_WARN("init ddl clog callback failed", K(ret)); + } else { + ObPartTransCtx *trans_ctx = nullptr; + ObRandom rand; + int64_t replay_hint = rand.get(); + SCN scn; + if (OB_ISNULL(trans_ctx = ctx_guard.get_store_ctx().mvcc_acc_ctx_.tx_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("trans_ctx should not be null", K(ret)); + } else if (OB_FAIL(trans_ctx->submit_direct_load_inc_redo_log(log, cb, replay_hint, scn))) { + LOG_WARN("fail to submit ddl inc redo log", K(ret), K(log)); + } else { + ddl_inc_log_handle_.cb_ = cb; + cb = nullptr; + ddl_inc_log_handle_.scn_ = scn; + } + } + if (OB_FAIL(ret)) { + if (nullptr != cb) { + ob_delete(cb); + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::local_write_inc_commit_log( + ObDDLIncCommitLog &log, + ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + ObStoreCtxGuard ctx_guard; + ObLS *ls = nullptr; + ObTabletID lob_meta_tablet_id = log.get_log_basic().get_lob_meta_tablet_id(); + ObDDLIncCommitClogCb *cb = nullptr; + ObPartTransCtx *trans_ctx = nullptr; + SCN base_scn = SCN::min_scn(); + SCN scn = SCN::min_scn(); + bool is_external_consistent = false; + ObDDLIncLogHandle handle; + + if (OB_UNLIKELY(!log.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(log)); + } else if (OB_FAIL(get_write_store_ctx_guard(tx_desc, ctx_guard, ls))) { + LOG_WARN("fail to get_write_store_ctx_guard", K(ret), K(ls_id_)); + } else if (OB_ISNULL(cb = OB_NEW(ObDDLIncCommitClogCb, ObMemAttr(MTL_ID(), "DDL_IRLW")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to alloc memory", K(ret)); + } else if (OB_FAIL(cb->init(ls_id_, log.get_log_basic()))) { + LOG_WARN("failed to init cb", K(ret)); + } else if (OB_FAIL(OB_TS_MGR.get_ts_sync(MTL_ID(), ObDDLIncLogHandle::DDL_INC_LOG_TIMEOUT, base_scn, is_external_consistent))) { + LOG_WARN("fail to get gts sync", K(ret), K(log)); + } else if (OB_ISNULL(trans_ctx = ctx_guard.get_store_ctx().mvcc_acc_ctx_.tx_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("trans_ctx should not be null", K(ret)); + } else if (OB_FAIL(trans_ctx->submit_direct_load_inc_commit_log(log, cb, scn))) { + LOG_WARN("fail to submit ddl inc commit log", K(ret), K(log)); + } else { + bool need_retry = true; + while (need_retry) { + if (OB_FAIL(OB_TS_MGR.wait_gts_elapse(MTL_ID(), scn))) { + if (OB_EAGAIN != ret) { + LOG_WARN("fail to wait gts elapse", K(ret), K(log)); + } else { + ob_usleep(1000); + } + } else { + need_retry = false; + } + } + { + common::ObTimeGuard timeguard("write_inc_commit_log wait", 5 * 1000 * 1000); // 5s + if (OB_SUCC(ret)) { + handle.cb_ = cb; + cb = nullptr; + if (OB_FAIL(handle.wait())) { + LOG_WARN("wait inc commit log finish failed", K(ret), K(tablet_id_)); + } + } + } + } + if (OB_FAIL(ret)) { + if (nullptr != cb) { + ob_delete(cb); + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::retry_remote_write_inc_commit_log( + const ObTabletID lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + int retry_cnt = 0; + const int64_t MAX_REMOTE_WRITE_RETRY_CNT = 800; + while (OB_SUCC(ret)) { + if (OB_FAIL(switch_to_remote_write())) { + LOG_WARN("flush ls leader location failed", K(ret)); + } else if (OB_FAIL(remote_write_inc_commit_log(lob_meta_tablet_id, tx_desc))) { + if (OB_NOT_MASTER == ret && retry_cnt++ < MAX_REMOTE_WRITE_RETRY_CNT) { + ob_usleep(10 * 1000); // 10 ms. + ret = OB_SUCCESS; + } else { + LOG_WARN("remote write ddl inc commit log failed", K(ret), K_(leader_ls_id), K_(leader_addr)); + } + } else { + break; + } + } + + return ret; +} + +int ObDDLIncRedoLogWriter::remote_write_inc_commit_log( + const ObTabletID lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc) +{ + int ret = OB_SUCCESS; + ObSrvRpcProxy *srv_rpc_proxy = GCTX.srv_rpc_proxy_; + + if (OB_ISNULL(srv_rpc_proxy)) { + ret = OB_ERR_SYS; + LOG_WARN("srv rpc proxy or location service is null", K(ret), KP(srv_rpc_proxy)); + } else { + obrpc::ObRpcRemoteWriteDDLIncCommitLogArg arg; + obrpc::ObRpcRemoteWriteDDLIncCommitLogRes res; + if (OB_FAIL(arg.init(MTL_ID(), leader_ls_id_, tablet_id_, lob_meta_tablet_id, tx_desc))) { + LOG_WARN("fail to init ObRpcRemoteWriteDDLIncCommitLogArg", K(ret)); + } else if (OB_FAIL(srv_rpc_proxy->to(leader_addr_).by(MTL_ID()).remote_write_ddl_inc_commit_log(arg, res))) { + LOG_WARN("remote write inc commit log failed", K(ret), K_(leader_ls_id), K_(leader_addr)); + } else if (OB_FAIL(MTL(ObTransService *)->add_tx_exec_result(*arg.tx_desc_, res.tx_result_))) { + LOG_WARN("fail to get_tx_exec_result", K(ret), K(*arg.tx_desc_)); + } + } + + return ret; +} + +ObDDLIncRedoLogWriterCallback::ObDDLIncRedoLogWriterCallback() + : is_inited_(false), + redo_info_(), + macro_block_id_(), + block_type_(ObDDLMacroBlockType::DDL_MB_INVALID_TYPE), + table_key_(), + task_id_(0), + data_format_version_(0), + tx_desc_(nullptr), + trans_id_() +{ +} + +ObDDLIncRedoLogWriterCallback::~ObDDLIncRedoLogWriterCallback() +{ + (void)wait(); +} + +int ObDDLIncRedoLogWriterCallback::init( + const share::ObLSID &ls_id, + const ObTabletID &tablet_id, + const ObDDLMacroBlockType block_type, + const ObITable::TableKey &table_key, + const int64_t task_id, + const share::SCN &start_scn, + const uint64_t data_format_version, + ObTxDesc *tx_desc, + const ObTransID &trans_id) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + LOG_WARN("inited twice", K(ret)); + } else if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid() || block_type == DDL_MB_INVALID_TYPE || + !table_key.is_valid() || task_id == 0 || data_format_version < 0 || OB_ISNULL(tx_desc) || !trans_id.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(ls_id), K(tablet_id), K(block_type), K(table_key), K(task_id), K(data_format_version), KP(tx_desc), K(trans_id)); + } else if (OB_FAIL(ddl_inc_writer_.init(ls_id, tablet_id))) { + LOG_WARN("fail to init ddl_inc_writer_", K(ret), K(ls_id), K(tablet_id)); + } else { + block_type_ = block_type; + table_key_ = table_key; + task_id_ = task_id; + start_scn_ = start_scn; + data_format_version_ = data_format_version; + tx_desc_ = tx_desc; + trans_id_ = trans_id; + is_inited_ = true; + } + + return ret; +} + +void ObDDLIncRedoLogWriterCallback::reset() +{ + is_inited_ = false; + redo_info_.reset(); + macro_block_id_.reset(); + ddl_inc_writer_.reset(); + block_type_ = ObDDLMacroBlockType::DDL_MB_INVALID_TYPE; + table_key_.reset(); + task_id_ = 0; + start_scn_.reset(); + data_format_version_ = 0; + tx_desc_ = nullptr; + trans_id_.reset(); +} + +int ObDDLIncRedoLogWriterCallback::write( + const ObMacroBlockHandle ¯o_handle, + const ObLogicMacroBlockId &logic_id, + char *buf, + const int64_t buf_len, + const int64_t row_count) +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDDLIncRedoLogWriterCallback is not inited", K(ret)); + } else if (OB_UNLIKELY(!macro_handle.is_valid() || !logic_id.is_valid() || nullptr == buf || row_count <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(macro_handle), K(logic_id), KP(buf), K(row_count)); + } else { + macro_block_id_ = macro_handle.get_macro_id(); + redo_info_.table_key_ = table_key_; + redo_info_.data_buffer_.assign(buf, buf_len); + redo_info_.block_type_ = block_type_; + redo_info_.logic_id_ = logic_id; + redo_info_.start_scn_ = start_scn_; + redo_info_.data_format_version_ = data_format_version_; + redo_info_.type_ = ObDirectLoadType::DIRECT_LOAD_INCREMENTAL; + redo_info_.trans_id_ = trans_id_; + if (OB_FAIL(ddl_inc_writer_.write_inc_redo_log_with_retry(redo_info_, macro_block_id_, task_id_, tx_desc_))) { + LOG_WARN("write ddl inc redo log fail", K(ret)); + } + } + return ret; +} + +int ObDDLIncRedoLogWriterCallback::wait() +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDDLIncRedoLogWriterCallback is not inited", K(ret)); + } else if (OB_FAIL(ddl_inc_writer_.wait_inc_redo_log_finish())) { + LOG_WARN("fail to wait inc redo log finish", K(ret), K(table_key_), K(macro_block_id_)); + } + return ret; +} diff --git a/src/storage/ddl/ob_ddl_inc_redo_log_writer.h b/src/storage/ddl/ob_ddl_inc_redo_log_writer.h new file mode 100644 index 000000000..058fecacd --- /dev/null +++ b/src/storage/ddl/ob_ddl_inc_redo_log_writer.h @@ -0,0 +1,152 @@ +/** + * 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. + */ + +#pragma once + +#include "storage/ddl/ob_ddl_redo_log_writer.h" +#include "storage/ddl/ob_ddl_inc_clog.h" +#include "storage/ddl/ob_ddl_inc_clog_callback.h" +#include "storage/tx_storage/ob_access_service.h" +#include "storage/tx/ob_trans_define_v4.h" + +namespace oceanbase +{ +namespace storage +{ + +class ObDDLIncLogHandle +{ +public: + static const int64_t DDL_INC_LOG_TIMEOUT = 60 * 1000 * 1000; // 1min + static const int64_t CHECK_DDL_INC_LOG_FINISH_INTERVAL = 1000; // 1ms + ObDDLIncLogHandle(); + ~ObDDLIncLogHandle(); + int wait(const int64_t timeout = DDL_INC_LOG_TIMEOUT); + void reset(); + bool is_valid() const { return nullptr != cb_ && scn_.is_valid_and_not_min(); } +public: + ObDDLIncClogCb *cb_; + share::SCN scn_; +}; + +class ObDDLIncRedoLogWriter final +{ +public: + static const int64_t DEFAULT_RETRY_TIMEOUT_US = 60L * 1000L * 1000L; // 1min + ObDDLIncRedoLogWriter(); + ~ObDDLIncRedoLogWriter(); + int init( + const share::ObLSID &ls_id, + const ObTabletID &tablet_id); + void reset(); + static bool need_retry(int ret_code, bool allow_remote_write); + int write_inc_start_log_with_retry( + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc, + share::SCN &start_scn); + int write_inc_redo_log_with_retry( + const storage::ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + const int64_t task_id, + transaction::ObTxDesc *tx_desc); + int wait_inc_redo_log_finish(); + int write_inc_commit_log_with_retry( + const bool allow_remote_write, + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc); +private: + int write_inc_start_log( + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc, + share::SCN &start_scn); + int write_inc_redo_log( + const storage::ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + const int64_t task_id, + transaction::ObTxDesc *tx_desc); + int write_inc_commit_log( + const bool allow_remote_write, + const ObTabletID &lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc); + int get_write_store_ctx_guard( + transaction::ObTxDesc *tx_desc, + ObStoreCtxGuard &ctx_guard, + storage::ObLS *&ls); + int switch_to_remote_write(); + int local_write_inc_start_log( + ObDDLIncStartLog &log, + transaction::ObTxDesc *tx_desc, + share::SCN &start_scn); + int local_write_inc_redo_log( + const storage::ObDDLMacroBlockRedoInfo &redo_info, + const blocksstable::MacroBlockId ¯o_block_id, + const int64_t task_id, + transaction::ObTxDesc *tx_desc); + int local_write_inc_commit_log( + ObDDLIncCommitLog &log, + transaction::ObTxDesc *tx_desc); + int retry_remote_write_inc_commit_log( + const common::ObTabletID lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc); + int remote_write_inc_commit_log( + const common::ObTabletID lob_meta_tablet_id, + transaction::ObTxDesc *tx_desc); +private: + bool is_inited_; + bool remote_write_; + share::ObLSID ls_id_; + ObTabletID tablet_id_; + ObDDLIncLogHandle ddl_inc_log_handle_; + ObAddr leader_addr_; + share::ObLSID leader_ls_id_; + char *buffer_; +}; + +class ObDDLIncRedoLogWriterCallback : public blocksstable::ObIMacroBlockFlushCallback +{ +public: + ObDDLIncRedoLogWriterCallback(); + virtual ~ObDDLIncRedoLogWriterCallback(); + int init( + const share::ObLSID &ls_id, + const ObTabletID &tablet_id, + const storage::ObDDLMacroBlockType block_type, + const ObITable::TableKey &table_key, + const int64_t task_id, + const share::SCN &start_scn, + const uint64_t data_format_version, + transaction::ObTxDesc *tx_desc, + const transaction::ObTransID &trans_id); + void reset(); + int write( + const blocksstable::ObMacroBlockHandle ¯o_handle, + const blocksstable::ObLogicMacroBlockId &logic_id, + char *buf, + const int64_t buf_len, + const int64_t row_count); + int wait(); +private: + bool is_inited_; + storage::ObDDLMacroBlockRedoInfo redo_info_; + blocksstable::MacroBlockId macro_block_id_; + ObDDLIncRedoLogWriter ddl_inc_writer_; + storage::ObDDLMacroBlockType block_type_; + ObITable::TableKey table_key_; + int64_t task_id_; + share::SCN start_scn_; + uint64_t data_format_version_; + transaction::ObTxDesc *tx_desc_; + transaction::ObTransID trans_id_; +}; + +} // end namespace storage +} // end namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_merge_task.cpp b/src/storage/ddl/ob_ddl_merge_task.cpp index ab41e5ca0..455ef5ac0 100644 --- a/src/storage/ddl/ob_ddl_merge_task.cpp +++ b/src/storage/ddl/ob_ddl_merge_task.cpp @@ -86,7 +86,6 @@ int ObDDLTableMergeDag::create_first_task() ObLSService *ls_service = MTL(ObLSService *); ObLSHandle ls_handle; ObTabletHandle tablet_handle; - ObDDLKvMgrHandle ddl_kv_mgr_handle; ObArray ddl_kvs_handle; ObDDLTableMergeTask *merge_task = nullptr; if (OB_FAIL(ls_service->get_ls(ddl_param_.ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { @@ -99,19 +98,8 @@ int ObDDLTableMergeDag::create_first_task() } else if (OB_UNLIKELY(!tablet_handle.is_valid())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected err", K(ret), K(ddl_param_)); - } else if (OB_FAIL(tablet_handle.get_obj()->get_ddl_kv_mgr(ddl_kv_mgr_handle))) { - if (OB_ENTRY_NOT_EXIST == ret) { - ret = OB_TASK_EXPIRED; - LOG_INFO("ddl kv mgr not exist", K(ret), K(ddl_param_)); - } else { - LOG_WARN("get ddl kv mgr failed", K(ret), K(ddl_param_)); - } - } else if (is_full_direct_load(ddl_param_.direct_load_type_) - && ddl_param_.start_scn_ < tablet_handle.get_obj()->get_tablet_meta().ddl_start_scn_) { - ret = OB_TASK_EXPIRED; - LOG_WARN("ddl task expired, skip it", K(ret), K(ddl_param_), "new_start_scn", tablet_handle.get_obj()->get_tablet_meta().ddl_start_scn_); - } else if (OB_FAIL(ddl_kv_mgr_handle.get_obj()->get_ddl_kvs(true/*frozen_only*/, ddl_kvs_handle))) { - LOG_WARN("get freezed ddl kv failed", K(ret), K(ddl_param_)); + } else if (OB_FAIL(prepare_ddl_kvs(*tablet_handle.get_obj(), ddl_kvs_handle))) { + LOG_WARN("fail to prepare load ddl kvs", K(ret)); } else if (OB_FAIL(alloc_task(merge_task))) { LOG_WARN("Fail to alloc task", K(ret), K(ddl_param_)); } else if (OB_FAIL(merge_task->init(ddl_param_, ddl_kvs_handle))) { @@ -122,6 +110,93 @@ int ObDDLTableMergeDag::create_first_task() return ret; } +int ObDDLTableMergeDag::prepare_ddl_kvs(ObTablet &tablet, ObIArray &ddl_kvs_handle) +{ + int ret = OB_SUCCESS; + if (is_full_direct_load(ddl_param_.direct_load_type_)) { // full direct load + if (OB_FAIL(prepare_full_direct_load_ddl_kvs(tablet, ddl_kvs_handle))) { + LOG_WARN("fail to prepare full direct load ddl kvs", K(ret)); + } + } else { // incremental direct load + if (OB_FAIL(prepare_incremental_direct_load_ddl_kvs(tablet, ddl_kvs_handle))) { + LOG_WARN("fail to prepare incremental direct load ddl kvs", K(ret)); + } + } + return ret; +} + +int ObDDLTableMergeDag::prepare_full_direct_load_ddl_kvs(ObTablet &tablet, ObIArray &ddl_kvs_handle) +{ + int ret = OB_SUCCESS; + ObDDLKvMgrHandle ddl_kv_mgr_handle; + ddl_kvs_handle.reset(); + if (OB_FAIL(tablet.get_ddl_kv_mgr(ddl_kv_mgr_handle))) { + if (OB_ENTRY_NOT_EXIST == ret) { + ret = OB_TASK_EXPIRED; + LOG_INFO("ddl kv mgr not exist", K(ret), K(ddl_param_)); + } else { + LOG_WARN("get ddl kv mgr failed", K(ret), K(ddl_param_)); + } + } else if (ddl_param_.start_scn_ < tablet.get_tablet_meta().ddl_start_scn_) { + ret = OB_TASK_EXPIRED; + LOG_WARN("ddl task expired, skip it", K(ret), K(ddl_param_), "new_start_scn", tablet.get_tablet_meta().ddl_start_scn_); + } else if (OB_FAIL(ddl_kv_mgr_handle.get_obj()->get_ddl_kvs(true/*frozen_only*/, ddl_kvs_handle))) { + LOG_WARN("get freezed ddl kv failed", K(ret), K(ddl_param_)); + } + return ret; +} + +int ObDDLTableMergeDag::prepare_incremental_direct_load_ddl_kvs(ObTablet &tablet, ObIArray &ddl_kvs_handle) +{ + int ret = OB_SUCCESS; + ObSEArray memtable_handles; + ObITable *table = nullptr; + ObDDLKV *ddl_kv = nullptr; + ObTableHandleV2 selected_ddl_kv_handle; + ddl_kvs_handle.reset(); + if (OB_FAIL(tablet.get_all_memtables(memtable_handles))) { + LOG_WARN("fail to get all memtable", K(ret), K(tablet)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < memtable_handles.count(); ++i) { + ObTableHandleV2 &table_handle = memtable_handles.at(i); + if (OB_ISNULL(table = table_handle.get_table())) { + ret = OB_ERR_SYS; + LOG_ERROR("table must not null", K(ret), K(table_handle)); + } else if (OB_UNLIKELY(!table->is_direct_load_memtable())) { + LOG_DEBUG("skip not direct load memtable", K(i), KPC(table), K(memtable_handles)); + break; + } else if (OB_ISNULL(ddl_kv = static_cast(table))) { + ret = OB_ERR_SYS; + LOG_ERROR("table not ddl kv", K(ret), KPC(table), K(memtable_handles)); + } else if (OB_UNLIKELY(ddl_kv->is_active_memtable())) { + LOG_DEBUG("skip active ddlkv", K(i), KPC(ddl_kv), K(memtable_handles)); + break; + } else if (!ddl_kv->can_be_minor_merged()) { + FLOG_INFO("ddlkv cannot mini merge now", K(i), KPC(ddl_kv), K(memtable_handles)); + break; + } else { + selected_ddl_kv_handle = table_handle; + if (ddl_kv->get_end_scn() > tablet.get_tablet_meta().clog_checkpoint_scn_) { + break; + } + } + } + if (OB_SUCC(ret)) { + if (!selected_ddl_kv_handle.is_valid()) { + ret = OB_NO_NEED_MERGE; + LOG_DEBUG("ddlkv no need merge", K(tablet), K(memtable_handles)); + } else { + ObDDLKVHandle ddl_kv_handle; + if (OB_FAIL(ddl_kv_handle.set_obj(selected_ddl_kv_handle))) { + LOG_WARN("fail to set obj", K(ret), K(selected_ddl_kv_handle)); + } else if (OB_FAIL(ddl_kvs_handle.push_back(ddl_kv_handle))) { + LOG_WARN("fail to push back", K(ret), K(ddl_kv_handle)); + } + } + } + return ret; +} + bool ObDDLTableMergeDag::operator == (const ObIDag &other) const { bool is_same = true; @@ -132,7 +207,8 @@ bool ObDDLTableMergeDag::operator == (const ObIDag &other) const const ObDDLTableMergeDag &other_dag = static_cast (other); // each tablet has max 1 dag in running, so that the compaction task is unique and no need to consider concurrency is_same = ddl_param_.tablet_id_ == other_dag.ddl_param_.tablet_id_ - && ddl_param_.ls_id_ == other_dag.ddl_param_.ls_id_; + && ddl_param_.ls_id_ == other_dag.ddl_param_.ls_id_ + && ddl_param_.direct_load_type_ == other_dag.ddl_param_.direct_load_type_; } return is_same; } @@ -238,6 +314,47 @@ int wait_lob_tablet_major_exist(ObLSHandle &ls_handle, ObTablet &tablet) } int ObDDLTableMergeTask::process() +{ + int ret = OB_SUCCESS; + LOG_INFO("ddl merge task start process", K(*this), "ddl_event_info", ObDDLEventInfo()); + ObLSService *ls_service = MTL(ObLSService *); + ObLSHandle ls_handle; + ObTabletHandle tablet_handle; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("not init", K(ret)); + } else if (OB_FAIL(ls_service->get_ls(merge_param_.ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { + LOG_WARN("get ls failed", K(ret), K(merge_param_)); + } else if (OB_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, + merge_param_.tablet_id_, + tablet_handle, + ObMDSGetTabletMode::READ_ALL_COMMITED))) { + LOG_WARN("get tablet failed", K(ret), K(merge_param_)); + } else if (OB_UNLIKELY(!tablet_handle.is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), K(merge_param_)); + } else if (OB_FAIL(merge_ddl_kvs(ls_handle, *tablet_handle.get_obj()))) { + LOG_WARN("fail to merge ddl kvs", K(ret)); + } + return ret; +} + +int ObDDLTableMergeTask::merge_ddl_kvs(ObLSHandle &ls_handle, ObTablet &tablet) +{ + int ret = OB_SUCCESS; + if (is_full_direct_load(merge_param_.direct_load_type_)) { + if (OB_FAIL(merge_full_direct_load_ddl_kvs(ls_handle, tablet))) { + LOG_WARN("fail to merge full direct load ddl kvs", K(ret)); + } + } else { // incremental direct load + if (OB_FAIL(merge_incremental_direct_load_ddl_kvs(ls_handle, tablet))) { + LOG_WARN("fail to merge incremental direct load ddl kvs", K(ret)); + } + } + return ret; +} + +int ObDDLTableMergeTask::merge_full_direct_load_ddl_kvs(ObLSHandle &ls_handle, ObTablet &tablet) { int ret = OB_SUCCESS; int64_t MAX_DDL_SSTABLE = ObTabletDDLKvMgr::MAX_DDL_KV_CNT_IN_STORAGE * 0.5; @@ -249,10 +366,7 @@ int ObDDLTableMergeTask::process() } LOG_INFO("set max ddl sstable in errsim mode", K(MAX_DDL_SSTABLE)); #endif - LOG_INFO("ddl merge task start process", K(*this), "ddl_event_info", ObDDLEventInfo()); - ObTabletHandle tablet_handle; ObDDLKvMgrHandle ddl_kv_mgr_handle; - ObLSHandle ls_handle; ObTableStoreIterator ddl_table_iter; ObTabletMemberWrapper table_store_wrapper; const uint64_t tenant_id = MTL_ID(); @@ -264,27 +378,17 @@ int ObDDLTableMergeTask::process() ObTenantDirectLoadMgr *tenant_direct_load_mgr = MTL(ObTenantDirectLoadMgr *); ObTabletDirectLoadMgrHandle tablet_mgr_hdl; ObTabletFullDirectLoadMgr *tablet_direct_load_mgr = nullptr; - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - LOG_WARN("not init", K(ret)); - } else if (OB_ISNULL(tenant_direct_load_mgr)) { + if (OB_ISNULL(tenant_direct_load_mgr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected err", K(ret), K(MTL_ID())); - } else if (OB_FAIL(MTL(ObLSService *)->get_ls(merge_param_.ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { - LOG_WARN("failed to get log stream", K(ret), K(merge_param_)); - } else if (OB_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, - merge_param_.tablet_id_, - tablet_handle, - ObMDSGetTabletMode::READ_ALL_COMMITED))) { - LOG_WARN("failed to get tablet", K(ret), K(merge_param_)); - } else if (OB_FAIL(tablet_handle.get_obj()->get_ddl_kv_mgr(ddl_kv_mgr_handle))) { + } else if (OB_FAIL(tablet.get_ddl_kv_mgr(ddl_kv_mgr_handle))) { if (OB_ENTRY_NOT_EXIST == ret) { ret = OB_TASK_EXPIRED; LOG_INFO("ddl kv mgr not exist", K(ret), K(merge_param_)); } else { LOG_WARN("get ddl kv mgr failed", K(ret), K(merge_param_)); } - } else if (OB_FAIL(tablet_handle.get_obj()->get_ddl_sstables(ddl_table_iter))) { + } else if (OB_FAIL(tablet.get_ddl_sstables(ddl_table_iter))) { LOG_WARN("get ddl sstable handles failed", K(ret)); } else { DEBUG_SYNC(BEFORE_DDL_TABLE_MERGE_TASK); @@ -312,7 +416,7 @@ int ObDDLTableMergeTask::process() } else if (nullptr != first_major_sstable) { is_major_exist = true; LOG_INFO("major sstable has been created before", K(merge_param_)); - } else if (tablet_handle.get_obj()->get_tablet_meta().table_store_flag_.with_major_sstable()) { + } else if (tablet.get_tablet_meta().table_store_flag_.with_major_sstable()) { ret = OB_TASK_EXPIRED; LOG_INFO("tablet me says with major but no major, meaning its a migrated deleted tablet, skip"); } else if (OB_FAIL(tenant_direct_load_mgr->get_tablet_mgr(merge_param_.tablet_id_, @@ -321,7 +425,7 @@ int ObDDLTableMergeTask::process() LOG_WARN("get tablet direct load mgr failed", K(ret), K(merge_param_)); } else if (OB_FAIL(tablet_mgr_hdl.get_full_obj()->prepare_major_merge_param(ddl_param))) { LOG_WARN("preare full direct load sstable param failed", K(ret)); - } else if (merge_param_.is_commit_ && OB_FAIL(wait_lob_tablet_major_exist(ls_handle, *tablet_handle.get_obj()))) { + } else if (merge_param_.is_commit_ && OB_FAIL(wait_lob_tablet_major_exist(ls_handle, tablet))) { if (OB_EAGAIN != ret) { LOG_WARN("wait lob tablet major sstable exist faild", K(ret), K(merge_param_)); } else { @@ -352,7 +456,7 @@ int ObDDLTableMergeTask::process() // use the final table key of major, do nothing } if (OB_FAIL(ObTabletDDLUtil::compact_ddl_kv(*ls_handle.get_ls(), - *tablet_handle.get_obj(), + tablet, ddl_table_iter, frozen_ddl_kvs_, ddl_param, @@ -384,6 +488,60 @@ int ObDDLTableMergeTask::process() return ret; } +int ObDDLTableMergeTask::merge_incremental_direct_load_ddl_kvs(ObLSHandle &ls_handle, ObTablet &tablet) +{ + int ret = OB_SUCCESS; + common::ObArenaAllocator allocator("DDLMergeTask", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); + ObDDLKV *ddl_kv = nullptr; + ObTableStoreIterator ddl_table_iter; + ObTabletDDLParam ddl_param; + ObTableHandleV2 compacted_sstable_handle; + if (OB_UNLIKELY(frozen_ddl_kvs_.count() != 1)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected frozen ddl kvs", K(ret), K(merge_param_), K(frozen_ddl_kvs_)); + } else if (OB_ISNULL(ddl_kv = frozen_ddl_kvs_.at(0).get_obj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected invalid ddlkv handle", K(ret), K(merge_param_), K(frozen_ddl_kvs_)); + } else if (ddl_kv->get_end_scn() <= tablet.get_tablet_meta().clog_checkpoint_scn_) { + // do nothing + } else { + ddl_param.direct_load_type_ = merge_param_.direct_load_type_; + ddl_param.ls_id_ = merge_param_.ls_id_; + ddl_param.start_scn_ = ddl_kv->get_ddl_start_scn(); + ddl_param.commit_scn_ = ddl_kv->get_ddl_start_scn(); + ddl_param.data_format_version_ = ddl_kv->get_data_format_version(); + ddl_param.table_key_.tablet_id_ = merge_param_.tablet_id_; + ddl_param.table_key_.scn_range_.start_scn_ = ddl_kv->get_start_scn(); + ddl_param.table_key_.scn_range_.end_scn_ = ddl_kv->get_end_scn(); + ddl_param.table_key_.table_type_ = ObITable::MINI_SSTABLE; + ddl_param.snapshot_version_ = ddl_kv->get_snapshot_version(); + ddl_param.trans_id_ = ddl_kv->get_trans_id(); + if (OB_FAIL(ObTabletDDLUtil::compact_ddl_kv(*ls_handle.get_ls(), + tablet, + ddl_table_iter, + frozen_ddl_kvs_, + ddl_param, + allocator, + compacted_sstable_handle))) { + LOG_WARN("compact sstables failed", K(ret), K(ddl_param), K(frozen_ddl_kvs_)); + } + } + if (OB_SUCC(ret)) { + int tmp_ret = OB_SUCCESS; + ObTabletHandle new_tablet_handle; + if (OB_TMP_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, + merge_param_.tablet_id_, + new_tablet_handle, + ObMDSGetTabletMode::READ_ALL_COMMITED))) { + LOG_WARN("failed to get tablet", K(tmp_ret), K(merge_param_)); + } else if (OB_TMP_FAIL(new_tablet_handle.get_obj()->release_memtables(new_tablet_handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_))) { + LOG_WARN("failed to release memtable", K(tmp_ret), + "clog_checkpoint_scn", new_tablet_handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_); + } + } + return ret; +} + // the input ddl sstable is sorted with start_scn int ObTabletDDLUtil::check_data_continue( ObTableStoreIterator &ddl_sstable_iter, @@ -488,11 +646,10 @@ int ObTabletDDLUtil::check_data_continue( } int ObTabletDDLUtil::prepare_index_data_desc(ObTablet &tablet, - const int64_t cg_idx, + const ObITable::TableKey &table_key, const int64_t snapshot_version, const uint64_t data_format_version, const ObSSTable *first_ddl_sstable, - const SCN &end_scn, const ObStorageSchema *storage_schema, ObWholeDataStoreDesc &data_desc) { @@ -501,6 +658,8 @@ int ObTabletDDLUtil::prepare_index_data_desc(ObTablet &tablet, ObLSService *ls_service = MTL(ObLSService *); const ObTabletID &tablet_id = tablet.get_tablet_meta().tablet_id_; const ObLSID &ls_id = tablet.get_tablet_meta().ls_id_; + const int64_t cg_idx = table_key.is_column_store_sstable() ? table_key.get_column_group_id() : -1/*negative value means row store*/; + const SCN end_scn = table_key.get_end_scn(); if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid() || snapshot_version <= 0 || data_format_version <= 0 || OB_ISNULL(storage_schema))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(ls_id), K(tablet_id), K(snapshot_version), K(data_format_version), KP(storage_schema)); @@ -509,6 +668,9 @@ int ObTabletDDLUtil::prepare_index_data_desc(ObTablet &tablet, if (cg_idx >= cg_schemas.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid cg idx", K(ret), K(cg_idx), K(cg_schemas.count())); + } else if (OB_UNLIKELY(table_key.is_minor_sstable())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected table key is minor sstable", K(ret), K(table_key)); } else { const ObStorageColumnGroupSchema &cur_cg_schema = cg_schemas.at(cg_idx); if (OB_FAIL(data_desc.init(*storage_schema, ls_id, tablet_id, @@ -521,9 +683,10 @@ int ObTabletDDLUtil::prepare_index_data_desc(ObTablet &tablet, } else if (OB_FAIL(data_desc.init(*storage_schema, ls_id, tablet_id, - compaction::MAJOR_MERGE, + table_key.is_minor_sstable() ? compaction::MINOR_MERGE : compaction::MAJOR_MERGE, snapshot_version, - data_format_version))) { + data_format_version, + end_scn))) { // use storage schema to init ObDataStoreDesc // all cols' default checksum will assigned to 0 // means all macro should contain all columns in schema @@ -563,11 +726,10 @@ int ObTabletDDLUtil::create_ddl_sstable(ObTablet &tablet, LOG_WARN("invalid argument", K(ret), K(ddl_param), KP(storage_schema)); } else if (OB_FAIL(ObTabletDDLUtil::prepare_index_data_desc( tablet, - ddl_param.table_key_.is_column_store_sstable() ? ddl_param.table_key_.get_column_group_id() : -1/*negative value means row store*/, + ddl_param.table_key_, ddl_param.snapshot_version_, ddl_param.data_format_version_, first_ddl_sstable, - ddl_param.table_key_.get_end_scn(), storage_schema, data_desc))) { LOG_WARN("prepare data store desc failed", K(ret), K(ddl_param)); @@ -633,6 +795,7 @@ int ObTabletDDLUtil::create_ddl_sstable( LOG_WARN("create sstable failed", K(ret), K(param)); } } else { + param.uncommitted_tx_id_ = ddl_param.trans_id_.get_id(); if (OB_FAIL(ObTabletCreateDeleteHelper::create_sstable(param, allocator, sstable_handle))) { LOG_WARN("create sstable failed", K(ret), K(param)); } @@ -673,13 +836,19 @@ int ObTabletDDLUtil::update_ddl_table_store( is_major_sstable, // update_with_major_flag /*DDL does not have verification between replicas, So using medium merge to force verification between replicas*/ - compaction::MEDIUM_MERGE, + is_full_direct_load(ddl_param.direct_load_type_) ? compaction::MEDIUM_MERGE : compaction::MINOR_MERGE, is_major_sstable// need report checksum ); - table_store_param.ddl_info_.keep_old_ddl_sstable_ = !is_major_sstable; - table_store_param.ddl_info_.data_format_version_ = ddl_param.data_format_version_; - table_store_param.ddl_info_.ddl_commit_scn_ = ddl_param.commit_scn_; - table_store_param.ddl_info_.ddl_checkpoint_scn_ = sstable->is_ddl_dump_sstable() ? sstable->get_end_scn() : ddl_param.commit_scn_; + if (is_full_direct_load(ddl_param.direct_load_type_)) { // full direct load + table_store_param.ddl_info_.keep_old_ddl_sstable_ = !is_major_sstable; + table_store_param.ddl_info_.data_format_version_ = ddl_param.data_format_version_; + table_store_param.ddl_info_.ddl_commit_scn_ = ddl_param.commit_scn_; + table_store_param.ddl_info_.ddl_checkpoint_scn_ = sstable->is_ddl_dump_sstable() ? sstable->get_end_scn() : ddl_param.commit_scn_; + } else { // incremental direct load + table_store_param.clog_checkpoint_scn_ = sstable->get_end_scn(); + table_store_param.need_check_transfer_seq_ = true; + table_store_param.transfer_seq_ = tablet.get_tablet_meta().transfer_info_.transfer_seq_; + } if (OB_FAIL(ls.update_tablet_table_store(ddl_param.table_key_.get_tablet_id(), table_store_param, new_tablet_handle))) { LOG_WARN("failed to update tablet table store", K(ret), K(ddl_param.table_key_), K(table_store_param)); } else { @@ -988,7 +1157,7 @@ int compact_sstables( tablet, ddl_param, sorted_metas, - sstables.empty() ? nullptr : sstables.at(0)/*first ddl sstable*/, + (sstables.empty() || is_incremental_direct_load(ddl_param.direct_load_type_)) ? nullptr : sstables.at(0)/*first ddl sstable*/, storage_schema, allocator, sstable_handle))) { diff --git a/src/storage/ddl/ob_ddl_merge_task.h b/src/storage/ddl/ob_ddl_merge_task.h index 313c5a434..2e80b6e83 100644 --- a/src/storage/ddl/ob_ddl_merge_task.h +++ b/src/storage/ddl/ob_ddl_merge_task.h @@ -59,6 +59,10 @@ public: virtual uint64_t get_consumer_group_id() const override { return consumer_group_id_; } virtual bool is_ha_dag() const override { return false; } +private: + int prepare_ddl_kvs(ObTablet &tablet, ObIArray &ddl_kvs_handle); + int prepare_full_direct_load_ddl_kvs(ObTablet &tablet, ObIArray &ddl_kvs_handle); + int prepare_incremental_direct_load_ddl_kvs(ObTablet &tablet, ObIArray &ddl_kvs_handle); private: bool is_inited_; ObDDLTableMergeDagParam ddl_param_; @@ -77,6 +81,10 @@ public: int init(const ObDDLTableMergeDagParam &ddl_dag_param, const ObIArray &frozen_ddl_kvs); virtual int process() override; TO_STRING_KV(K_(is_inited), K_(merge_param)); +private: + int merge_ddl_kvs(ObLSHandle &ls_handle, ObTablet &tablet); + int merge_full_direct_load_ddl_kvs(ObLSHandle &ls_handle, ObTablet &tablet); + int merge_incremental_direct_load_ddl_kvs(ObLSHandle &ls_handle, ObTablet &tablet); private: bool is_inited_; ObDDLTableMergeDagParam merge_param_; @@ -106,11 +114,10 @@ class ObTabletDDLUtil public: static int prepare_index_data_desc( ObTablet &tablet, - const int64_t cg_idx, // negative means row store + const ObITable::TableKey &table_key, const int64_t snapshot_version, const uint64_t data_format_version, const blocksstable::ObSSTable *first_ddl_sstable, - const share::SCN &end_scn, const ObStorageSchema *storage_schema, blocksstable::ObWholeDataStoreDesc &data_desc); diff --git a/src/storage/ddl/ob_ddl_redo_log_replayer.cpp b/src/storage/ddl/ob_ddl_redo_log_replayer.cpp index 30da1b2f4..4b3cb4a77 100644 --- a/src/storage/ddl/ob_ddl_redo_log_replayer.cpp +++ b/src/storage/ddl/ob_ddl_redo_log_replayer.cpp @@ -115,6 +115,41 @@ int ObDDLRedoLogReplayer::replay_commit(const ObDDLCommitLog &log, const SCN &sc return ret; } +int ObDDLRedoLogReplayer::replay_inc_start(const ObDDLIncStartLog &log, const share::SCN &scn) +{ + int ret = OB_SUCCESS; + ObDDLIncStartReplayExecutor replay_executor; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("ObDDLRedoLogReplayer has not been inited", K(ret)); + } else if (OB_FAIL(replay_executor.init(ls_, log, scn))) { + LOG_WARN("failed to init ddl inc start log replay executor", K(ret)); + } else if (OB_FAIL(replay_executor.execute(scn, ls_->get_ls_id(), log.get_log_basic().get_tablet_id()))) { + if (OB_NO_NEED_UPDATE == ret) { + ret = OB_SUCCESS; + } else if (OB_EAGAIN != ret) { + LOG_WARN("failed to replay", K(ret), K(log), K(scn)); + } + } + + return ret; +} + +int ObDDLRedoLogReplayer::replay_inc_commit(const ObDDLIncCommitLog &log, const SCN &scn) +{ + int ret = OB_SUCCESS; + ObDDLIncCommitReplayExecutor replay_executor; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("ObDDLRedoLogReplayer has not been inited", K(ret)); + } else if (OB_FAIL(replay_executor.init(ls_, log, scn))) { + LOG_WARN("failed to init ddl inc commit log replay executor", K(ret)); + } else if (OB_FAIL(replay_executor.execute(scn, ls_->get_ls_id(), log.get_log_basic().get_tablet_id()))) { + LOG_WARN("execute replay execute failed", K(ret)); + } + + return ret; +} void ObDDLRedoLogReplayer::destroy() { diff --git a/src/storage/ddl/ob_ddl_redo_log_replayer.h b/src/storage/ddl/ob_ddl_redo_log_replayer.h index c298bbf2e..f99de132d 100644 --- a/src/storage/ddl/ob_ddl_redo_log_replayer.h +++ b/src/storage/ddl/ob_ddl_redo_log_replayer.h @@ -14,6 +14,7 @@ #define OCEANBASE_STORAGE_OB_DDL_REDO_LOG_REPLAYER_H #include "storage/ddl/ob_ddl_clog.h" +#include "storage/ddl/ob_ddl_inc_clog.h" #include "storage/ddl/ob_ddl_struct.h" #include "storage/blocksstable/ob_block_sstable_struct.h" @@ -34,6 +35,8 @@ public: int replay_start(const ObDDLStartLog &log, const share::SCN &scn); int replay_redo(const ObDDLRedoLog &log, const share::SCN &scn); int replay_commit(const ObDDLCommitLog &log, const share::SCN &scn); + int replay_inc_start(const ObDDLIncStartLog &log, const share::SCN &scn); + int replay_inc_commit(const ObDDLIncCommitLog &log, const share::SCN &scn); private: void destroy(); diff --git a/src/storage/ddl/ob_ddl_redo_log_row_iterator.cpp b/src/storage/ddl/ob_ddl_redo_log_row_iterator.cpp new file mode 100644 index 000000000..02e527158 --- /dev/null +++ b/src/storage/ddl/ob_ddl_redo_log_row_iterator.cpp @@ -0,0 +1,119 @@ +/** + * 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. + */ + +#define USING_LOG_PREFIX STORAGE + +#include "storage/ddl/ob_ddl_redo_log_row_iterator.h" + +namespace oceanbase +{ +namespace storage +{ +using namespace common; +using namespace blocksstable; +using namespace transaction; +using namespace share::schema; + +ObDDLRedoLogRowIterator::ObDDLRedoLogRowIterator(ObIAllocator &allocator, const uint64_t tenant_id) + : allocator_(allocator), + iter_(allocator, tenant_id), + rowkey_obobj_(nullptr), + schema_rowkey_column_count_(0), + is_inited_(false) +{ +} + +ObDDLRedoLogRowIterator::~ObDDLRedoLogRowIterator() +{ + reset(); +} + +int ObDDLRedoLogRowIterator::init(const ObString &data_buffer) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(iter_.open(data_buffer.ptr(), data_buffer.length()))) { + LOG_WARN("fail to open iter_", KR(ret), K(data_buffer)); + } else if (FALSE_IT(schema_rowkey_column_count_ = iter_.get_rowkey_column_descs().count() - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt())) { + } else if (OB_UNLIKELY(schema_rowkey_column_count_ <= 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("schema_rowkey_column_count_ invalid", KR(ret), K(schema_rowkey_column_count_)); + } else if (OB_ISNULL(rowkey_obobj_ = static_cast(allocator_.alloc(sizeof(ObObj) * schema_rowkey_column_count_)))) { + LOG_WARN("fail to alloc memory", KR(ret)); + } else { + is_inited_ = true; + } + + return ret; +} + +void ObDDLRedoLogRowIterator::reset() +{ + iter_.reset(); + rowkey_.reset(); + if (rowkey_obobj_ != nullptr) { + allocator_.free(rowkey_obobj_); + rowkey_obobj_ = nullptr; + } + schema_rowkey_column_count_ = 0; + is_inited_ = false; +} + +int ObDDLRedoLogRowIterator::get_next_row(const ObDatumRow *&row, + const ObStoreRowkey *&rowkey, + ObTxSEQ &seq_no, + blocksstable::ObDmlRowFlag &row_flag) +{ + int ret = OB_SUCCESS; + row = nullptr; + rowkey = nullptr; + seq_no.reset(); + row_flag.reset(); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("not inited", KR(ret)); + } else if (OB_FAIL(iter_.get_next_row(row))) { + if (ret != OB_ITER_END) { + LOG_WARN("fail to get next row", KR(ret)); + } + } else { + const ObStorageDatum *datums = row->storage_datums_; + const ObIArray &col_desc = iter_.get_rowkey_column_descs(); + for (int64_t i = 0; OB_SUCC(ret) && i < schema_rowkey_column_count_; i++) { + if (OB_FAIL(datums[i].to_obj_enhance(rowkey_obobj_[i], col_desc.at(i).col_type_))) { + LOG_WARN("fail to get obobj", KR(ret), K(i)); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(rowkey_.assign(rowkey_obobj_, schema_rowkey_column_count_))) { + LOG_WARN("fail to assign rowkey", KR(ret)); + } else { + rowkey = &rowkey_; + seq_no = ObTxSEQ::cast_from_int(datums[schema_rowkey_column_count_ + 1].get_int()); + row_flag = row->row_flag_; + } + } + } + + return ret; +} + +int ObDDLRedoLogRowIterator::get_next_lob_meta_row(const ObLobMetaInfo *&row, + const ObStoreRowkey *&rowkey, + ObTxSEQ &seq_no, + blocksstable::ObDmlRowFlag &row_flag) +{ + // 一期暂不支持 + return OB_NOT_SUPPORTED; +} + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_redo_log_row_iterator.h b/src/storage/ddl/ob_ddl_redo_log_row_iterator.h new file mode 100644 index 000000000..a3d57d1da --- /dev/null +++ b/src/storage/ddl/ob_ddl_redo_log_row_iterator.h @@ -0,0 +1,49 @@ +/** + * 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. + */ +#pragma once + +#include "share/ob_errno.h" +#include "lib/oblog/ob_log_module.h" +#include "storage/lob/ob_lob_util.h" +#include "storage/blocksstable/ob_datum_row.h" +#include "storage/blocksstable/ob_macro_block_bare_iterator.h" + +namespace oceanbase +{ +namespace storage +{ +class ObDDLRedoLogRowIterator +{ +public: + ObDDLRedoLogRowIterator(common::ObIAllocator &allocator, const uint64_t tenant_id); + ~ObDDLRedoLogRowIterator(); + int init(const ObString &data_buffer); + void reset(); + int get_next_row(const blocksstable::ObDatumRow *&row, + const ObStoreRowkey *&rowkey, + transaction::ObTxSEQ &seq_no, + blocksstable::ObDmlRowFlag &row_flag); + int get_next_lob_meta_row(const ObLobMetaInfo *&row, + const ObStoreRowkey *&rowkey, + transaction::ObTxSEQ &seq_no, + blocksstable::ObDmlRowFlag &row_flag); +private: + common::ObIAllocator &allocator_; + blocksstable::ObMacroBlockRowBareIterator iter_; + common::ObStoreRowkey rowkey_; + common::ObObj *rowkey_obobj_; + int64_t schema_rowkey_column_count_; + bool is_inited_; +}; + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ddl/ob_ddl_redo_log_writer.cpp b/src/storage/ddl/ob_ddl_redo_log_writer.cpp index 12b110a0f..92d29490a 100644 --- a/src/storage/ddl/ob_ddl_redo_log_writer.cpp +++ b/src/storage/ddl/ob_ddl_redo_log_writer.cpp @@ -39,6 +39,17 @@ using namespace oceanbase::blocksstable; using namespace oceanbase::logservice; using namespace oceanbase::share; using namespace oceanbase::blocksstable; +using namespace oceanbase::transaction; + +bool ObDDLFullNeedStopWriteChecker::check_need_stop_write() +{ + return ddl_kv_mgr_handle_.get_obj()->get_count() >= ObTabletDDLKvMgr::MAX_DDL_KV_CNT_IN_STORAGE - 1; +} + +bool ObDDLIncNeedStopWriteChecker::check_need_stop_write() +{ + return tablet_.get_memtable_count() >= common::MAX_MEMSTORE_CNT - 1; +} int ObDDLCtrlSpeedItem::init(const share::ObLSID &ls_id) { @@ -174,7 +185,7 @@ int ObDDLCtrlSpeedItem::do_sleep( const int64_t next_available_ts, const uint64_t tenant_id, const int64_t task_id, - ObDDLKvMgrHandle &ddl_kv_mgr_handle, + ObDDLNeedStopWriteChecker &checker, int64_t &real_sleep_us) { int ret = OB_SUCCESS; @@ -191,8 +202,8 @@ int ObDDLCtrlSpeedItem::do_sleep( LOG_WARN("invalid argument.", K(ret), K(next_available_ts), K(tenant_id), K(task_id)); } else if (OB_FAIL(DDL_SIM(MTL_ID(), task_id, DDL_REDO_WRITER_SPEED_CONTROL_FAILED))) { LOG_WARN("ddl sim failure", K(ret), K(MTL_ID()), K(task_id)); - } else if (OB_TMP_FAIL(check_need_stop_write(ddl_kv_mgr_handle, is_need_stop_write))) { - LOG_WARN("fail to check need stop write", K(tmp_ret), K(ddl_kv_mgr_handle)); + } else if (OB_TMP_FAIL(check_need_stop_write(checker, is_need_stop_write))) { + LOG_WARN("fail to check need stop write", K(tmp_ret)); } if (OB_FAIL(ret)) { } else if (is_need_stop_write) /*clog disk used exceeds threshold*/ { @@ -218,8 +229,8 @@ int ObDDLCtrlSpeedItem::do_sleep( K(write_speed_), K(need_stop_write_), K(ref_cnt_), K(disk_used_stop_write_threshold_)); } - if (OB_TMP_FAIL(check_need_stop_write(ddl_kv_mgr_handle, is_need_stop_write))) { - LOG_WARN("fail to check need stop write", K(tmp_ret), K(ddl_kv_mgr_handle)); + if (OB_TMP_FAIL(check_need_stop_write(checker, is_need_stop_write))) { + LOG_WARN("fail to check need stop write", K(tmp_ret)); } loop_cnt++; } @@ -231,7 +242,7 @@ int ObDDLCtrlSpeedItem::do_sleep( return ret; } -int ObDDLCtrlSpeedItem::check_need_stop_write(ObDDLKvMgrHandle &ddl_kv_mgr_handle, +int ObDDLCtrlSpeedItem::check_need_stop_write(ObDDLNeedStopWriteChecker &checker, bool &is_need_stop_write) { int ret = OB_SUCCESS; @@ -245,9 +256,7 @@ int ObDDLCtrlSpeedItem::check_need_stop_write(ObDDLKvMgrHandle &ddl_kv_mgr_handl LOG_WARN("check cur node is leader failed", K(ret)); } else { if (is_leader) { - int64_t ddl_kv_count = ddl_kv_mgr_handle.get_obj()->get_count(); - is_need_stop_write = (ddl_kv_count >= ObTabletDDLKvMgr::MAX_DDL_KV_CNT_IN_STORAGE - 1); - is_need_stop_write = (is_need_stop_write || need_stop_write_); + is_need_stop_write = (checker.check_need_stop_write() || need_stop_write_); } else { is_need_stop_write = false; } @@ -261,7 +270,7 @@ int ObDDLCtrlSpeedItem::limit_and_sleep( const int64_t bytes, const uint64_t tenant_id, const int64_t task_id, - ObDDLKvMgrHandle &ddl_kv_mgr_handle, + ObDDLNeedStopWriteChecker &checker, int64_t &real_sleep_us) { int ret = OB_SUCCESS; @@ -285,7 +294,7 @@ int ObDDLCtrlSpeedItem::limit_and_sleep( INT64_MAX, &transmit_sleep_us))) { LOG_WARN("fail to limit out and sleep", K(ret), K(bytes), K(transmit_sleep_us)); - } else if (OB_FAIL(do_sleep(next_available_ts, tenant_id, task_id, ddl_kv_mgr_handle, real_sleep_us))) { + } else if (OB_FAIL(do_sleep(next_available_ts, tenant_id, task_id, checker, real_sleep_us))) { LOG_WARN("fail to sleep", K(ret), K(next_available_ts), K(real_sleep_us)); } else {/* do nothing. */} return ret; @@ -379,7 +388,7 @@ int ObDDLCtrlSpeedHandle::limit_and_sleep(const uint64_t tenant_id, const share::ObLSID &ls_id, const int64_t bytes, const int64_t task_id, - ObDDLKvMgrHandle &ddl_kv_mgr_handle, + ObDDLNeedStopWriteChecker &checker, int64_t &real_sleep_us) { int ret = OB_SUCCESS; @@ -410,7 +419,7 @@ int ObDDLCtrlSpeedHandle::limit_and_sleep(const uint64_t tenant_id, } else if (OB_FAIL(speed_handle_item->limit_and_sleep(bytes, tenant_id, task_id, - ddl_kv_mgr_handle, + checker, real_sleep_us))) { LOG_WARN("fail to limit and sleep", K(ret), K(bytes), K(task_id), K(real_sleep_us)); } @@ -720,8 +729,11 @@ int ObDDLRedoLogWriter::local_write_ddl_macro_redo( LOG_WARN("get tablet handle failed", K(ret), K(ls_id), K(log.get_redo_info())); } else if (OB_FAIL(tablet_handle.get_obj()->get_ddl_kv_mgr(ddl_kv_mgr_handle))) { LOG_WARN("create ddl kv mgr failed", K(ret)); - } else if (OB_TMP_FAIL(ObDDLCtrlSpeedHandle::get_instance().limit_and_sleep(tenant_id, ls_id, buffer_size, task_id, ddl_kv_mgr_handle, real_sleep_us))) { - LOG_WARN("fail to limit and sleep", K(tmp_ret), K(tenant_id), K(task_id), K(ls_id), K(buffer_size), K(real_sleep_us)); + } else { + ObDDLFullNeedStopWriteChecker checker(ddl_kv_mgr_handle); + if (OB_TMP_FAIL(ObDDLCtrlSpeedHandle::get_instance().limit_and_sleep(tenant_id, ls_id, buffer_size, task_id, checker, real_sleep_us))) { + LOG_WARN("fail to limit and sleep", K(tmp_ret), K(tenant_id), K(task_id), K(ls_id), K(buffer_size), K(real_sleep_us)); + } } if (OB_FAIL(ret)) { } else if (OB_ISNULL(cb = op_alloc(ObDDLMacroBlockClogCb))) { @@ -1401,7 +1413,7 @@ int ObDDLRedoLogWriter::switch_to_remote_write() int ObDDLRedoLogWriter::retry_remote_write_macro_redo( const int64_t task_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info) + const storage::ObDDLMacroBlockRedoInfo &redo_info) { int ret = OB_SUCCESS; int retry_cnt = 0; @@ -1488,8 +1500,7 @@ ObDDLRedoLogWriter::~ObDDLRedoLogWriter() ObDDLRedoLogWriterCallback::ObDDLRedoLogWriterCallback() : is_inited_(false), redo_info_(), block_type_(ObDDLMacroBlockType::DDL_MB_INVALID_TYPE), - table_key_(), macro_block_id_(), ddl_writer_(nullptr), task_id_(0), - data_format_version_(0), row_id_offset_(-1) + table_key_(), macro_block_id_(), task_id_(0), data_format_version_(0), row_id_offset_(-1) { } @@ -1498,12 +1509,13 @@ ObDDLRedoLogWriterCallback::~ObDDLRedoLogWriterCallback() (void)wait(); } -int ObDDLRedoLogWriterCallback::init(const ObDDLMacroBlockType block_type, +int ObDDLRedoLogWriterCallback::init(const share::ObLSID &ls_id, + const ObTabletID &tablet_id, + const ObDDLMacroBlockType block_type, const ObITable::TableKey &table_key, const int64_t task_id, const share::SCN &start_scn, const uint64_t data_format_version, - ObDDLRedoLogWriter *ddl_writer, const int64_t row_id_offset/*=-1*/) { int ret = OB_SUCCESS; @@ -1514,17 +1526,18 @@ int ObDDLRedoLogWriterCallback::init(const ObDDLMacroBlockType block_type, if (OB_UNLIKELY(is_inited_)) { ret = OB_INIT_TWICE; LOG_WARN("ddl redo log writer has been inited twice", K(ret)); - } else if (OB_UNLIKELY(!table_key.is_valid() || nullptr == ddl_writer || DDL_MB_INVALID_TYPE == block_type || 0 == task_id - || data_format_version < 0)) { + } else if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid() || !table_key.is_valid() || + DDL_MB_INVALID_TYPE == block_type || 0 == task_id || data_format_version < 0)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid arguments", K(ret), K(table_key), K(block_type), K(data_format_version), K(task_id), KP(ddl_writer)); + LOG_WARN("invalid arguments", K(ret), K(ls_id), K(tablet_id), K(table_key), K(block_type), K(data_format_version), K(task_id)); } else if (OB_UNLIKELY(table_key.is_column_store_sstable() && row_id_offset < 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument of column group data", K(ret), K(table_key), K(row_id_offset)); + } else if (OB_FAIL(ddl_writer_.init(ls_id, tablet_id))) { + LOG_WARN("fail to init ddl_writer_", K(ret), K(ls_id), K(tablet_id)); } else { block_type_ = block_type; table_key_ = table_key; - ddl_writer_ = ddl_writer; task_id_ = task_id; start_scn_ = start_scn; data_format_version_ = data_format_version; @@ -1541,7 +1554,7 @@ void ObDDLRedoLogWriterCallback::reset() block_type_ = ObDDLMacroBlockType::DDL_MB_INVALID_TYPE; table_key_.reset(); macro_block_id_.reset(); - ddl_writer_ = nullptr; + ddl_writer_.reset(); task_id_ = 0; start_scn_.reset(); data_format_version_ = 0; @@ -1574,11 +1587,12 @@ int ObDDLRedoLogWriterCallback::write(const ObMacroBlockHandle ¯o_handle, redo_info_.logic_id_ = logic_id; redo_info_.start_scn_ = start_scn_; redo_info_.data_format_version_ = data_format_version_; + redo_info_.type_ = ObDirectLoadType::DIRECT_LOAD_LOAD_DATA; if (is_column_group_info_valid()) { redo_info_.end_row_id_ = row_id_offset_ + row_count - 1; row_id_offset_ += row_count; } - if (OB_FAIL(ddl_writer_->write_macro_block_log(redo_info_, macro_block_id_, true/*allow remote write*/, task_id_))) { + if (OB_FAIL(ddl_writer_.write_macro_block_log(redo_info_, macro_block_id_, true/*allow remote write*/, task_id_))) { LOG_WARN("fail to write ddl redo log", K(ret)); if (ObDDLRedoLogWriter::need_retry(ret)) { int tmp_ret = OB_SUCCESS; @@ -1599,7 +1613,7 @@ int ObDDLRedoLogWriterCallback::wait() if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDDLRedoLogWriterCallback is not inited", K(ret)); - } else if (OB_FAIL(ddl_writer_->wait_macro_block_log_finish(redo_info_, macro_block_id_))) { + } else if (OB_FAIL(ddl_writer_.wait_macro_block_log_finish(redo_info_, macro_block_id_))) { LOG_WARN("fail to wait redo log finish", K(ret)); } return ret; @@ -1623,9 +1637,9 @@ int ObDDLRedoLogWriterCallback::retry(const int64_t timeout_us) while (ObTimeUtility::fast_current_time() - start_ts < timeout_us) { // ignore ret if (OB_FAIL(THIS_WORKER.check_status())) { LOG_WARN("check status failed", K(ret)); - } else if (OB_FAIL(ddl_writer_->write_macro_block_log(redo_info_, macro_block_id_, true/*allow remote write*/, task_id_))) { + } else if (OB_FAIL(ddl_writer_.write_macro_block_log(redo_info_, macro_block_id_, true/*allow remote write*/, task_id_))) { LOG_WARN("fail to write ddl redo log", K(ret)); - } else if (OB_FAIL(ddl_writer_->wait_macro_block_log_finish(redo_info_, macro_block_id_))) { + } else if (OB_FAIL(ddl_writer_.wait_macro_block_log_finish(redo_info_, macro_block_id_))) { LOG_WARN("wait ddl redo log finish failed", K(ret)); } else { FLOG_INFO("retry write ddl macro redo success", K(ret), K(table_key_), K(macro_block_id_)); diff --git a/src/storage/ddl/ob_ddl_redo_log_writer.h b/src/storage/ddl/ob_ddl_redo_log_writer.h index f54b90eb9..d1fb3c451 100644 --- a/src/storage/ddl/ob_ddl_redo_log_writer.h +++ b/src/storage/ddl/ob_ddl_redo_log_writer.h @@ -26,7 +26,6 @@ namespace oceanbase namespace blocksstable { -struct ObDDLMacroBlockRedoInfo; struct ObSSTableMergeRes; } @@ -39,6 +38,31 @@ class ObLogHandler; namespace storage { class ObLSHandle; +class ObDDLNeedStopWriteChecker +{ +public: + virtual bool check_need_stop_write() = 0; +}; + +class ObDDLFullNeedStopWriteChecker : public ObDDLNeedStopWriteChecker +{ +public: + ObDDLFullNeedStopWriteChecker(ObDDLKvMgrHandle &ddl_kv_mgr_handle) : ddl_kv_mgr_handle_(ddl_kv_mgr_handle) {} + virtual ~ObDDLFullNeedStopWriteChecker() {} + virtual bool check_need_stop_write() override; +public: + ObDDLKvMgrHandle &ddl_kv_mgr_handle_; +}; + +class ObDDLIncNeedStopWriteChecker : public ObDDLNeedStopWriteChecker +{ +public: + ObDDLIncNeedStopWriteChecker(ObTablet &tablet) : tablet_(tablet) {} + virtual ~ObDDLIncNeedStopWriteChecker() {} + virtual bool check_need_stop_write() override; +public: + ObTablet &tablet_; +}; // control the write speed of ddl clog for 4.0 . More detailly, // a. set write speed to the log archive speed if archive is on; @@ -57,9 +81,9 @@ public: int limit_and_sleep(const int64_t bytes, const uint64_t tenant_id, const int64_t task_id, - ObDDLKvMgrHandle &ddl_kv_mgr_handle, + ObDDLNeedStopWriteChecker &checker, int64_t &real_sleep_us); - int check_need_stop_write(ObDDLKvMgrHandle &ddl_kv_mgr_handle, + int check_need_stop_write(ObDDLNeedStopWriteChecker &checker, bool &is_need_stop_write); // for ref_cnt_ void inc_ref() { ATOMIC_INC(&ref_cnt_); } @@ -74,7 +98,7 @@ private: int do_sleep(const int64_t next_available_ts, const uint64_t tenant_id, const int64_t task_id, - ObDDLKvMgrHandle &ddl_kv_mgr_handle, + ObDDLNeedStopWriteChecker &checker, int64_t &real_sleep_us); private: static const int64_t MIN_WRITE_SPEED = 50L; @@ -98,7 +122,7 @@ public: const share::ObLSID &ls_id, const int64_t bytes, const int64_t task_id, - ObDDLKvMgrHandle &ddl_kv_mgr_handle, + ObDDLNeedStopWriteChecker &checker, int64_t &real_sleep_us); private: @@ -258,12 +282,12 @@ public: uint32_t &lock_tid, share::SCN &start_scn); int write_macro_block_log( - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const blocksstable::MacroBlockId ¯o_block_id, const bool allow_remote_write, const int64_t task_id); int wait_macro_block_log_finish( - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const blocksstable::MacroBlockId ¯o_block_id); int write_commit_log( const bool allow_remote_write, @@ -310,12 +334,12 @@ private: share::SCN &commit_scn); int retry_remote_write_macro_redo( const int64_t task_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info); + const storage::ObDDLMacroBlockRedoInfo &redo_info); int retry_remote_write_commit_clog( const obrpc::ObRpcRemoteWriteDDLCommitLogArg &arg, share::SCN &commit_scn); int local_write_ddl_macro_redo( - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info, + const storage::ObDDLMacroBlockRedoInfo &redo_info, const share::ObLSID &ls_id, const int64_t task_id, logservice::ObLogHandler *log_handler, @@ -324,7 +348,7 @@ private: ObDDLRedoLogHandle &handle); int remote_write_ddl_macro_redo( const int64_t task_id, - const blocksstable::ObDDLMacroBlockRedoInfo &redo_info); + const storage::ObDDLMacroBlockRedoInfo &redo_info); private: bool is_inited_; bool remote_write_; @@ -343,12 +367,13 @@ public: ObDDLRedoLogWriterCallback(); virtual ~ObDDLRedoLogWriterCallback(); int init( - const blocksstable::ObDDLMacroBlockType block_type, + const share::ObLSID &ls_id, + const ObTabletID &tablet_id, + const storage::ObDDLMacroBlockType block_type, const ObITable::TableKey &table_key, const int64_t task_id, const share::SCN &start_scn, const uint64_t data_format_version, - ObDDLRedoLogWriter *ddl_writer, const int64_t row_id_offset = -1); void reset(); int write( @@ -364,11 +389,11 @@ private: int retry(const int64_t timeout_us); private: bool is_inited_; - blocksstable::ObDDLMacroBlockRedoInfo redo_info_; - blocksstable::ObDDLMacroBlockType block_type_; + storage::ObDDLMacroBlockRedoInfo redo_info_; + storage::ObDDLMacroBlockType block_type_; ObITable::TableKey table_key_; blocksstable::MacroBlockId macro_block_id_; - ObDDLRedoLogWriter *ddl_writer_; + ObDDLRedoLogWriter ddl_writer_; int64_t task_id_; share::SCN start_scn_; uint64_t data_format_version_; diff --git a/src/storage/ddl/ob_ddl_replay_executor.cpp b/src/storage/ddl/ob_ddl_replay_executor.cpp index 326dc3cf1..53c219454 100644 --- a/src/storage/ddl/ob_ddl_replay_executor.cpp +++ b/src/storage/ddl/ob_ddl_replay_executor.cpp @@ -40,12 +40,74 @@ int ObDDLReplayExecutor::check_need_replay_ddl_log_( int ret = OB_SUCCESS; need_replay = true; ObTablet *tablet = nullptr; - ObDDLKvMgrHandle ddl_kv_mgr_handle; ObMigrationStatus migration_status; if (OB_UNLIKELY(nullptr == ls || !tablet_handle.is_valid() || !ddl_start_scn.is_valid_and_not_min() || !scn.is_valid_and_not_min())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("not init", K(ret), KP(ls), K(tablet_handle), K(ddl_start_scn), K(scn)); - } else if (OB_FAIL(ls->get_ls_meta().get_migration_status(migration_status))) { + } else if (OB_FAIL(check_need_replay_(ls, tablet_handle, need_replay))) { + LOG_WARN("fail to check need replay", K(ret), KP(ls), K(tablet_handle)); + } else if (!need_replay) { + // do nothing + } else if (OB_ISNULL(tablet = tablet_handle.get_obj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tablet is null", K(ret), K(tablet_handle)); + } else if (scn <= tablet->get_tablet_meta().ddl_checkpoint_scn_) { + need_replay = false; + if (REACH_COUNT_INTERVAL(1000L)) { + LOG_INFO("no need to replay ddl log, because the log ts is less than the ddl checkpoint ts", + K(tablet_handle), K(scn), "ddl_checkpoint_ts", tablet->get_tablet_meta().ddl_checkpoint_scn_); + } + } else if (ddl_start_scn < tablet->get_tablet_meta().ddl_start_scn_) { + need_replay = false; + if (REACH_COUNT_INTERVAL(1000L)) { + LOG_INFO("no need to replay ddl log, because the ddl start log ts is less than the value in ddl kv manager", + K(tablet_handle), K(ddl_start_scn), "ddl_start_scn_in_tablet", tablet->get_tablet_meta().ddl_start_scn_); + } + } + return ret; +} + +int ObDDLReplayExecutor::check_need_replay_ddl_inc_log_( + const ObLS *ls, + const ObTabletHandle &tablet_handle, + const share::SCN &scn, + bool &need_replay) +{ + int ret = OB_SUCCESS; + need_replay = true; + ObTablet *tablet = nullptr; + ObMigrationStatus migration_status; + if (OB_UNLIKELY(nullptr == ls || !tablet_handle.is_valid() || !scn.is_valid_and_not_min())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("not init", K(ret), KP(ls), K(tablet_handle), K(scn)); + } else if (OB_FAIL(check_need_replay_(ls, tablet_handle, need_replay))) { + LOG_WARN("fail to check need replay", K(ret), KP(ls), K(tablet_handle)); + } else if (!need_replay) { + // do nothing + } else if (OB_ISNULL(tablet = tablet_handle.get_obj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tablet is null", K(ret), K(tablet_handle)); + } else if (scn <= tablet->get_tablet_meta().clog_checkpoint_scn_) { + need_replay = false; + if (REACH_COUNT_INTERVAL(1000L)) { + LOG_INFO("no need to replay ddl inc log, because the log ts is less than the clog checkpoint ts", + K(tablet_handle), K(scn), "clog_checkpoint_ts", tablet->get_tablet_meta().clog_checkpoint_scn_); + } + } + + return ret; +} + +int ObDDLReplayExecutor::check_need_replay_( + const ObLS *ls, + const ObTabletHandle &tablet_handle, + bool &need_replay) +{ + int ret = OB_SUCCESS; + need_replay = true; + ObTablet *tablet = nullptr; + ObMigrationStatus migration_status; + if (OB_FAIL(ls->get_ls_meta().get_migration_status(migration_status))) { LOG_WARN("get migration status failed", K(ret), KPC(ls)); } else if (ObMigrationStatus::OB_MIGRATION_STATUS_ADD_FAIL == migration_status || ObMigrationStatus::OB_MIGRATION_STATUS_MIGRATE_FAIL == migration_status) { @@ -66,19 +128,8 @@ int ObDDLReplayExecutor::check_need_replay_ddl_log_( LOG_INFO("no need to replay ddl log, because tablet will be deleted", K(tablet_handle), "tablet_meta", tablet->get_tablet_meta()); } - } else if (scn <= tablet->get_tablet_meta().ddl_checkpoint_scn_) { - need_replay = false; - if (REACH_COUNT_INTERVAL(1000L)) { - LOG_INFO("no need to replay ddl log, because the log ts is less than the ddl checkpoint ts", - K(tablet_handle), K(scn), "ddl_checkpoint_ts", tablet->get_tablet_meta().ddl_checkpoint_scn_); - } - } else if (ddl_start_scn < tablet->get_tablet_meta().ddl_start_scn_) { - need_replay = false; - if (REACH_COUNT_INTERVAL(1000L)) { - LOG_INFO("no need to replay ddl log, because the ddl start log ts is less than the value in ddl kv manager", - K(tablet_handle), K(ddl_start_scn), "ddl_start_scn_in_tablet", tablet->get_tablet_meta().ddl_start_scn_); - } } + return ret; } @@ -283,25 +334,94 @@ int ObDDLRedoReplayExecutor::init( int ObDDLRedoReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) { int ret = OB_SUCCESS; - bool need_replay = true; - ObTabletMemberWrapper table_store_wrapper; - - ObDDLMacroBlock macro_block; if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; LOG_WARN("ObDDLRedoLogExecutor has not been inited", K(ret)); - } else if (OB_UNLIKELY(!log_->is_valid())) { + } else if (OB_UNLIKELY(!tablet_handle.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid arguments", K(ret), K_(log)); - } else if (OB_FAIL(check_need_replay_ddl_log_(ls_, tablet_handle, log_->get_redo_info().start_scn_, scn_, need_replay))) { + LOG_WARN("invalid arguments", K(ret), K(tablet_handle)); + } else { + const ObDDLMacroBlockRedoInfo &redo_info = log_->get_redo_info(); + ObMacroBlockWriteInfo write_info; + ObDDLMacroBlock macro_block; + write_info.buffer_ = redo_info.data_buffer_.ptr(); + write_info.size_= redo_info.data_buffer_.length(); + write_info.io_desc_.set_wait_event(ObWaitEventIds::DB_FILE_COMPACT_WRITE); + write_info.io_timeout_ms_ = max(DDL_FLUSH_MACRO_BLOCK_TIMEOUT / 1000L, GCONF._data_storage_io_timeout / 1000L); + macro_block.block_type_ = redo_info.block_type_; + macro_block.logic_id_ = redo_info.logic_id_; + macro_block.scn_ = scn_; + macro_block.buf_ = redo_info.data_buffer_.ptr(); + macro_block.size_ = redo_info.data_buffer_.length(); + macro_block.ddl_start_scn_ = redo_info.start_scn_; + macro_block.table_key_ = redo_info.table_key_; + macro_block.end_row_id_ = redo_info.end_row_id_; + macro_block.trans_id_ = redo_info.trans_id_; + if (is_incremental_direct_load(redo_info.type_)) { + if (OB_FAIL(do_inc_replay_(tablet_handle, write_info, macro_block))) { + LOG_WARN("fail to do inc replay", K(ret)); + } + } else { + if (OB_FAIL(do_full_replay_(tablet_handle, write_info, macro_block))) { + LOG_WARN("fail to do full replay", K(ret)); + } + } + } + + return ret; +} + +int ObDDLRedoReplayExecutor::do_inc_replay_( + ObTabletHandle &tablet_handle, + blocksstable::ObMacroBlockWriteInfo &write_info, + storage::ObDDLMacroBlock ¯o_block) +{ + int ret = OB_SUCCESS; + bool need_replay = true; + if (OB_FAIL(check_need_replay_ddl_inc_log_(ls_, tablet_handle, scn_, need_replay))) { + if (OB_EAGAIN != ret) { + LOG_WARN("fail to check need replay ddl log", K(ret), K(scn_), K(log_)); + } + } else if (!need_replay) { + // do nothing + } else { + ObMacroBlockHandle macro_handle; + const ObDDLMacroBlockRedoInfo &redo_info = log_->get_redo_info(); + const ObITable::TableKey &table_key = redo_info.table_key_; + ObTabletID tablet_id = table_key.get_tablet_id(); + const int64_t snapshot_version = table_key .get_snapshot_version(); + const uint64_t data_format_version = redo_info.data_format_version_; + if (OB_FAIL(ObBlockManager::async_write_block(write_info, macro_handle))) { + LOG_WARN("fail to async write block", K(ret), K(write_info), K(macro_handle)); + } else if (OB_FAIL(macro_handle.wait())) { + LOG_WARN("fail to wait macro block io finish", K(ret), K(write_info)); + } else if (OB_FAIL(macro_block.block_handle_.set_block_id(macro_handle.get_macro_id()))) { + LOG_WARN("set macro block id failed", K(ret), K(macro_handle.get_macro_id())); + } else if (OB_FAIL(tablet_handle.get_obj()->set_macro_block(macro_block, snapshot_version, data_format_version))) { + LOG_WARN("fail to set_inc_macro_block", K(ret)); + } + FLOG_INFO("finish replay ddl inc redo log", K(ret), KPC_(log), K(macro_block), "ddl_event_info", ObDDLEventInfo()); + } + + return ret; +} + +int ObDDLRedoReplayExecutor::do_full_replay_( + ObTabletHandle &tablet_handle, + blocksstable::ObMacroBlockWriteInfo &write_info, + storage::ObDDLMacroBlock ¯o_block) +{ + int ret = OB_SUCCESS; + ObMacroBlockHandle macro_handle; + ObTabletID tablet_id = log_->get_redo_info().table_key_.get_tablet_id(); + bool need_replay = true; + ObTabletMemberWrapper table_store_wrapper; + if (OB_FAIL(check_need_replay_ddl_log_(ls_, tablet_handle, log_->get_redo_info().start_scn_, scn_, need_replay))) { if (OB_EAGAIN != ret) { LOG_WARN("fail to check need replay ddl log", K(ret), K_(tablet_id), K_(scn)); } } else if (!need_replay) { // do nothing - } else if (OB_UNLIKELY(!tablet_handle.is_valid())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("need replay but tablet handle is invalid", K(ret), K(need_replay), K(tablet_handle)); } else if (OB_FAIL(tablet_handle.get_obj()->fetch_table_store(table_store_wrapper))) { LOG_WARN("fail to fetch table store", K(ret)); } else if (!table_store_wrapper.get_member()->get_major_sstables().empty()) { @@ -311,13 +431,6 @@ int ObDDLRedoReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) LOG_INFO("no need to replay ddl log, because the major sstable already exist", K_(tablet_id)); } } else { - ObMacroBlockWriteInfo write_info; - ObMacroBlockHandle macro_handle; - const ObDDLMacroBlockRedoInfo &redo_info = log_->get_redo_info(); - write_info.buffer_ = redo_info.data_buffer_.ptr(); - write_info.size_= redo_info.data_buffer_.length(); - write_info.io_desc_.set_wait_event(ObWaitEventIds::DB_FILE_COMPACT_WRITE); - write_info.io_timeout_ms_ = max(DDL_FLUSH_MACRO_BLOCK_TIMEOUT / 1000L, GCONF._data_storage_io_timeout / 1000L); if (OB_FAIL(ObBlockManager::async_write_block(write_info, macro_handle))) { LOG_WARN("fail to async write block", K(ret), K(write_info), K(macro_handle)); } else if (OB_FAIL(macro_handle.wait())) { @@ -325,32 +438,22 @@ int ObDDLRedoReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) } else if (OB_FAIL(macro_block.block_handle_.set_block_id(macro_handle.get_macro_id()))) { LOG_WARN("set macro block id failed", K(ret), K(macro_handle.get_macro_id())); } else { - macro_block.block_type_ = redo_info.block_type_; - macro_block.logic_id_ = redo_info.logic_id_; - macro_block.scn_ = scn_; - macro_block.buf_ = redo_info.data_buffer_.ptr(); - macro_block.size_ = redo_info.data_buffer_.length(); - macro_block.ddl_start_scn_ = redo_info.start_scn_; - macro_block.table_key_ = redo_info.table_key_; - macro_block.end_row_id_ = redo_info.end_row_id_; - const int64_t snapshot_version = redo_info.table_key_.get_snapshot_version(); + const ObDDLMacroBlockRedoInfo &redo_info = log_->get_redo_info(); const ObITable::TableKey &table_key = redo_info.table_key_; + const int64_t snapshot_version = redo_info.table_key_.get_snapshot_version(); bool is_major_sstable_exist = false; uint64_t data_format_version = redo_info.data_format_version_; - - // to upgrade from lower version without `data_format_version` in redo log, - // use data_format_version in start log instead. ObTabletDirectLoadMgrHandle direct_load_mgr_handle; ObTenantDirectLoadMgr *tenant_direct_load_mgr = MTL(ObTenantDirectLoadMgr *); if (OB_ISNULL(tenant_direct_load_mgr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected err", K(ret)); } else if (OB_FAIL(tenant_direct_load_mgr->get_tablet_mgr_and_check_major( - ls_->get_ls_id(), - redo_info.table_key_.tablet_id_, - true/* is_full_direct_load */, - direct_load_mgr_handle, - is_major_sstable_exist))) { + ls_->get_ls_id(), + redo_info.table_key_.tablet_id_, + true/* is_full_direct_load */, + direct_load_mgr_handle, + is_major_sstable_exist))) { if (OB_ENTRY_NOT_EXIST == ret && is_major_sstable_exist) { need_replay = false; ret = OB_SUCCESS; @@ -370,13 +473,14 @@ int ObDDLRedoReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) ret = OB_SUCCESS; } else { LOG_WARN("set macro block into ddl kv failed", K(ret), K(tablet_handle), K(macro_block), - K(snapshot_version), K(data_format_version)); + K(snapshot_version), K(data_format_version)); } } } } } - FLOG_INFO("finish replay ddl redo log", K(ret), K(need_replay), KPC_(log), K(macro_block), "ddl_event_info", ObDDLEventInfo()); + FLOG_INFO("finish replay ddl full redo log", K(ret), K(need_replay), KPC_(log), K(macro_block), "ddl_event_info", ObDDLEventInfo()); + return ret; } @@ -384,7 +488,6 @@ int ObDDLRedoReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) ObDDLCommitReplayExecutor::ObDDLCommitReplayExecutor() : ObDDLReplayExecutor(), log_(nullptr) { - } int ObDDLCommitReplayExecutor::init( @@ -498,6 +601,140 @@ int ObDDLCommitReplayExecutor::replay_ddl_commit(ObTabletHandle &tablet_handle) return ret; } +// ObDDLIncStartReplayExecutor +ObDDLIncStartReplayExecutor::ObDDLIncStartReplayExecutor() + : ObDDLReplayExecutor(), log_(nullptr) +{ +} + +int ObDDLIncStartReplayExecutor::init( + ObLS *ls, + const ObDDLIncStartLog &log, + const share::SCN &scn) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", KR(ret), K_(is_inited)); + } else if (OB_ISNULL(ls) + || OB_UNLIKELY(!log.is_valid()) + || OB_UNLIKELY(!scn.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), KP(ls), K(log), K(scn)); + } else { + ls_ = ls; + log_ = &log; + scn_ = scn; + is_inited_ = true; + } + + return ret; +} + +int ObDDLIncStartReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) +{ + int ret = OB_SUCCESS; + bool need_replay = true; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDDLIncStartReplayExecutor has not been inited", K(ret)); + } else if (OB_UNLIKELY(!tablet_handle.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(tablet_handle)); + } else if (OB_FAIL(check_need_replay_ddl_inc_log_(ls_, tablet_handle, scn_, need_replay))) { + if (OB_EAGAIN != ret) { + LOG_WARN("fail to check need replay ddl log", K(ret), K(scn_), K(log_)); + } + } else if (!need_replay) { + // do nothing + } else { + ObTabletID tablet_id = log_->get_log_basic().get_tablet_id(); + ObTabletID lob_meta_tablet_id = log_->get_log_basic().get_lob_meta_tablet_id(); + if (OB_ISNULL(ls_) || !tablet_id.is_valid()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KP(ls_), K(tablet_id)); + } else { + int tmp_ret = ls_->sync_tablet_freeze_for_direct_load(tablet_id); + int tmp_ret_lob = OB_SUCCESS; + if (lob_meta_tablet_id.is_valid()) { + tmp_ret_lob = ls_->sync_tablet_freeze_for_direct_load(lob_meta_tablet_id); + } + ret = tmp_ret | tmp_ret_lob; + if (OB_FAIL(ret)) { + LOG_ERROR("sync freeze failed", KR(ret), KR(tmp_ret), KR(tmp_ret_lob), K(tablet_id), K(lob_meta_tablet_id)); + } + } + } + + return ret; +} + +// ObDDLIncCommitReplayExecutor +ObDDLIncCommitReplayExecutor::ObDDLIncCommitReplayExecutor() + : ObDDLReplayExecutor(), log_(nullptr) +{ +} + +int ObDDLIncCommitReplayExecutor::init( + ObLS *ls, + const ObDDLIncCommitLog &log, + const share::SCN &scn) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(is_inited_)) { + ret = OB_INIT_TWICE; + LOG_WARN("init twice", KR(ret), K_(is_inited)); + } else if (OB_ISNULL(ls) + || OB_UNLIKELY(!log.is_valid()) + || OB_UNLIKELY(!scn.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), KP(ls), K(log), K(scn)); + } else { + ls_ = ls; + log_ = &log; + scn_ = scn; + is_inited_ = true; + } + + return ret; +} + +int ObDDLIncCommitReplayExecutor::do_replay_(ObTabletHandle &tablet_handle) +{ + int ret = OB_SUCCESS; + bool need_replay = true; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDDLIncCommitReplayExecutor has not been inited", K(ret)); + } else if (OB_UNLIKELY(!tablet_handle.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(tablet_handle)); + } else if (OB_FAIL(check_need_replay_ddl_inc_log_(ls_, tablet_handle, scn_, need_replay))) { + if (OB_EAGAIN != ret) { + LOG_WARN("fail to check need replay ddl log", K(ret), K(scn_), K(log_)); + } + } else if (!need_replay) { + // do nothing + } else { + ObTabletID tablet_id = log_->get_log_basic().get_tablet_id(); + ObTabletID lob_meta_tablet_id = log_->get_log_basic().get_lob_meta_tablet_id(); + if (OB_ISNULL(ls_) || !tablet_id.is_valid()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KP(ls_), K(tablet_id)); + } else { + int tmp_ret = ls_->sync_tablet_freeze_for_direct_load(tablet_id); + int tmp_ret_lob = OB_SUCCESS; + if (lob_meta_tablet_id.is_valid()) { + tmp_ret_lob = ls_->sync_tablet_freeze_for_direct_load(lob_meta_tablet_id); + } + ret = tmp_ret | tmp_ret_lob; + if (OB_FAIL(ret)) { + LOG_ERROR("sync freeze failed", KR(ret), KR(tmp_ret), KR(tmp_ret_lob), K(tablet_id), K(lob_meta_tablet_id)); + } + } + } + return ret; +} // ObSchemaChangeReplayExecutor ObSchemaChangeReplayExecutor::ObSchemaChangeReplayExecutor() diff --git a/src/storage/ddl/ob_ddl_replay_executor.h b/src/storage/ddl/ob_ddl_replay_executor.h index be673aa78..629fde8a3 100644 --- a/src/storage/ddl/ob_ddl_replay_executor.h +++ b/src/storage/ddl/ob_ddl_replay_executor.h @@ -16,6 +16,7 @@ #include "common/ob_tablet_id.h" #include "logservice/replayservice/ob_tablet_replay_executor.h" #include "storage/ddl/ob_ddl_clog.h" +#include "storage/ddl/ob_ddl_inc_clog.h" #include "storage/ddl/ob_ddl_struct.h" #include "storage/blocksstable/ob_block_sstable_struct.h" @@ -44,6 +45,11 @@ protected: const share::SCN &ddl_start_scn, const share::SCN &scn, bool &need_replay); + static int check_need_replay_ddl_inc_log_( + const ObLS *ls, + const ObTabletHandle &tablet_handle, + const share::SCN &scn, + bool &need_replay); static int get_lob_meta_tablet_id( const ObTabletHandle &tablet_handle, @@ -55,7 +61,11 @@ protected: { return false; } - +private: + static int check_need_replay_( + const ObLS *ls, + const ObTabletHandle &tablet_handle, + bool &need_replay); protected: ObLS *ls_; common::ObTabletID tablet_id_; @@ -86,7 +96,6 @@ private: const ObDDLStartLog *log_; }; - class ObDDLRedoReplayExecutor final : public ObDDLReplayExecutor { public: @@ -104,12 +113,19 @@ protected: // @return OB_NO_NEED_UPDATE, this log needs to be ignored. // @return other error codes, failed to replay. int do_replay_(ObTabletHandle &handle) override; - +private: + int do_inc_replay_( + ObTabletHandle &tablet_handle, + blocksstable::ObMacroBlockWriteInfo &write_info, + storage::ObDDLMacroBlock ¯o_block); + int do_full_replay_( + ObTabletHandle &tablet_handle, + blocksstable::ObMacroBlockWriteInfo &write_info, + storage::ObDDLMacroBlock ¯o_block); private: const ObDDLRedoLog *log_; }; - class ObDDLCommitReplayExecutor final : public ObDDLReplayExecutor { public: @@ -134,6 +150,43 @@ private: const ObDDLCommitLog *log_; }; +class ObDDLIncStartReplayExecutor final : public ObDDLReplayExecutor +{ +public: + ObDDLIncStartReplayExecutor(); + + int init(ObLS *ls, const ObDDLIncStartLog &log, const share::SCN &scn); + +protected: + // replay to the tablet + // @return OB_SUCCESS, replay successfully, data has written to tablet. + // @return OB_EAGAIN, failed to replay, need retry. + // @return OB_NO_NEED_UPDATE, this log needs to be ignored. + // @return other error codes, failed to replay. + int do_replay_(ObTabletHandle &handle) override; + +private: + const ObDDLIncStartLog *log_; +}; + +class ObDDLIncCommitReplayExecutor final : public ObDDLReplayExecutor +{ +public: + ObDDLIncCommitReplayExecutor(); + + int init(ObLS *ls, const ObDDLIncCommitLog &log, const share::SCN &scn); + +protected: + // replay to the tablet + // @return OB_SUCCESS, replay successfully, data has written to tablet. + // @return OB_EAGAIN, failed to replay, need retry. + // @return OB_NO_NEED_UPDATE, this log needs to be ignored. + // @return other error codes, failed to replay. + int do_replay_(ObTabletHandle &handle) override; + +private: + const ObDDLIncCommitLog *log_; +}; class ObSchemaChangeReplayExecutor final : public logservice::ObTabletReplayExecutor { diff --git a/src/storage/ddl/ob_ddl_struct.cpp b/src/storage/ddl/ob_ddl_struct.cpp index e951dec13..c705f9b46 100644 --- a/src/storage/ddl/ob_ddl_struct.cpp +++ b/src/storage/ddl/ob_ddl_struct.cpp @@ -12,6 +12,7 @@ #define USING_LOG_PREFIX STORAGE +#include "storage/ls/ob_ls.h" #include "storage/ddl/ob_ddl_struct.h" #include "storage/ddl/ob_tablet_ddl_kv.h" #include "storage/ddl/ob_tablet_ddl_kv_mgr.h" @@ -19,6 +20,7 @@ #include "storage/blocksstable/ob_block_manager.h" #include "storage/meta_mem/ob_tenant_meta_mem_mgr.h" #include "storage/ddl/ob_direct_insert_sstable_ctx_new.h" +#include "storage/ob_i_table.h" using namespace oceanbase::storage; using namespace oceanbase::blocksstable; @@ -78,8 +80,16 @@ int ObDDLMacroHandle::reset_macro_block_ref() } ObDDLMacroBlock::ObDDLMacroBlock() - : block_handle_(), logic_id_(), block_type_(DDL_MB_INVALID_TYPE), ddl_start_scn_(SCN::min_scn()), - scn_(SCN::min_scn()), buf_(nullptr), size_(0), table_key_(), end_row_id_(-1) + : block_handle_(), + logic_id_(), + block_type_(DDL_MB_INVALID_TYPE), + ddl_start_scn_(SCN::min_scn()), + scn_(SCN::min_scn()), + buf_(nullptr), + size_(0), + table_key_(), + end_row_id_(-1), + trans_id_() { } @@ -135,11 +145,25 @@ ObDDLKVHandle &ObDDLKVHandle::operator =(const ObDDLKVHandle &other) if (OB_NOT_NULL(other.ddl_kv_)) { ddl_kv_ = other.ddl_kv_; ddl_kv_->inc_ref(); + t3m_ = other.t3m_; + allocator_ = other.allocator_; } } return *this; } +bool ObDDLKVHandle::is_valid() const +{ + bool bret = false; + if (nullptr == ddl_kv_) { + } else if (ddl_kv_->is_inc_ddl_kv()) { + bret = (nullptr != t3m_) ^ (nullptr != allocator_); + } else { + bret = (nullptr == t3m_) & (nullptr == allocator_); + } + return bret; +} + int ObDDLKVHandle::set_obj(ObDDLKV *ddl_kv) { int ret = OB_SUCCESS; @@ -154,12 +178,50 @@ int ObDDLKVHandle::set_obj(ObDDLKV *ddl_kv) return ret; } +int ObDDLKVHandle::set_obj(ObTableHandleV2 &table_handle) +{ + int ret = OB_SUCCESS; + ObDDLKV *ddl_kv = nullptr; + if (OB_UNLIKELY(!table_handle.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(table_handle)); + } else if (OB_FAIL(table_handle.get_direct_load_memtable(ddl_kv))) { + LOG_WARN("fail to get direct load memtable", K(ret), K(table_handle)); + } else { + reset(); + ddl_kv_ = ddl_kv; + ddl_kv_->inc_ref(); + t3m_ = table_handle.get_t3m(); + allocator_ = table_handle.get_allocator(); + } + return ret; +} + void ObDDLKVHandle::reset() { if (nullptr != ddl_kv_) { - ddl_kv_->dec_ref(); - ddl_kv_ = nullptr; + if (OB_UNLIKELY(!is_valid())) { + LOG_ERROR_RET(OB_INVALID_ERROR, "t3m or allocator is nullptr", KP_(ddl_kv), KP_(t3m), KP_(allocator)); + ob_abort(); + } else { + const int64_t ref_cnt = ddl_kv_->dec_ref(); + if (0 == ref_cnt) { + if (nullptr != t3m_) { + t3m_->push_table_into_gc_queue(ddl_kv_, ObITable::DIRECT_LOAD_MEMTABLE); + } else if (nullptr != allocator_) { + ddl_kv_->~ObDDLKV(); + allocator_->free(ddl_kv_); + } else { + MTL(ObTenantMetaMemMgr *)->release_ddl_kv(ddl_kv_); + } + } else if (OB_UNLIKELY(ref_cnt < 0)) { + LOG_ERROR_RET(OB_ERR_UNEXPECTED, "table ref cnt may be leaked", K(ref_cnt), KP(ddl_kv_)); + } + } } + ddl_kv_ = nullptr; + t3m_ = nullptr; + allocator_ = nullptr; } ObDDLKVPendingGuard::ObDDLKVPendingGuard(ObTablet *tablet, const SCN &scn, const SCN &start_scn, @@ -251,6 +313,54 @@ int ObDDLKVPendingGuard::set_macro_block( return ret; } +ObDDLMacroBlockRedoInfo::ObDDLMacroBlockRedoInfo() + : table_key_(), + data_buffer_(), + block_type_(ObDDLMacroBlockType::DDL_MB_INVALID_TYPE), + start_scn_(SCN::min_scn()), + data_format_version_(0/*for compatibility*/), + end_row_id_(-1), + type_(ObDirectLoadType::DIRECT_LOAD_INVALID), + trans_id_() +{ +} + +void ObDDLMacroBlockRedoInfo::reset() +{ + table_key_.reset(); + data_buffer_.reset(); + block_type_ = ObDDLMacroBlockType::DDL_MB_INVALID_TYPE; + logic_id_.reset(); + start_scn_ = SCN::min_scn(); + data_format_version_ = 0; + end_row_id_ = -1; + type_ = ObDirectLoadType::DIRECT_LOAD_INVALID; + trans_id_.reset(); +} + +bool ObDDLMacroBlockRedoInfo::is_valid() const +{ + return table_key_.is_valid() && data_buffer_.ptr() != nullptr && block_type_ != ObDDLMacroBlockType::DDL_MB_INVALID_TYPE + && logic_id_.is_valid() && start_scn_.is_valid_and_not_min() && data_format_version_ >= 0 + && type_ > ObDirectLoadType::DIRECT_LOAD_INVALID && type_ < ObDirectLoadType::DIRECT_LOAD_MAX + && (is_incremental_direct_load(type_) ? trans_id_.is_valid() : !trans_id_.is_valid()); +} + +bool ObDDLMacroBlockRedoInfo::is_column_group_info_valid() const +{ + return table_key_.is_column_store_sstable() && end_row_id_ >= 0; +} + +OB_SERIALIZE_MEMBER(ObDDLMacroBlockRedoInfo, + table_key_, + data_buffer_, + block_type_, + logic_id_, + start_scn_, + data_format_version_, + end_row_id_, + type_, + trans_id_); ObTabletDirectLoadMgrHandle::ObTabletDirectLoadMgrHandle() : tablet_mgr_(nullptr) @@ -321,4 +431,4 @@ int ObTabletDirectLoadMgrHandle::assign(const ObTabletDirectLoadMgrHandle &other } } return ret; -} +} \ No newline at end of file diff --git a/src/storage/ddl/ob_ddl_struct.h b/src/storage/ddl/ob_ddl_struct.h index c189f5c65..add0371fc 100644 --- a/src/storage/ddl/ob_ddl_struct.h +++ b/src/storage/ddl/ob_ddl_struct.h @@ -24,6 +24,13 @@ namespace storage static const int64_t DDL_FLUSH_MACRO_BLOCK_TIMEOUT = 5 * 1000 * 1000; +enum ObDDLMacroBlockType +{ + DDL_MB_INVALID_TYPE = 0, + DDL_MB_DATA_TYPE = 1, + DDL_MB_INDEX_TYPE = 2, +}; + class ObDDLMacroHandle { public: @@ -49,35 +56,49 @@ public: int deep_copy(ObDDLMacroBlock &dst_block, common::ObIAllocator &allocator) const; bool is_valid() const; bool is_column_group_info_valid() const; - TO_STRING_KV(K_(block_handle), K_(logic_id), K_(block_type), K_(ddl_start_scn), - K_(scn), KP_(buf), K_(size), K_(table_key), K_(end_row_id)); + TO_STRING_KV(K_(block_handle), + K_(logic_id), + K_(block_type), + K_(ddl_start_scn), + K_(scn), + KP_(buf), + K_(size), + K_(table_key), + K_(end_row_id), + K_(trans_id)); public: ObDDLMacroHandle block_handle_; blocksstable::ObLogicMacroBlockId logic_id_; - blocksstable::ObDDLMacroBlockType block_type_; + ObDDLMacroBlockType block_type_; share::SCN ddl_start_scn_; share::SCN scn_; const char *buf_; int64_t size_; ObITable::TableKey table_key_; int64_t end_row_id_; + transaction::ObTransID trans_id_; // for incremental direct load only }; class ObDDLKV; class ObDDLKVHandle final { public: - ObDDLKVHandle() : ddl_kv_(nullptr) {} - ObDDLKVHandle(const ObDDLKVHandle &other) : ddl_kv_(nullptr) { *this = other; } + ObDDLKVHandle() : ddl_kv_(nullptr), t3m_(nullptr), allocator_(nullptr) {} + ObDDLKVHandle(const ObDDLKVHandle &other) : ddl_kv_(nullptr), t3m_(nullptr), allocator_(nullptr) { *this = other; } ObDDLKVHandle &operator =(const ObDDLKVHandle &other); ~ObDDLKVHandle() { reset(); } ObDDLKV* get_obj() const { return ddl_kv_; } - bool is_valid() const { return nullptr != ddl_kv_; } + bool is_valid() const; + // for full direct load int set_obj(ObDDLKV *ddl_kv); + // for incremental direct load + int set_obj(ObTableHandleV2 &table_handle); void reset(); TO_STRING_KV(KP_(ddl_kv)); private: ObDDLKV *ddl_kv_; + ObTenantMetaMemMgr *t3m_; + common::ObIAllocator *allocator_; }; @@ -147,6 +168,36 @@ static inline bool is_incremental_direct_load(const ObDirectLoadType &type) return ObDirectLoadType::DIRECT_LOAD_INCREMENTAL == type; } +struct ObDDLMacroBlockRedoInfo final +{ + OB_UNIS_VERSION(1); +public: + ObDDLMacroBlockRedoInfo(); + ~ObDDLMacroBlockRedoInfo() = default; + bool is_valid() const; + bool is_column_group_info_valid() const; + void reset(); + TO_STRING_KV(K_(table_key), + K_(data_buffer), + K_(block_type), + K_(logic_id), + K_(start_scn), + K_(data_format_version), + K_(end_row_id), + K_(type), + K_(trans_id)); +public: + storage::ObITable::TableKey table_key_; + ObString data_buffer_; + ObDDLMacroBlockType block_type_; + blocksstable::ObLogicMacroBlockId logic_id_; + share::SCN start_scn_; + uint64_t data_format_version_; + int64_t end_row_id_; + storage::ObDirectLoadType type_; + transaction::ObTransID trans_id_; // for incremental direct load only +}; + class ObTabletDirectLoadMgr; class ObTabletFullDirectLoadMgr; class ObTabletIncDirectLoadMgr; diff --git a/src/storage/ddl/ob_direct_insert_sstable_ctx_new.cpp b/src/storage/ddl/ob_direct_insert_sstable_ctx_new.cpp index 165e500ea..e2a102f79 100644 --- a/src/storage/ddl/ob_direct_insert_sstable_ctx_new.cpp +++ b/src/storage/ddl/ob_direct_insert_sstable_ctx_new.cpp @@ -27,6 +27,7 @@ #include "storage/ddl/ob_direct_load_struct.h" #include "storage/ddl/ob_ddl_merge_task.h" #include "storage/ddl/ob_ddl_redo_log_writer.h" +#include "storage/ddl/ob_ddl_inc_redo_log_writer.h" #include "storage/lob/ob_lob_util.h" #include "storage/tx_storage/ob_ls_service.h" #include "storage/column_store/ob_column_oriented_sstable.h" @@ -275,8 +276,17 @@ int ObTenantDirectLoadMgr::try_create_tablet_direct_load_mgr( } else if (OB_ISNULL(direct_load_mgr = direct_load_mgr_handle.get_obj())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected err", K(ret), K(mgr_key)); + } else if (!mgr_key.is_full_direct_load_) { + // For incremental direct load, different task cannot use the same ObTabletDirectLoadMgr, remove old ObTabletDirectLoadMgr + if (OB_FAIL(remove_tablet_direct_load_nolock(mgr_key))) { + LOG_WARN("fail to remove tablet direct load", K(ret), K(mgr_key)); + } else { + LOG_INFO("remove an old tablet direct load", K(mgr_key), K(context_id), "old_context_id", direct_load_mgr->get_context_id()); + direct_load_mgr = nullptr; + direct_load_mgr_handle.reset(); + } } - if (OB_SUCC(ret) && !major_sstable_exist) { + if (OB_SUCC(ret) && (!mgr_key.is_full_direct_load_ || !major_sstable_exist)) { if (nullptr == direct_load_mgr) { void *buf = nullptr; const int64_t buf_size = mgr_key.is_full_direct_load_ ? @@ -287,16 +297,11 @@ int ObTenantDirectLoadMgr::try_create_tablet_direct_load_mgr( } else if (mgr_key.is_full_direct_load_) { direct_load_mgr = new (buf) ObTabletFullDirectLoadMgr(); } else { - direct_load_mgr = new (buf) ObTabletIncDirectLoadMgr(); + direct_load_mgr = new (buf) ObTabletIncDirectLoadMgr(context_id); } if (OB_FAIL(ret)) { } else if (OB_FAIL(direct_load_mgr_handle.set_obj(direct_load_mgr))) { LOG_WARN("set direct load mgr failed", K(ret)); - } else if (OB_FAIL(tablet_mgr_map_.set_refactored(mgr_key, direct_load_mgr))) { - LOG_WARN("set tablet mgr failed", K(ret)); - } else { - direct_load_mgr->inc_ref(); - LOG_INFO("create tablet direct load mgr", K(mgr_key), K(execution_id), K(major_sstable_exist)); } // cleanup if failed. if (OB_FAIL(ret)) { @@ -309,6 +314,14 @@ int ObTenantDirectLoadMgr::try_create_tablet_direct_load_mgr( buf = nullptr; } } + // ownership of direct_load_mgr has been transferred to direct_load_mgr_handle + if (OB_FAIL(ret)) { + } else if (OB_FAIL(tablet_mgr_map_.set_refactored(mgr_key, direct_load_mgr))) { + LOG_WARN("set tablet mgr failed", K(ret)); + } else { + direct_load_mgr->inc_ref(); + LOG_INFO("create tablet direct load mgr", K(mgr_key), K(execution_id), K(major_sstable_exist)); + } } } if (OB_SUCC(ret) && need_set_exec_ctx) { // only build execution context map for data tablet @@ -359,6 +372,11 @@ int ObTenantDirectLoadMgr::open_tablet_direct_load( } else { LOG_WARN("get table mgr failed", K(ret), K(tablet_id), K(is_full_direct_load)); } + } + // TODO(suzhi.yt) remove this later + else if (!is_full_direct_load && context_id != handle.get_obj()->get_context_id()) { + ret = OB_TASK_EXPIRED; + LOG_WARN("tablet direct load context id not macth", K(ret), K(context_id), "current_context_id", handle.get_obj()->get_context_id()); } else { is_mgr_exist = true; } @@ -407,6 +425,9 @@ int ObTenantDirectLoadMgr::open_sstable_slice( } else { LOG_WARN("get table mgr failed", K(ret), K(slice_info)); } + } else if (!slice_info.is_full_direct_load_ && slice_info.context_id_ != handle.get_obj()->get_context_id()) { + ret = OB_TASK_EXPIRED; + LOG_WARN("tablet direct load context id not macth", K(ret), "context_id", slice_info.context_id_, "current_context_id", handle.get_obj()->get_context_id()); } else if (OB_FAIL(handle.get_obj()->open_sstable_slice( slice_info.is_lob_slice_/*is_data_tablet_process_for_lob*/, start_seq, new_slice_id))) { LOG_WARN("open sstable slice failed", K(ret), K(slice_info)); @@ -446,6 +467,9 @@ int ObTenantDirectLoadMgr::fill_sstable_slice( } } else if (OB_FAIL(get_tablet_exec_context_with_rlock(exec_id, exec_context))) { LOG_WARN("get tablet execution context failed", K(ret)); + } else if (!slice_info.is_full_direct_load_ && slice_info.context_id_ != handle.get_obj()->get_context_id()) { + ret = OB_TASK_EXPIRED; + LOG_WARN("tablet direct load context id not macth", K(ret), "context_id", slice_info.context_id_, "current_context_id", handle.get_obj()->get_context_id()); } else if (OB_FAIL(handle.get_obj()->fill_sstable_slice(slice_info, exec_context.start_scn_, iter, affected_rows, insert_monitor))) { if (OB_TRANS_COMMITED == ret && slice_info.is_full_direct_load_) { need_iter_part_row = true; @@ -491,6 +515,9 @@ int ObTenantDirectLoadMgr::fill_lob_sstable_slice( } } else if (OB_FAIL(get_tablet_exec_context_with_rlock(exec_id, exec_context))) { LOG_WARN("get tablet execution context failed", K(ret)); + } else if (!slice_info.is_full_direct_load_ && slice_info.context_id_ != handle.get_obj()->get_context_id()) { + ret = OB_TASK_EXPIRED; + LOG_WARN("tablet direct load context id not macth", K(ret), "context_id", slice_info.context_id_, "current_context_id", handle.get_obj()->get_context_id()); } else if (OB_FAIL(handle.get_obj()->fill_lob_sstable_slice(allocator, slice_info, exec_context.start_scn_, pk_interval, lob_column_idxs, col_types, datum_row))) { LOG_WARN("fail to fill batch sstable slice", KR(ret), K(slice_info), K(datum_row)); } @@ -512,6 +539,9 @@ int ObTenantDirectLoadMgr::calc_range( } else if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguement", K(ret), K(ls_id), K(tablet_id)); + } else if (OB_UNLIKELY(!is_full_direct_load)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected calc range in incremental direct load", K(ret)); } else if (OB_FAIL(get_tablet_mgr_and_check_major(ls_id, tablet_id, is_full_direct_load, handle, is_major_sstable_exist))) { if (OB_ENTRY_NOT_EXIST == ret && is_major_sstable_exist) { ret = OB_TASK_EXPIRED; @@ -565,6 +595,9 @@ int ObTenantDirectLoadMgr::fill_column_group( } else if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid() || thread_cnt <= 0 || thread_id < 0 || thread_id > thread_cnt - 1)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguement", K(ret), K(ls_id), K(tablet_id), K(thread_cnt), K(thread_id)); + } else if (OB_UNLIKELY(!is_full_direct_load)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected calc range in incremental direct load", K(ret)); } else if (OB_FAIL(get_tablet_mgr_and_check_major(ls_id, tablet_id, is_full_direct_load, handle, is_major_sstable_exist))) { if (OB_ENTRY_NOT_EXIST == ret && is_major_sstable_exist) { ret = OB_TASK_EXPIRED; @@ -579,6 +612,7 @@ int ObTenantDirectLoadMgr::fill_column_group( } int ObTenantDirectLoadMgr::cancel( + const int64_t context_id, const share::ObLSID &ls_id, const common::ObTabletID &tablet_id, const bool is_full_direct_load) @@ -590,16 +624,27 @@ int ObTenantDirectLoadMgr::cancel( if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; LOG_WARN("not init", K(ret)); - } else if (OB_UNLIKELY(!ls_id.is_valid() || !tablet_id.is_valid())) { + } else if (OB_UNLIKELY(context_id < 0 || !ls_id.is_valid() || !tablet_id.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid arguement", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(get_tablet_mgr_and_check_major(ls_id, tablet_id, is_full_direct_load, handle, is_major_sstable_exist))) { - if (OB_ENTRY_NOT_EXIST == ret && is_major_sstable_exist) { - ret = OB_TASK_EXPIRED; - LOG_INFO("direct load mgr not exist, but major sstable exist", K(ret), K(tablet_id)); - } else { - LOG_WARN("get table mgr failed", K(ret), K(tablet_id)); + LOG_WARN("invalid arguement", K(ret), K(context_id), K(ls_id), K(tablet_id)); + } else if (is_full_direct_load ) { + if (OB_FAIL(get_tablet_mgr_and_check_major(ls_id, tablet_id, is_full_direct_load, handle, is_major_sstable_exist))) { + if (OB_ENTRY_NOT_EXIST == ret && is_major_sstable_exist) { + ret = OB_TASK_EXPIRED; + LOG_INFO("direct load mgr not exist, but major sstable exist", K(ret), K(tablet_id)); + } else { + LOG_WARN("get table mgr failed", K(ret), K(tablet_id)); + } } + } else { + if (OB_FAIL(get_tablet_mgr(tablet_id, is_full_direct_load, handle))) { + LOG_WARN("get table mgr failed", K(ret), K(tablet_id), K(is_full_direct_load)); + } else if (context_id != handle.get_obj()->get_context_id()) { + ret = OB_TASK_EXPIRED; + LOG_WARN("tablet direct load context id not macth", K(ret), K(context_id), "current_context_id", handle.get_obj()->get_context_id()); + } + } + if (OB_FAIL(ret)) { } else if (OB_FAIL(handle.get_obj()->cancel())) { LOG_WARN("cancel fill sstable slice failed", K(ret)); } @@ -661,6 +706,7 @@ int ObTenantDirectLoadMgr::close_tablet_direct_load( ObTabletDirectLoadMgrHandle handle; ObTabletDirectLoadMgrKey mgr_key(tablet_id, is_full_direct_load); ObTabletDirectLoadExecContextId exec_id; + ObTabletDirectLoadExecContext exec_context; exec_id.tablet_id_ = tablet_id; exec_id.context_id_ = context_id; if (OB_UNLIKELY(!is_inited_)) { @@ -677,31 +723,44 @@ int ObTenantDirectLoadMgr::close_tablet_direct_load( } else { LOG_WARN("get table mgr failed", K(ret), K(ls_id), K(tablet_id)); } - } else { - if (need_commit) { - ObTabletDirectLoadExecContext exec_context; - if (OB_FAIL(get_tablet_exec_context_with_rlock(exec_id, exec_context))) { - LOG_WARN("get exec context failed", K(ret), K(exec_id)); - } else if (OB_FAIL(handle.get_obj()->close(exec_context.execution_id_, exec_context.start_scn_))) { - LOG_WARN("close failed", K(ret)); - } - } else { - // For full/incremental direct load, the ObTabletDirectLoadMgr will be removed from MTL when, + } else if (!is_full_direct_load && context_id != handle.get_obj()->get_context_id()) { + ret = OB_TASK_EXPIRED; + LOG_WARN("tablet direct load context id not macth", K(ret), K(context_id), "current_context_id", handle.get_obj()->get_context_id()); + } else if (need_commit) { + ObTabletDirectLoadExecContext exec_context; + if (OB_FAIL(get_tablet_exec_context_with_rlock(exec_id, exec_context))) { + LOG_WARN("get exec context failed", K(ret), K(exec_id)); + } else if (OB_FAIL(handle.get_obj()->close(exec_context.execution_id_, exec_context.start_scn_))) { + LOG_WARN("close failed", K(ret)); + } + } + if (OB_SUCC(ret)) { + if (is_full_direct_load) { + // For full direct load, the ObTabletDirectLoadMgr will be removed from MTL when, // 1. the direct load task abort indicated by `need_commit = false`, and we do not care about // the error code triggered by the not found ObTabletDirectLoadMgr after. // 2. the direct load task commit and all ddl kvs persist successfully. // But how to notify the follower to remove it, with write commit failed log or tablet gc task ?? - } - if (OB_SUCC(ret)) { - ObBucketHashWLockGuard guard(bucket_lock_, exec_id.hash()); - if (OB_FAIL(tablet_exec_context_map_.erase_refactored(exec_id))) { - LOG_WARN("erase tablet execution context failed", K(ret), K(exec_id)); - } else { - LOG_INFO("erase execution context", K(exec_id), K(tablet_id)); + } else { + // For incremental direct load, the ObTabletDirectLoadMgr will be removed immediately + ObTabletID lob_meta_tablet_id = handle.get_obj()->get_lob_meta_tablet_id(); + ObTabletDirectLoadMgrKey log_meta_mgr_key(lob_meta_tablet_id, is_full_direct_load); + if (log_meta_mgr_key.is_valid() && OB_FAIL(remove_tablet_direct_load(log_meta_mgr_key, context_id))) { + LOG_WARN("fail to remove lob meta tablet direct load", K(ret), K(log_meta_mgr_key), K(context_id)); + } else if (OB_FAIL(remove_tablet_direct_load(mgr_key, context_id))) { + LOG_WARN("fail to remove tablet direct load", K(ret), K(mgr_key), K(context_id)); } } } + if (OB_SUCC(ret)) { + ObBucketHashWLockGuard guard(bucket_lock_, exec_id.hash()); + if (OB_FAIL(tablet_exec_context_map_.erase_refactored(exec_id))) { + LOG_WARN("erase tablet execution context failed", K(ret), K(exec_id)); + } else { + LOG_INFO("erase execution context", K(exec_id), K(tablet_id)); + } + } return ret; } @@ -1024,7 +1083,9 @@ int ObTenantDirectLoadMgr::gc_tablet_direct_load() ObLS *ls = nullptr; ObLSHandle ls_handle; ObTabletHandle tablet_handle; - if (OB_ISNULL(ls_svr)) { + if (!mgr_key.is_full_direct_load_) { + // skip + } else if (OB_ISNULL(ls_svr)) { LOG_WARN("invalid mtl ObLSService", K(ret)); } else if (OB_FAIL(ls_svr->get_ls(ls_id, ls_handle, ObLSGetMod::DDL_MOD))) { LOG_WARN("get log stream failed", K(ret), K(ls_id)); @@ -1042,13 +1103,13 @@ int ObTenantDirectLoadMgr::gc_tablet_direct_load() return ret; } -int ObTenantDirectLoadMgr::remove_tablet_direct_load(const ObTabletDirectLoadMgrKey &mgr_key) +int ObTenantDirectLoadMgr::remove_tablet_direct_load(const ObTabletDirectLoadMgrKey &mgr_key, int64_t context_id) { ObBucketHashWLockGuard guard(bucket_lock_, mgr_key.hash()); - return remove_tablet_direct_load_nolock(mgr_key); + return remove_tablet_direct_load_nolock(mgr_key, context_id); } -int ObTenantDirectLoadMgr::remove_tablet_direct_load_nolock(const ObTabletDirectLoadMgrKey &mgr_key) +int ObTenantDirectLoadMgr::remove_tablet_direct_load_nolock(const ObTabletDirectLoadMgrKey &mgr_key, int64_t context_id) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_inited_)) { @@ -1065,6 +1126,8 @@ int ObTenantDirectLoadMgr::remove_tablet_direct_load_nolock(const ObTabletDirect } else if (OB_ISNULL(tablet_direct_load_mgr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected err", K(ret), K(mgr_key)); + } else if (!mgr_key.is_full_direct_load_ && context_id > 0 && context_id != tablet_direct_load_mgr->get_context_id()) { + // context_id not match, ignore } else if (OB_FAIL(tablet_mgr_map_.erase_refactored(mgr_key))) { LOG_WARN("erase from map failed", K(ret)); } else { @@ -1188,13 +1251,59 @@ int ObTabletDirectLoadMgr::update( ObTabletDirectLoadMgr *lob_tablet_mgr, const ObTabletDirectLoadInsertParam &build_param) { - UNUSED(lob_tablet_mgr); int ret = OB_SUCCESS; const int64_t bucket_num = 97L; // 97 const int64_t memory_limit = 1024L * 1024L * 1024L * 10L; // 10GB + ObLSService *ls_service = nullptr; + ObLSHandle ls_handle; if (OB_UNLIKELY(!build_param.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(build_param)); + } else if (OB_ISNULL(ls_service = MTL(ObLSService *))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), K(MTL_ID())); + } else if (OB_FAIL(ls_service->get_ls(build_param.common_param_.ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { + LOG_WARN("failed to get log stream", K(ret), K(build_param)); + } else if (OB_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, + build_param.common_param_.tablet_id_, + tablet_handle_, + ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { + LOG_WARN("get tablet handle failed", K(ret), K(build_param)); + } else if (nullptr != lob_tablet_mgr) { + // has lob + ObTabletDirectLoadInsertParam lob_param; + ObSchemaGetterGuard schema_guard; + ObTabletBindingMdsUserData ddl_data; + const ObTableSchema *table_schema = nullptr; + if (OB_FAIL(lob_param.assign(build_param))) { + LOG_WARN("assign lob parameter failed", K(ret)); + } else if (OB_FAIL(tablet_handle_.get_obj()->ObITabletMdsInterface::get_ddl_data(share::SCN::max_scn(), ddl_data))) { + LOG_WARN("get ddl data failed", K(ret)); + } else if (OB_FALSE_IT(lob_param.common_param_.tablet_id_ = ddl_data.lob_meta_tablet_id_)) { + } else if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard( + MTL_ID(), schema_guard, lob_param.runtime_only_param_.schema_version_))) { + LOG_WARN("get tenant schema failed", K(ret), K(MTL_ID()), K(lob_param)); + } else if (OB_FAIL(schema_guard.get_table_schema(MTL_ID(), + lob_param.runtime_only_param_.table_id_, table_schema))) { + LOG_WARN("get table schema failed", K(ret), K(lob_param)); + } else if (OB_ISNULL(table_schema)) { + ret = OB_TABLE_NOT_EXIST; + LOG_WARN("table not exist", K(ret), K(lob_param)); + } else { + lob_param.runtime_only_param_.table_id_ = table_schema->get_aux_lob_meta_tid(); + } + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(lob_mgr_handle_.set_obj(lob_tablet_mgr))) { + LOG_WARN("set lob direct load mgr failed", K(ret), K(lob_param)); + } else if (OB_FAIL(lob_mgr_handle_.get_obj()->update(nullptr, lob_param))) { + LOG_WARN("init lob failed", K(ret), K(lob_param)); + } else { + LOG_INFO("set lob mgr handle", K(lob_param)); + } + } + + if (OB_FAIL(ret)) { } else if (!build_param.is_replay_ && !sqc_build_ctx_.slice_mgr_map_.created()) { // 1. Create slice_mgr_map if the tablet_direct_load_mgr is created firstly. // 2. Create slice_mgr_map if the node is switched from follower to leader. @@ -2080,7 +2189,8 @@ int ObTabletDirectLoadMgr::prepare_index_builder_if_need(const ObTableSchema &ta } else if (OB_FAIL(index_block_desc.init(table_schema, ls_id_, tablet_id_, is_full_direct_load(direct_load_type_) ? compaction::ObMergeType::MAJOR_MERGE : compaction::ObMergeType::MINOR_MERGE, is_full_direct_load(direct_load_type_) ? table_key_.get_snapshot_version() : 1L, - data_format_version_))) { + data_format_version_, + is_full_direct_load(direct_load_type_) ? SCN::invalid_scn() : table_key_.get_end_scn()))) { LOG_WARN("fail to init data desc", K(ret)); } else { void *builder_buf = nullptr; @@ -2099,7 +2209,8 @@ int ObTabletDirectLoadMgr::prepare_index_builder_if_need(const ObTableSchema &ta } else if (OB_FAIL(sqc_build_ctx_.data_block_desc_.init(table_schema, ls_id_, tablet_id_, is_full_direct_load(direct_load_type_) ? compaction::ObMergeType::MAJOR_MERGE : compaction::ObMergeType::MINOR_MERGE, is_full_direct_load(direct_load_type_) ? table_key_.get_snapshot_version() : 1L, - data_format_version_))) { + data_format_version_, + is_full_direct_load(direct_load_type_) ? SCN::invalid_scn() : table_key_.get_end_scn()))) { LOG_WARN("fail to init data block desc", K(ret)); } else { sqc_build_ctx_.data_block_desc_.get_desc().sstable_index_builder_ = sqc_build_ctx_.index_builder_; // for build the tail index block in macro block @@ -2170,84 +2281,34 @@ int ObTabletFullDirectLoadMgr::update( const ObTabletDirectLoadInsertParam &build_param) { int ret = OB_SUCCESS; - ObLSService *ls_service = nullptr; - ObLSHandle ls_handle; ObStorageSchema *storage_schema = nullptr; ObArenaAllocator arena_allocator("dl_mgr_update", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); ObLatchWGuard guard(lock_, ObLatchIds::TABLET_DIRECT_LOAD_MGR_LOCK); if (OB_UNLIKELY(!build_param.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(ret), K(build_param)); - } else if (OB_ISNULL(ls_service = MTL(ObLSService *))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected err", K(ret), K(MTL_ID())); - } else if (OB_FAIL(ls_service->get_ls(build_param.common_param_.ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { - LOG_WARN("failed to get log stream", K(ret), K(build_param)); - } else if (OB_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, - build_param.common_param_.tablet_id_, - tablet_handle_, - ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { - LOG_WARN("get tablet handle failed", K(ret), K(build_param)); + } else if (OB_FAIL(ObTabletDirectLoadMgr::update(lob_tablet_mgr, build_param))) { + LOG_WARN("init failed", K(ret), K(build_param)); } else if (OB_FAIL(tablet_handle_.get_obj()->load_storage_schema(arena_allocator, storage_schema))) { LOG_WARN("load storage schema failed", K(ret)); - } else if (nullptr != lob_tablet_mgr) { - // has lob - ObTabletDirectLoadInsertParam lob_param; - ObSchemaGetterGuard schema_guard; - ObTabletBindingMdsUserData ddl_data; - const ObTableSchema *table_schema = nullptr; - if (OB_FAIL(lob_param.assign(build_param))) { - LOG_WARN("assign lob parameter failed", K(ret)); - } else if (OB_FAIL(tablet_handle_.get_obj()->ObITabletMdsInterface::get_ddl_data(share::SCN::max_scn(), ddl_data))) { - LOG_WARN("get ddl data failed", K(ret)); - } else if (OB_FALSE_IT(lob_param.common_param_.tablet_id_ = ddl_data.lob_meta_tablet_id_)) { - } else if (build_param.is_replay_) { - // no need to update table id. - } else if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard( - MTL_ID(), schema_guard, lob_param.runtime_only_param_.schema_version_))) { - LOG_WARN("get tenant schema failed", K(ret), K(MTL_ID()), K(lob_param)); - } else if (OB_FAIL(schema_guard.get_table_schema(MTL_ID(), - lob_param.runtime_only_param_.table_id_, table_schema))) { - LOG_WARN("get table schema failed", K(ret), K(lob_param)); - } else if (OB_ISNULL(table_schema)) { - ret = OB_TABLE_NOT_EXIST; - LOG_WARN("table not exist", K(ret), K(lob_param)); - } else { - lob_param.runtime_only_param_.table_id_ = table_schema->get_aux_lob_meta_tid(); - } - - if (OB_FAIL(ret)) { - } else if (OB_FAIL(lob_mgr_handle_.set_obj(lob_tablet_mgr))) { - LOG_WARN("set lob direct load mgr failed", K(ret), K(lob_param)); - } else if (OB_FAIL(lob_mgr_handle_.get_obj()->update(nullptr, lob_param))) { - LOG_WARN("init lob failed", K(ret), K(lob_param)); - } else { - LOG_INFO("set lob mgr handle", K(lob_param)); - } - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(ObTabletDirectLoadMgr::update(nullptr, build_param))) { - LOG_WARN("init failed", K(ret), K(build_param)); - } else { - table_key_.reset(); - table_key_.tablet_id_ = build_param.common_param_.tablet_id_; - bool is_column_group_store = false; - if (OB_FAIL(ObCODDLUtil::need_column_group_store(*storage_schema, is_column_group_store))) { - LOG_WARN("fail to get schema is column group store", K(ret)); - } else if (is_column_group_store) { - table_key_.table_type_ = ObITable::COLUMN_ORIENTED_SSTABLE; - int64_t base_cg_idx = -1; - if (OB_FAIL(ObCODDLUtil::get_base_cg_idx(storage_schema, base_cg_idx))) { - LOG_WARN("get base cg idx failed", K(ret)); - } else { - table_key_.column_group_idx_ = static_cast(base_cg_idx); - } + } else { + table_key_.reset(); + table_key_.tablet_id_ = build_param.common_param_.tablet_id_; + bool is_column_group_store = false; + if (OB_FAIL(ObCODDLUtil::need_column_group_store(*storage_schema, is_column_group_store))) { + LOG_WARN("fail to get schema is column group store", K(ret)); + } else if (is_column_group_store) { + table_key_.table_type_ = ObITable::COLUMN_ORIENTED_SSTABLE; + int64_t base_cg_idx = -1; + if (OB_FAIL(ObCODDLUtil::get_base_cg_idx(storage_schema, base_cg_idx))) { + LOG_WARN("get base cg idx failed", K(ret)); } else { - table_key_.table_type_ = ObITable::MAJOR_SSTABLE; + table_key_.column_group_idx_ = static_cast(base_cg_idx); } - table_key_.version_range_.snapshot_version_ = build_param.common_param_.read_snapshot_; + } else { + table_key_.table_type_ = ObITable::MAJOR_SSTABLE; } + table_key_.version_range_.snapshot_version_ = build_param.common_param_.read_snapshot_; } ObTabletObjLoadHelper::free(arena_allocator, storage_schema); LOG_INFO("init tablet direct load mgr finished", K(ret), K(build_param), KPC(this)); @@ -3143,3 +3204,143 @@ int ObTabletFullDirectLoadMgr::update_major_sstable() ObTabletObjLoadHelper::free(tmp_arena, storage_schema); return ret; } + +/** + * ObTabletIncDirectLoadMgr + */ + +ObTabletIncDirectLoadMgr::ObTabletIncDirectLoadMgr(int64_t context_id) + : ObTabletDirectLoadMgr(), + context_id_(context_id), + start_scn_(share::SCN::min_scn()), + is_closed_(false) +{ +} + +ObTabletIncDirectLoadMgr::~ObTabletIncDirectLoadMgr() +{ +} + +int ObTabletIncDirectLoadMgr::update( + ObTabletDirectLoadMgr *lob_tablet_mgr, + const ObTabletDirectLoadInsertParam &build_param) +{ + int ret = OB_SUCCESS; + ObLatchWGuard guard(lock_, ObLatchIds::TABLET_DIRECT_LOAD_MGR_LOCK); + if (OB_UNLIKELY(!build_param.is_valid() || + nullptr == build_param.runtime_only_param_.tx_desc_ || + !build_param.runtime_only_param_.trans_id_.is_valid() || + build_param.runtime_only_param_.seq_no_ <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arg", K(ret), K(build_param)); + } else if (OB_FAIL(ObTabletDirectLoadMgr::update(lob_tablet_mgr, build_param))) { + LOG_WARN("init failed", K(ret), K(build_param)); + } else { + table_key_.reset(); + table_key_.tablet_id_ = build_param.common_param_.tablet_id_; + table_key_.table_type_ = ObITable::MINI_SSTABLE; + // set scn_range for check valid only + table_key_.scn_range_.start_scn_.convert_for_tx(1); + table_key_.scn_range_.end_scn_.convert_for_tx(build_param.common_param_.read_snapshot_); // for logic version + data_format_version_ = build_param.common_param_.data_format_version_; + sqc_build_ctx_.reset_slice_ctx_on_demand(); + start_scn_.set_min(); + } + LOG_INFO("init tablet inc direct load mgr finished", K(ret), K(build_param), KPC(this)); + return ret; +} + +int ObTabletIncDirectLoadMgr::open( + const int64_t current_execution_id, + share::SCN &start_scn) +{ + int ret = OB_SUCCESS; + ObTabletIncDirectLoadMgr *lob_tablet_mgr = nullptr; + start_scn.reset(); + ObLatchWGuard guard(lock_, ObLatchIds::TABLET_DIRECT_LOAD_MGR_LOCK); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("not init", K(ret)); + } else if (OB_UNLIKELY(!is_valid() || !sqc_build_ctx_.is_valid() || current_execution_id < 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), KPC(this), K(current_execution_id)); + } else if (lob_mgr_handle_.is_valid() + && OB_ISNULL(lob_tablet_mgr = lob_mgr_handle_.get_inc_obj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), KPC(this)); + } + if (OB_SUCC(ret)) { + ObDDLIncRedoLogWriter redo_writer; + if (OB_FAIL(redo_writer.init(ls_id_, tablet_id_))) { + LOG_WARN("init redo writer failed", K(ret), K(ls_id_), K(tablet_id_)); + } else if (OB_FAIL(redo_writer.write_inc_start_log_with_retry( + nullptr != lob_tablet_mgr ? lob_tablet_mgr->get_tablet_id() : ObTabletID(), + sqc_build_ctx_.build_param_.runtime_only_param_.tx_desc_, + start_scn))) { + LOG_WARN("fail write start log", K(ret), K(data_format_version_), K(sqc_build_ctx_)); + } else if (OB_UNLIKELY(!start_scn.is_valid_and_not_min())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), K(start_scn)); + } else if (nullptr != lob_tablet_mgr && OB_FAIL(lob_tablet_mgr->start(current_execution_id, start_scn))) { + LOG_WARN("fail to start lob", KR(ret)); + } else if (OB_FAIL(start(current_execution_id, start_scn))) { + LOG_WARN("fail to start", KR(ret)); + } + } + return ret; +} + +int ObTabletIncDirectLoadMgr::start(const int64_t execution_id, const share::SCN &start_scn) +{ + UNUSED(execution_id); + int ret = OB_SUCCESS; + start_scn_ = start_scn; + return ret; +} + +int ObTabletIncDirectLoadMgr::close(const int64_t current_execution_id, const share::SCN &start_scn) +{ + int ret = OB_SUCCESS; + ObTabletIncDirectLoadMgr *lob_tablet_mgr = nullptr; + ObLatchWGuard guard(lock_, ObLatchIds::TABLET_DIRECT_LOAD_MGR_LOCK); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("not init", K(ret)); + } else if (OB_UNLIKELY(current_execution_id < 0 || !start_scn.is_valid_and_not_min())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid arguments", K(ret), K(current_execution_id), K(start_scn)); + } else if (OB_UNLIKELY(start_scn != start_scn_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected start scn", KR(ret), K(context_id_), K(start_scn_), K(start_scn)); + } else if (OB_UNLIKELY(is_closed_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected close twice", KR(ret), K(context_id_)); + } else if (lob_mgr_handle_.is_valid() + && OB_ISNULL(lob_tablet_mgr = lob_mgr_handle_.get_inc_obj())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), KPC(this)); + } else { + ObDDLIncRedoLogWriter redo_writer; + if (OB_FAIL(redo_writer.init(ls_id_, tablet_id_))) { + LOG_WARN("init redo writer failed", K(ret), K(ls_id_), K(tablet_id_)); + } else if (OB_FAIL(redo_writer.write_inc_commit_log_with_retry( + true /*allow_remote_write*/, + nullptr != lob_tablet_mgr ? lob_tablet_mgr->get_tablet_id() : ObTabletID(), + sqc_build_ctx_.build_param_.runtime_only_param_.tx_desc_))) { + LOG_WARN("fail write start log", K(ret), K(data_format_version_), K(sqc_build_ctx_)); + } else if (nullptr != lob_tablet_mgr && OB_FAIL(lob_tablet_mgr->commit(current_execution_id, start_scn))) { + LOG_WARN("fail to commit lob", KR(ret)); + } else if (OB_FAIL(commit(current_execution_id, start_scn))) { + LOG_WARN("fail to commit", KR(ret)); + } + } + return ret; +} + +int ObTabletIncDirectLoadMgr::commit(const int64_t execution_id, const share::SCN &commit_scn) +{ + UNUSEDx(execution_id, commit_scn); + int ret = OB_SUCCESS; + is_closed_ = true; + return ret; +} diff --git a/src/storage/ddl/ob_direct_insert_sstable_ctx_new.h b/src/storage/ddl/ob_direct_insert_sstable_ctx_new.h index bb2037c5f..0700cafe7 100644 --- a/src/storage/ddl/ob_direct_insert_sstable_ctx_new.h +++ b/src/storage/ddl/ob_direct_insert_sstable_ctx_new.h @@ -191,14 +191,17 @@ public: const int64_t thread_cnt, const int64_t thread_id); int cancel( + const int64_t context_id, const share::ObLSID &ls_id, const common::ObTabletID &tablet_id, const bool is_full_direct_load); int gc_tablet_direct_load(); // remove tablet direct load mgr from hashmap, // for full direct load, it will be called when physical major generates, - // for incremental direct load, it will be called when all KVs dump. - int remove_tablet_direct_load(const ObTabletDirectLoadMgrKey &mgr_key); + // for incremental direct load, it will be called in close_tablet_direct_load + // @param [in] context_id to match ObTabletDirectLoadMgr, avoid an old task remove a new ObTabletDirectLoadMgr + // only take effect when !mgr_key.is_full_direct_load_ and context_id > 0 + int remove_tablet_direct_load(const ObTabletDirectLoadMgrKey &mgr_key, int64_t context_id = 0); ObIAllocator &get_allocator() { return allocator_; } private: struct GetGcCandidateOp final { @@ -233,7 +236,7 @@ private: int get_tablet_exec_context_with_rlock( const ObTabletDirectLoadExecContextId &exec_id, ObTabletDirectLoadExecContext &exec_context); - int remove_tablet_direct_load_nolock(const ObTabletDirectLoadMgrKey &mgr_key); + int remove_tablet_direct_load_nolock(const ObTabletDirectLoadMgrKey &mgr_key, int64_t context_id = 0); // to generate unique slice id for slice writer, putting here is just to // simplify the logic of the tablet_direct_load_mgr. int64_t generate_slice_id(); @@ -353,6 +356,7 @@ public: int64_t get_ref() { return ATOMIC_LOAD(&ref_cnt_); } // some utils. + virtual int64_t get_context_id() const { return 0; } virtual share::SCN get_start_scn() = 0; virtual share::SCN get_commit_scn(const ObTabletMeta &tablet_meta) = 0; inline const ObITable::TableKey &get_table_key() const { return table_key_; } @@ -502,46 +506,35 @@ DISALLOW_COPY_AND_ASSIGN(ObTabletFullDirectLoadMgr); class ObTabletIncDirectLoadMgr final : public ObTabletDirectLoadMgr { public: - ObTabletIncDirectLoadMgr() - : ObTabletDirectLoadMgr() - { } - ~ObTabletIncDirectLoadMgr() {} - virtual int update( - ObTabletDirectLoadMgr *lob_tablet_mgr, - const ObTabletDirectLoadInsertParam &build_param) + ObTabletIncDirectLoadMgr(int64_t context_id); + ~ObTabletIncDirectLoadMgr(); + + // called by creator only + int update(ObTabletDirectLoadMgr *lob_tablet_mgr, + const ObTabletDirectLoadInsertParam &build_param) override final; + int open(const int64_t current_execution_id, share::SCN &start_scn) override final; + int close(const int64_t current_execution_id, const share::SCN &start_scn) override final; + + int64_t get_context_id() const override { return context_id_; } + share::SCN get_start_scn() override { return start_scn_; } + // unused, for full direct load only + share::SCN get_commit_scn(const ObTabletMeta &tablet_meta) override { - return OB_NOT_IMPLEMENT; - } - int open(const int64_t current_execution_id, share::SCN &start_scn) override - { - // write start log to freeze memtable and ddl kv. - return OB_NOT_IMPLEMENT; - } - int close(const int64_t current_execution_id, const share::SCN &start_scn) override - { - return OB_NOT_IMPLEMENT; + UNUSED(tablet_meta); + return share::SCN::invalid_scn(); } - // to freeze in_memory_indexed_sstables and memtables. - int start(ObTablet &tablet, const ObITable::TableKey &table_key, const share::SCN &start_scn, const uint64_t data_format_version, const int64_t execution_id, const share::SCN &checkpoint_scn); - int start_nolock(const ObITable::TableKey &table_key, const share::SCN &start_scn, const uint64_t data_format_version, const int64_t execution_id, const share::SCN &checkpoint_scn); - // return ddl param with end_scn. - // int get_direct_load_merge_param(ObTabletDDLParam &ddl_param) override; - // mini merge, used for compaction. - // int get_direct_load_merge_param(const ObTabletMeta &tablet_meta, ObDDLTableMergeDagParam &merge_param) override; - share::SCN get_start_scn() override { return share::SCN::min_scn(); } - share::SCN get_commit_scn(const ObTabletMeta &tablet_meta) override { return share::SCN::invalid_scn(); } - int freeze_in_memory_indexed_sstable( - const share::SCN &freeze_scn = share::SCN::min_scn()); - -// private: - int wait_memory_index_sstable_freeze(); // check and wait in memory index sstable freeze. private: + int start(const int64_t execution_id, const share::SCN &start_scn); + int commit(const int64_t execution_id, const share::SCN &commit_scn); + +private: + int64_t context_id_; + share::SCN start_scn_; + bool is_closed_; DISALLOW_COPY_AND_ASSIGN(ObTabletIncDirectLoadMgr); }; - - }// namespace storage }// namespace oceanbase diff --git a/src/storage/ddl/ob_direct_load_struct.cpp b/src/storage/ddl/ob_direct_load_struct.cpp index 2ab9cadd7..4cdb3b271 100644 --- a/src/storage/ddl/ob_direct_load_struct.cpp +++ b/src/storage/ddl/ob_direct_load_struct.cpp @@ -35,6 +35,7 @@ using namespace oceanbase::blocksstable; using namespace oceanbase::share; using namespace oceanbase::share::schema; using namespace oceanbase::sql; +using namespace oceanbase::transaction; int ObTabletDirectLoadInsertParam::assign(const ObTabletDirectLoadInsertParam &other_param) { @@ -391,9 +392,10 @@ int ObLobMetaRowIterator::get_next_row(const blocksstable::ObDatumRow *&row) LOG_WARN("transform failed", K(ret), K(lob_meta_write_result_.info_)); } else { tmp_row_.storage_datums_[ObLobMetaUtil::SEQ_ID_COL_ID + 1].set_int(-trans_version_); - tmp_row_.storage_datums_[ObLobMetaUtil::SEQ_ID_COL_ID + 2].set_int(sql_no_); + tmp_row_.storage_datums_[ObLobMetaUtil::SEQ_ID_COL_ID + 2].set_int(-sql_no_); tmp_row_.set_trans_id(trans_id_); tmp_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); + tmp_row_.mvcc_row_flag_.set_uncommitted_row(trans_id_.is_valid()); row = &tmp_row_; } } @@ -401,7 +403,14 @@ int ObLobMetaRowIterator::get_next_row(const blocksstable::ObDatumRow *&row) } ObTabletDDLParam::ObTabletDDLParam() - : direct_load_type_(ObDirectLoadType::DIRECT_LOAD_INVALID), ls_id_(), start_scn_(SCN::min_scn()), commit_scn_(SCN::min_scn()), data_format_version_(0), table_key_(), snapshot_version_(0) + : direct_load_type_(ObDirectLoadType::DIRECT_LOAD_INVALID), + ls_id_(), + start_scn_(SCN::min_scn()), + commit_scn_(SCN::min_scn()), + data_format_version_(0), + table_key_(), + snapshot_version_(0), + trans_id_() { } @@ -631,15 +640,31 @@ int ObMacroBlockSliceStore::init( const uint64_t data_format_version = tablet_direct_load_mgr->get_data_format_version(); const ObDirectLoadType direct_load_type = tablet_direct_load_mgr->get_direct_load_type(); const ObWholeDataStoreDesc &data_desc = tablet_direct_load_mgr->get_sqc_build_ctx().data_block_desc_; - if (OB_FAIL(ddl_redo_writer_.init(ls_id, table_key.tablet_id_))) { - LOG_WARN("init sstable redo writer failed", K(ret), K(ls_id), K(table_key)); - } else if (OB_FAIL(write_ddl_redo_callback_.init(DDL_MB_DATA_TYPE, table_key, ddl_task_id, - start_scn, data_format_version, &ddl_redo_writer_))) { - LOG_WARN("init write ddl redo callback failed", K(ret)); - } else if (OB_FAIL(macro_block_writer_.open(data_desc.get_desc(), data_seq, &write_ddl_redo_callback_))) { - LOG_WARN("open macro bock writer failed", K(ret)); + ObTxDesc *tx_desc = tablet_direct_load_mgr->get_sqc_build_ctx().build_param_.runtime_only_param_.tx_desc_; + const ObTransID &trans_id = tablet_direct_load_mgr->get_sqc_build_ctx().build_param_.runtime_only_param_.trans_id_; + if (is_incremental_direct_load(direct_load_type)) { + if (OB_ISNULL(ddl_redo_callback_ = OB_NEW(ObDDLIncRedoLogWriterCallback, ObMemAttr(MTL_ID(), "DDL_MBSS")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory", K(ret)); + } else if (OB_FAIL(static_cast(ddl_redo_callback_)->init( + ls_id, table_key.tablet_id_, DDL_MB_DATA_TYPE, table_key, ddl_task_id, start_scn, data_format_version, tx_desc, trans_id))) { + LOG_WARN("fail to init inc ddl_redo_callback_", K(ret)); + } } else { - is_inited_ = true; + if (OB_ISNULL(ddl_redo_callback_ = OB_NEW(ObDDLRedoLogWriterCallback, ObMemAttr(MTL_ID(), "DDL_MBSS")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory", K(ret)); + } else if (OB_FAIL(static_cast(ddl_redo_callback_)->init( + ls_id, table_key.tablet_id_, DDL_MB_DATA_TYPE, table_key, ddl_task_id, start_scn, data_format_version, -1/*row_id_offset*/))) { + LOG_WARN("fail to init full ddl_redo_callback_", K(ret)); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(macro_block_writer_.open(data_desc.get_desc(), data_seq, ddl_redo_callback_))) { + LOG_WARN("open macro bock writer failed", K(ret)); + } else { + is_inited_ = true; + } } } return ret; @@ -677,7 +702,8 @@ bool ObTabletDDLParam::is_valid() const && start_scn_.is_valid_and_not_min() && commit_scn_.is_valid() && commit_scn_ != SCN::max_scn() && snapshot_version_ > 0 - && data_format_version_ > 0; + && data_format_version_ > 0 + && (is_incremental_direct_load(direct_load_type_) ? trans_id_.is_valid() : !trans_id_.is_valid()); } ObDirectLoadSliceWriter::ObDirectLoadSliceWriter() @@ -748,40 +774,38 @@ int ObDirectLoadSliceWriter::prepare_slice_store_if_need( LOG_WARN("not init", K(ret)); } else if (nullptr != slice_store_) { // do nothing - } else if (is_full_direct_load(tablet_direct_load_mgr_->get_direct_load_type())) { - if (is_column_store) { - need_column_store_ = true; - ObChunkSliceStore *chunk_slice_store = nullptr; - if (OB_UNLIKELY(!tablet_handle.is_valid())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid tablet handle", K(ret), K(tablet_handle)); - } else if (OB_ISNULL(chunk_slice_store = OB_NEWx(ObChunkSliceStore, &allocator_))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("allocate memory for chunk slice store failed", K(ret)); - } else if (OB_FAIL(chunk_slice_store->init(schema_rowkey_column_num + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(), - tablet_handle, allocator_, tablet_direct_load_mgr_->get_column_info(), dir_id, parallelism))) { - LOG_WARN("init chunk slice store failed", K(ret)); - } else { - slice_store_ = chunk_slice_store; - } - if (OB_FAIL(ret) && nullptr != chunk_slice_store) { - chunk_slice_store->~ObChunkSliceStore(); - allocator_.free(chunk_slice_store); - } + } else if (is_full_direct_load(tablet_direct_load_mgr_->get_direct_load_type()) && is_column_store) { + need_column_store_ = true; + ObChunkSliceStore *chunk_slice_store = nullptr; + if (OB_UNLIKELY(!tablet_handle.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid tablet handle", K(ret), K(tablet_handle)); + } else if (OB_ISNULL(chunk_slice_store = OB_NEWx(ObChunkSliceStore, &allocator_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory for chunk slice store failed", K(ret)); + } else if (OB_FAIL(chunk_slice_store->init(schema_rowkey_column_num + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(), + tablet_handle, allocator_, tablet_direct_load_mgr_->get_column_info(), dir_id, parallelism))) { + LOG_WARN("init chunk slice store failed", K(ret)); } else { - ObMacroBlockSliceStore *macro_block_slice_store = nullptr; - if (OB_ISNULL(macro_block_slice_store = OB_NEWx(ObMacroBlockSliceStore, &allocator_))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("allocate memory for macro block slice store failed", K(ret)); - } else if (OB_FAIL(macro_block_slice_store->init(tablet_direct_load_mgr_, start_seq_, start_scn))) { - LOG_WARN("init macro block slice store failed", K(ret), KPC(tablet_direct_load_mgr_), K(start_seq_)); - } else { - slice_store_ = macro_block_slice_store; - } - if (OB_FAIL(ret) && nullptr != macro_block_slice_store) { - macro_block_slice_store->~ObMacroBlockSliceStore(); - allocator_.free(macro_block_slice_store); - } + slice_store_ = chunk_slice_store; + } + if (OB_FAIL(ret) && nullptr != chunk_slice_store) { + chunk_slice_store->~ObChunkSliceStore(); + allocator_.free(chunk_slice_store); + } + } else { + ObMacroBlockSliceStore *macro_block_slice_store = nullptr; + if (OB_ISNULL(macro_block_slice_store = OB_NEWx(ObMacroBlockSliceStore, &allocator_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory for macro block slice store failed", K(ret)); + } else if (OB_FAIL(macro_block_slice_store->init(tablet_direct_load_mgr_, start_seq_, start_scn))) { + LOG_WARN("init macro block slice store failed", K(ret), KPC(tablet_direct_load_mgr_), K(start_seq_)); + } else { + slice_store_ = macro_block_slice_store; + } + if (OB_FAIL(ret) && nullptr != macro_block_slice_store) { + macro_block_slice_store->~ObMacroBlockSliceStore(); + allocator_.free(macro_block_slice_store); } } return ret; @@ -1296,7 +1320,6 @@ void ObCOSliceWriter::reset() cg_row_.reset(); macro_block_writer_.reset(); flush_callback_.reset(); - ddl_clog_writer_.reset(); index_builder_.reset(); data_desc_.reset(); cg_schema_ = nullptr; @@ -1338,10 +1361,8 @@ int ObCOSliceWriter::init(const ObStorageSchema *storage_schema, const int64_t c } else if (OB_FAIL(index_builder_.init(data_desc_.get_desc(), nullptr/*macro block flush callback*/, ObSSTableIndexBuilder::ENABLE))) { // data_desc is deep copied LOG_WARN("init sstable index builder failed", K(ret), K(ls_id), K(table_key), K(data_desc_)); } else if (FALSE_IT(data_desc_.get_desc().sstable_index_builder_ = &index_builder_)) { // for build the tail index block in macro block - } else if (OB_FAIL(ddl_clog_writer_.init(ls_id, table_key.tablet_id_))) { - LOG_WARN("ddl clog writer init failed", K(ret), K(ls_id), K(table_key)); - } else if (OB_FAIL(flush_callback_.init(DDL_MB_DATA_TYPE, table_key, ddl_task_id, - start_scn, data_format_version, &ddl_clog_writer_, row_id_offset))) { + } else if (OB_FAIL(flush_callback_.init(ls_id, table_key.tablet_id_, DDL_MB_DATA_TYPE, table_key, ddl_task_id, + start_scn, data_format_version, row_id_offset))) { LOG_WARN("fail to init redo log writer callback", KR(ret)); } else if (OB_FAIL(macro_block_writer_.open(data_desc_.get_desc(), start_seq, &flush_callback_))) { LOG_WARN("fail to open macro block writer", K(ret), K(ls_id), K(table_key), K(data_desc_), K(start_seq)); diff --git a/src/storage/ddl/ob_direct_load_struct.h b/src/storage/ddl/ob_direct_load_struct.h index aa95d0e23..4a3669de4 100644 --- a/src/storage/ddl/ob_direct_load_struct.h +++ b/src/storage/ddl/ob_direct_load_struct.h @@ -29,6 +29,8 @@ #include "storage/blocksstable/ob_macro_block_struct.h" #include "storage/blocksstable/ob_imacro_block_flush_callback.h" #include "storage/ddl/ob_ddl_redo_log_writer.h" +#include "storage/ddl/ob_ddl_inc_redo_log_writer.h" +#include "storage/ddl/ob_ddl_inc_clog_callback.h" #include "storage/lob/ob_lob_meta.h" namespace oceanbase @@ -217,11 +219,11 @@ struct ObDirectInsertRuntimeOnlyParam final { public: ObDirectInsertRuntimeOnlyParam() - : exec_ctx_(nullptr), task_id_(0), table_id_(OB_INVALID_ID), schema_version_(0), task_cnt_(0), need_online_opt_stat_gather_(false), trans_id_(), seq_no_(0), parallel_(1) + : exec_ctx_(nullptr), task_id_(0), table_id_(OB_INVALID_ID), schema_version_(0), task_cnt_(0), need_online_opt_stat_gather_(false), tx_desc_(nullptr), trans_id_(), seq_no_(0), parallel_(1) {} ~ObDirectInsertRuntimeOnlyParam() = default; bool is_valid() const { return OB_INVALID_ID != task_id_ && OB_INVALID_ID != table_id_ && schema_version_ > 0 && task_cnt_ >= 0; } - TO_STRING_KV(KP_(exec_ctx), K_(task_id), K_(table_id), K_(schema_version), K_(task_cnt), K_(need_online_opt_stat_gather), K_(trans_id), K_(seq_no), K_(parallel)); + TO_STRING_KV(KP_(exec_ctx), K_(task_id), K_(table_id), K_(schema_version), K_(task_cnt), K_(need_online_opt_stat_gather), KP_(tx_desc), K_(trans_id), K_(seq_no), K_(parallel)); public: sql::ObExecContext *exec_ctx_; int64_t task_id_; @@ -229,6 +231,7 @@ public: int64_t schema_version_; int64_t task_cnt_; bool need_online_opt_stat_gather_; + transaction::ObTxDesc *tx_desc_; // default value is invalid tx_id, // participant tx_id for the incremental direct load, // and invalid tx_id for the full_direct_load. @@ -335,7 +338,14 @@ public: ObTabletDDLParam(); ~ObTabletDDLParam(); bool is_valid() const; - TO_STRING_KV(K_(direct_load_type), K_(ls_id), K_(start_scn), K_(commit_scn), K_(data_format_version), K_(table_key), K_(snapshot_version)); + TO_STRING_KV(K_(direct_load_type), + K_(ls_id), + K_(start_scn), + K_(commit_scn), + K_(data_format_version), + K_(table_key), + K_(snapshot_version), + K_(trans_id)); public: ObDirectLoadType direct_load_type_; share::ObLSID ls_id_; @@ -344,6 +354,7 @@ public: uint64_t data_format_version_; ObITable::TableKey table_key_; int64_t snapshot_version_; // used for full direct load only. + transaction::ObTransID trans_id_; // used for incremental direct load only }; struct ObDDLTableMergeDagParam : public share::ObIDagInitParam @@ -433,8 +444,13 @@ public: class ObMacroBlockSliceStore: public ObTabletSliceStore { public: - ObMacroBlockSliceStore() : is_inited_(false) {} - virtual ~ObMacroBlockSliceStore() {} + ObMacroBlockSliceStore() + : is_inited_(false), ddl_redo_callback_(nullptr) {} + virtual ~ObMacroBlockSliceStore() { + if (ddl_redo_callback_ != nullptr) { + common::ob_delete(ddl_redo_callback_); + } + } int init( ObTabletDirectLoadMgr *tablet_direct_load_mgr, const blocksstable::ObMacroDataSeq &data_seq, @@ -445,8 +461,7 @@ public: TO_STRING_KV(K(is_inited_), K(macro_block_writer_)); private: bool is_inited_; - ObDDLRedoLogWriter ddl_redo_writer_; - ObDDLRedoLogWriterCallback write_ddl_redo_callback_; + blocksstable::ObIMacroBlockFlushCallback *ddl_redo_callback_; blocksstable::ObMacroBlockWriter macro_block_writer_; }; @@ -611,7 +626,6 @@ private: blocksstable::ObWholeDataStoreDesc data_desc_; blocksstable::ObSSTableIndexBuilder index_builder_; blocksstable::ObMacroBlockWriter macro_block_writer_; - storage::ObDDLRedoLogWriter ddl_clog_writer_; storage::ObDDLRedoLogWriterCallback flush_callback_; blocksstable::ObDatumRow cg_row_; }; diff --git a/src/storage/ddl/ob_tablet_ddl_kv.cpp b/src/storage/ddl/ob_tablet_ddl_kv.cpp index 7f48f9e60..b2e8cf2dd 100644 --- a/src/storage/ddl/ob_tablet_ddl_kv.cpp +++ b/src/storage/ddl/ob_tablet_ddl_kv.cpp @@ -76,11 +76,10 @@ int ObBlockMetaTree::init(ObTablet &tablet, } else if (ddl_table_iter.count() > 0 && OB_FAIL(ddl_table_iter.get_boundary_table(false/*is_last*/, first_ddl_sstable))) { LOG_WARN("failed to get boundary table", K(ret)); } else if (OB_FAIL(ObTabletDDLUtil::prepare_index_data_desc(tablet, - table_key.is_column_store_sstable() ? table_key.get_column_group_id() : -1/*negative value means row_store*/, + table_key, table_key.get_snapshot_version(), data_format_version, static_cast(first_ddl_sstable), - table_key.get_end_scn(), storage_schema, data_desc_))) { LOG_WARN("prepare data store desc failed", K(ret), K(table_key), K(data_format_version)); @@ -179,7 +178,7 @@ int ObDDLMemtable::init_sstable_param( sstable_param.ddl_scn_ = ddl_start_scn; sstable_param.root_row_store_type_ = data_desc.get_row_store_type(); // for root block, not used for ddl memtable sstable_param.data_index_tree_height_ = 2; // fixed tree height, because there is only one root block - sstable_param.contain_uncommitted_row_ = false; // ddl build major sstable with committed rows only + sstable_param.contain_uncommitted_row_ = table_key.is_minor_sstable(); sstable_param.compressor_type_ = data_desc.get_compressor_type(); sstable_param.encrypt_id_ = data_desc.get_encrypt_id(); sstable_param.master_key_id_ = data_desc.get_master_key_id(); @@ -866,10 +865,10 @@ int ObDDLMemtable::init_ddl_index_iterator(const blocksstable::ObStorageDatumUti } ObDDLKV::ObDDLKV() - : is_inited_(false), is_closed_(false), ref_cnt_(0), lock_(), arena_allocator_("DDL_CONTAINER", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()), - ls_id_(), tablet_id_(), ddl_start_scn_(SCN::min_scn()), snapshot_version_(0), data_format_version_(0), - is_freezed_(false), last_freezed_scn_(SCN::min_scn()), - min_scn_(SCN::max_scn()), max_scn_(SCN::min_scn()), freeze_scn_(SCN::max_scn()), pending_cnt_(0), + : is_inited_(false), is_closed_(false), is_inc_ddl_kv_(false), is_independent_freezed_(false), lock_(), + arena_allocator_("DDL_CONTAINER", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()), + tablet_id_(), ddl_start_scn_(SCN::min_scn()), ddl_snapshot_version_(0), data_format_version_(0), trans_id_(), + min_scn_(SCN::max_scn()), max_scn_(SCN::min_scn()), pending_cnt_(0), macro_block_count_(0) { @@ -880,13 +879,6 @@ ObDDLKV::~ObDDLKV() reset(); } -void ObDDLKV::inc_ref() -{ - ATOMIC_AAF(&ref_cnt_, 1); - // FLOG_INFO("DDLKV inc_ref", K(ref_cnt_), KP(this), K(tablet_id_)); -} - - int ObDDLKV::init(const ObLSID &ls_id, const ObTabletID &tablet_id, const SCN &ddl_start_scn, @@ -907,13 +899,18 @@ int ObDDLKV::init(const ObLSID &ls_id, || data_format_version <= 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(ls_id), K(tablet_id), K(ddl_start_scn), K(snapshot_version), K(last_freezed_scn), K(data_format_version)); + } else if ((max_end_scn_ != SCN::min_scn() && last_freezed_scn >= max_end_scn_) + || last_freezed_scn >= rec_scn_) { + ret = OB_SCN_OUT_OF_BOUND; + TRANS_LOG(ERROR, "cannot set start ts now", K(ret), K(ls_id), KPC(this)); } else { ls_id_ = ls_id; tablet_id_ = tablet_id; ddl_start_scn_ = ddl_start_scn; - snapshot_version_ = snapshot_version; + ddl_snapshot_version_ = snapshot_version; data_format_version_ = data_format_version; - last_freezed_scn_ = last_freezed_scn; + is_inc_ddl_kv_ = false; + key_.scn_range_.start_scn_ = last_freezed_scn; is_inited_ = true; LOG_INFO("ddl kv init success", K(ret), KP(this), K(*this)); } @@ -925,17 +922,16 @@ void ObDDLKV::reset() FLOG_INFO("ddl kv reset", KP(this), K(*this)); is_inited_ = false; is_closed_ = false; - ls_id_.reset(); + is_inc_ddl_kv_ = false; + is_independent_freezed_ = false; tablet_id_.reset(); ddl_start_scn_ = SCN::min_scn(); - snapshot_version_ = 0; + ddl_snapshot_version_ = 0; data_format_version_ = 0; + trans_id_.reset(); - is_freezed_ = false; - last_freezed_scn_ = SCN::min_scn(); min_scn_ = SCN::max_scn(); max_scn_ = SCN::min_scn(); - freeze_scn_ = SCN::max_scn(); pending_cnt_ = 0; for (int64_t i = 0; i < ddl_memtables_.count(); ++i) { @@ -947,6 +943,8 @@ void ObDDLKV::reset() macro_block_count_ = 0; ddl_memtables_.reset(); arena_allocator_.reset(); + + ObITabletMemtable::reset(); } int ObDDLKV::create_ddl_memtable(ObTablet &tablet, const ObITable::TableKey &table_key, ObDDLMemtable *&ddl_memtable) @@ -1032,7 +1030,7 @@ int ObDDLKV::set_macro_block( } else if (OB_UNLIKELY(!macro_block.is_valid() || data_format_version <= 0 || snapshot_version <= 0)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(macro_block), K(data_format_version), K(snapshot_version)); - } else { + } else if (can_freeze) { const uint64_t tenant_id = MTL_ID(); ObUnitInfoGetter::ObTenantConfig unit; int tmp_ret = OB_SUCCESS; @@ -1048,7 +1046,7 @@ int ObDDLKV::set_macro_block( } } } - if (OB_SUCC(ret) && (get_macro_block_cnt() >= freeze_block_count || get_memory_used() >= MEMORY_LIMIT) && can_freeze) { + if (OB_SUCC(ret) && can_freeze && (get_macro_block_cnt() >= freeze_block_count || get_memory_used() >= MEMORY_LIMIT)) { ObDDLTableMergeDagParam param; param.direct_load_type_ = ObDirectLoadType::DIRECT_LOAD_DDL; param.ls_id_ = ls_id_; @@ -1067,9 +1065,18 @@ int ObDDLKV::set_macro_block( if (OB_SUCC(ret)) { ObDataMacroBlockMeta *data_macro_meta = nullptr; TCWLockGuard guard(lock_); - // For incremental direct load, ddl_start_scn is set to min_scn(). + // For incremental direct load, ddl_start_scn is init to min_scn(). + if (is_inc_ddl_kv_ && ddl_start_scn_.is_min()) { + ddl_start_scn_ = macro_block.ddl_start_scn_; + ddl_snapshot_version_ = snapshot_version; + data_format_version_ = data_format_version; + trans_id_ = macro_block.trans_id_; + } if (macro_block.ddl_start_scn_ != ddl_start_scn_) { - if (macro_block.ddl_start_scn_ > ddl_start_scn_) { + if (is_inc_ddl_kv_) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("macro block in different task cannot insert to same inc ddlkv", K(ret), KPC(this), K(macro_block), K(snapshot_version), K(data_format_version)); + } else if (macro_block.ddl_start_scn_ > ddl_start_scn_) { ret = OB_EAGAIN; LOG_INFO("ddl start scn too large, retry", K(ret), K(ls_id_), K(tablet_id_), K(ddl_start_scn_), K(macro_block)); @@ -1081,9 +1088,9 @@ int ObDDLKV::set_macro_block( } else if (macro_block.scn_ > freeze_scn_) { ret = OB_EAGAIN; LOG_INFO("this ddl kv is freezed, retry other ddl kv", K(ret), K(ls_id_), K(tablet_id_), K(macro_block), K(freeze_scn_)); - } else if (OB_UNLIKELY(snapshot_version != snapshot_version_ || data_format_version != data_format_version_)) { + } else if (OB_UNLIKELY(snapshot_version != ddl_snapshot_version_ || data_format_version != data_format_version_ || macro_block.trans_id_ != trans_id_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected error", K(ret), K(snapshot_version), K(data_format_version), KPC(this)); + LOG_WARN("unexpected error", K(ret), K(macro_block), K(snapshot_version), K(data_format_version), KPC(this)); } else { ObDDLMemtable *ddl_memtable = nullptr; // 1. try find the ddl memtable @@ -1163,19 +1170,35 @@ int ObDDLKV::freeze(const SCN &freeze_scn) LOG_WARN("ddl kv is not init", K(ret)); } else { TCWLockGuard guard(lock_); - if (is_freezed()) { - // do nothing + if (is_inc_ddl_kv()) { + ret = inc_load_freeze_(); } else { - if (freeze_scn.is_valid_and_not_min()) { - freeze_scn_ = freeze_scn; - } else if (max_scn_.is_valid_and_not_min()) { - freeze_scn_ = max_scn_; + ret = full_load_freeze_(freeze_scn); + } + } + return ret; +} + +int ObDDLKV::full_load_freeze_(const SCN &freeze_scn) +{ + int ret = OB_SUCCESS; + if (is_freezed()) { + // do nothing + } else { + SCN final_freeze_scn; + if (freeze_scn.is_valid_and_not_min()) { + final_freeze_scn = freeze_scn; + } else if (max_scn_.is_valid_and_not_min()) { + final_freeze_scn = max_scn_; + } else { + ret = OB_EAGAIN; + LOG_INFO("ddl kv not freezed, try again", K(ret), K(ls_id_), K(tablet_id_), K(get_macro_block_cnt())); + } + if (OB_SUCC(ret)) { + if (OB_FAIL(set_end_scn(final_freeze_scn))) { + LOG_WARN("fail to set end scn", K(ret), K(final_freeze_scn)); } else { - ret = OB_EAGAIN; - LOG_INFO("ddl kv not freezed, try again", K(ret), K(ls_id_), K(tablet_id_), K(get_macro_block_cnt())); - } - if (OB_SUCC(ret)) { - ATOMIC_SET(&is_freezed_, true); + ATOMIC_SET(&is_independent_freezed_, true); LOG_INFO("ddl kv freezed", K(ret), K(ls_id_), K(tablet_id_), K(get_macro_block_cnt())); } } @@ -1183,6 +1206,30 @@ int ObDDLKV::freeze(const SCN &freeze_scn) return ret; } +int ObDDLKV::inc_load_freeze_() +{ + int ret = OB_SUCCESS; + if (is_freezed()) { + ret = OB_ENTRY_EXIST; + } else { + ATOMIC_SET(&is_independent_freezed_, true); + } + return ret; +} + +bool ObDDLKV::is_freezed() +{ + bool is_freezed = false; + if (is_inc_ddl_kv()) { + is_freezed = ATOMIC_LOAD(&is_independent_freezed_) // freezed by direct_load_table_guard + || is_frozen_memtable(); // freezed by ddl_commit or logstream freeze + } else { + // full direct load only freezed by itself + is_freezed = ATOMIC_LOAD(&is_independent_freezed_); + } + return is_freezed; +} + int ObDDLKV::prepare_sstable(const bool need_check/*=true*/) { int ret = OB_SUCCESS; @@ -1200,6 +1247,7 @@ int ObDDLKV::prepare_sstable(const bool need_check/*=true*/) } } if (OB_SUCC(ret)) { + SCN start_scn = get_start_scn(); TCWLockGuard guard(lock_); for (int64_t i = 0; OB_SUCC(ret) && i < ddl_memtables_.count(); ++i) { ObDDLMemtable *ddl_memtable = ddl_memtables_.at(i); @@ -1207,7 +1255,7 @@ int ObDDLKV::prepare_sstable(const bool need_check/*=true*/) ret = OB_INVALID_ERROR; LOG_WARN("ddl memtable is null", K(ret)); } else { - ddl_memtable->set_scn_range(last_freezed_scn_, freeze_scn_); + ddl_memtable->set_scn_range(start_scn, freeze_scn_); } } } @@ -1268,25 +1316,13 @@ int ObDDLKV::wait_pending() const bool pending_finished = SCN::plus(max_decided_scn, 1) >= freeze_scn_ && !is_pending(); if (!pending_finished) { ret = OB_EAGAIN; - LOG_INFO("wait pending not finish", K(ret), K_(ls_id), K_(tablet_id), K_(freeze_scn), K_(last_freezed_scn), K_(min_scn), K_(max_scn), K(max_decided_scn)); + LOG_INFO("wait pending not finish", K(ret), K_(ls_id), K_(tablet_id), K_(freeze_scn), K_(min_scn), K_(max_scn), K(max_decided_scn)); } } } return ret; } -int64_t ObDDLKV::dec_ref() -{ - int64_t tmp_cnt = ATOMIC_SAF(&ref_cnt_, 1 /* just sub 1 */); - if (0 == tmp_cnt) { - MTL(ObTenantMetaMemMgr *)->release_ddl_kv(this); - } else if (tmp_cnt < 0) { - int ret = OB_ERR_SYS; - LOG_ERROR("ref_cnt of ddl kv less than 0", KP(this)); - } - return tmp_cnt; -} - int64_t ObDDLKV::get_memory_used() const { int64_t total_used_memory = 0; @@ -1298,3 +1334,497 @@ int64_t ObDDLKV::get_memory_used() const } return total_used_memory; } + +/**************** Implement ObITabletMemtable Function *****************/ +int ObDDLKV::init(const ObITable::TableKey &table_key, + ObLSHandle &ls_handle, + ObFreezer *freezer, + ObTabletMemtableMgr *memtable_mgr, + const int64_t schema_version, + const uint32_t freeze_clock) +{ + int ret = OB_SUCCESS; + + if (is_inited_) { + TRANS_LOG(WARN, "init twice", K(*this)); + ret = OB_INIT_TWICE; + } else if (!table_key.is_valid() || OB_ISNULL(freezer) || OB_ISNULL(memtable_mgr) || schema_version < 0 || + OB_UNLIKELY(!ls_handle.is_valid())) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, + "invalid param", + K(ret), + K(table_key), + KP(freezer), + KP(memtable_mgr), + K(schema_version), + K(freeze_clock), + K(ls_handle)); + } else if (OB_FAIL(set_memtable_mgr_(memtable_mgr))) { + TRANS_LOG(WARN, "fail to set memtable mgr", K(ret), KP(memtable_mgr)); + } else if (FALSE_IT(set_freeze_clock(freeze_clock))) { + } else if (FALSE_IT(set_max_schema_version(schema_version))) { + } else if (OB_FAIL(set_freezer(freezer))) { + TRANS_LOG(WARN, "fail to set freezer", K(ret), KP(freezer)); + } else if (OB_FAIL(ObITable::init(table_key))) { + TRANS_LOG(WARN, "failed to set_table_key", K(ret), K(table_key)); + } else { + ls_id_ = freezer_->get_ls_id(); + init_timestamp_ = ObClockGenerator::getClock(); + (void)set_freeze_state(TabletMemtableFreezeState::ACTIVE); + is_inc_ddl_kv_ = true; + tablet_id_ = table_key.tablet_id_; + is_inited_ = true; + TRANS_LOG(DEBUG, "inc direct load ddl kv init success", KPC(this)); + } + + // avoid calling destroy() when ret is OB_INIT_TWICE + if (OB_SUCCESS != ret && IS_NOT_INIT) { + reset(); + } + + return ret; +} + +bool ObDDLKV::ready_for_flush() { + if (is_frozen_memtable()) { + return ready_for_flush_(); + } else { + // ddl kv is active memtable + return false; + } +} + +bool ObDDLKV::ready_for_flush_() { + int ret = OB_SUCCESS; + bool ready_for_flush = false; + const ObLSID ls_id = get_ls_id(); + + // STEP 1 : freeze ddl kv if needed + if (ObITabletMemtable::get_end_scn().is_max()) { + if (OB_FAIL(decide_right_boundary())) { + if (OB_EAGAIN == ret) { + // ddl kv is not allowd to flush + } else { + LOG_WARN("decide right boundary for direct load memtable failed", KR(ret), KPC(this)); + } + } + } + + // STEP 2 : compare max_decided_scn with end_scn + SCN max_decided_scn = SCN::min_scn(); + const SCN end_scn = ObITabletMemtable::get_end_scn(); + if (OB_FAIL(ret)) { + } else if (end_scn.is_max()) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("end_scn should not be max scn", K(ret), K(ls_id), KPC(this)); + } else if (OB_FAIL(get_ls_current_right_boundary_(max_decided_scn))) { + LOG_WARN("get max decided scn failed", K(ret), K(ls_id)); + } else if (max_decided_scn >= end_scn) { + set_freeze_state(TabletMemtableFreezeState::READY_FOR_FLUSH); + ready_for_flush = true; + } + + // STEP 3 : print debug info if not ready_for_flush for long time + if (!ready_for_flush && 0 != get_frozen_time()) { + const int64_t WARN_LOG_INTERVAL = 10LL * 1000LL * 1000LL; // 10 seconds + const int64_t cur_time = ObClockGenerator::getClock(); + if (cur_time - get_frozen_time() > WARN_LOG_INTERVAL && cur_time - get_last_print_time() > WARN_LOG_INTERVAL) { + (void)set_last_print_time(cur_time); + STORAGE_LOG(WARN, + "direct load memtable not ready for flush for long time", + K(ls_id), + K(get_frozen_time()), + K(max_decided_scn), + KPC(this)); + } + } + + return ready_for_flush; +} + +int ObDDLKV::decide_right_boundary() +{ + int ret = OB_SUCCESS; + const ObLSID ls_id = get_ls_id(); + ObTabletMemtableMgr *mgr = get_memtable_mgr(); + if (OB_ISNULL(mgr)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tablet memtable mgr of ddl kv is unexpected null", KR(ret), K(ls_id), KPC(this)); + } else if (OB_FAIL(mgr->freeze_direct_load_memtable(this))) { + LOG_WARN("fail to freeze direct load memtable", K(ret)); + } + + return ret; +} + +bool ObDDLKV::rec_scn_is_stable() +{ + int ret = OB_SUCCESS; + ObLSID ls_id = get_ls_id(); + bool rec_scn_is_stable = false; + SCN max_decided_scn; + const SCN rec_scn = ObITabletMemtable::get_rec_scn(); + if (rec_scn.is_max()) { + // ddl kv do not have data yet + rec_scn_is_stable = false; + } else if (OB_FAIL(freezer_->get_max_consequent_callbacked_scn(max_decided_scn))) { + STORAGE_LOG(WARN, "get_max_consequent_callbacked_scn failed", K(ret), K(ls_id)); + } else if (max_decided_scn >= rec_scn) { + rec_scn_is_stable = true; + } + + const int64_t WARN_LOG_INTERVAL = 10LL * 1000LL * 1000LL; // 10 seconds + if (!rec_scn_is_stable && + (get_frozen_time() != 0 && ObClockGenerator::getClock() - get_frozen_time() > WARN_LOG_INTERVAL)) { + STORAGE_LOG(WARN, + "direct load memtable rec_scn not stable for long time", + K(ls_id), + KPC(this), + K(mt_stat_.frozen_time_), + K(max_decided_scn)); + } + return rec_scn_is_stable; +} + +bool ObDDLKV::is_frozen_memtable() +{ + const uint32_t logstream_freeze_clock = OB_NOT_NULL(freezer_) ? freezer_->get_freeze_clock() : 0; + const uint32_t memtable_freeze_clock = get_freeze_clock(); + const bool cannot_freeze = !allow_freeze() || ObITabletMemtable::get_rec_scn().is_max(); + if (cannot_freeze && logstream_freeze_clock > memtable_freeze_clock) { + ATOMIC_STORE(&freeze_clock_, logstream_freeze_clock); + TRANS_LOG(INFO, + "inc freeze_clock because the direct load memtable cannot be freezed", + K(memtable_freeze_clock), + K(logstream_freeze_clock), + KPC(this)); + } + const bool bool_ret = logstream_freeze_clock > get_freeze_clock() || is_tablet_freeze_; + + if (bool_ret && 0 == get_frozen_time()) { + set_frozen_time(ObClockGenerator::getClock()); + } + + return bool_ret; +} + +int ObDDLKV::flush(share::ObLSID ls_id) +{ + int ret = OB_SUCCESS; + + int64_t cur_time = ObTimeUtility::current_time(); + if (get_is_flushed()) { + ret = OB_NO_NEED_UPDATE; + } else { + ObDDLTableMergeDagParam param; + param.ls_id_ = ls_id; + param.tablet_id_ = key_.tablet_id_; + param.direct_load_type_ = DIRECT_LOAD_INCREMENTAL; + param.start_scn_ = ddl_start_scn_; + param.snapshot_version_ = ddl_snapshot_version_; + param.data_format_version_ = data_format_version_; + + if (OB_FAIL(compaction::ObScheduleDagFunc::schedule_ddl_table_merge_dag(param))) { + if (OB_EAGAIN != ret && OB_SIZE_OVERFLOW != ret) { + TRANS_LOG(WARN, "failed to schedule tablet merge dag", K(ret)); + } + } + } + return ret; +} + +void ObDDLKV::print_ready_for_flush() +{ + int ret = OB_SUCCESS; + bool ready_for_flush = false; + const ObLSID ls_id = get_ls_id(); + const common::ObTabletID tablet_id = key_.tablet_id_; + bool frozen_memtable_flag = is_frozen_memtable(); + int64_t write_ref = get_write_ref(); + + // STEP 2 : compare max_decided_scn with end_scn + SCN max_decided_scn = SCN::min_scn();; + const SCN end_scn = ObITabletMemtable::get_end_scn(); + if (OB_FAIL(get_ls_current_right_boundary_(max_decided_scn))) { + LOG_WARN("get max decided scn failed", K(ret), K(ls_id)); + } else if (max_decided_scn >= end_scn) { + ready_for_flush = true; + } + + TRANS_LOG(INFO, "[ObFreezer] print_ready_for_flush", + KP(this), K(ls_id), K(tablet_id), + K(ret), K(ready_for_flush), + K(frozen_memtable_flag), K(write_ref), + K(max_decided_scn), K(end_scn), + K_(trace_id)); +} + +void ObDDLKV::set_allow_freeze(const bool allow_freeze) +{ + int ret = OB_SUCCESS; + if (allow_freeze_ != allow_freeze) { + ATOMIC_STORE(&allow_freeze_, allow_freeze); + } +} + +int ObDDLKV::get_frozen_schema_version(int64_t &schema_version) const +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (ddl_memtables_.count() == 0) { + schema_version = 0; + } else if (OB_UNLIKELY(ddl_memtables_.count() != 1)) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->get_frozen_schema_version(schema_version))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::exist(const ObTableIterParam ¶m, ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, bool &is_exist, bool &has_found) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (ddl_memtables_.count() == 0) { + is_exist = false; + has_found = false; + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->exist(param, context, rowkey, is_exist, has_found))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::exist(ObRowsInfo &rowsInfo, bool &is_exist, bool &has_found) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (ddl_memtables_.count() == 0) { + is_exist = false; + has_found = false; + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->exist(rowsInfo, is_exist, has_found))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::scan(const ObTableIterParam ¶m, ObTableAccessContext &context, + const blocksstable::ObDatumRange &key_range, ObStoreRowIterator *&row_iter) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (OB_UNLIKELY(ddl_memtables_.count() == 0)) { + if (OB_FAIL(get_empty_iter(param, context, &key_range, row_iter))) { + LOG_WARN("fail to get empty iter", K(ret)); + } + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->scan(param, context, key_range, row_iter))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::get(const storage::ObTableIterParam ¶m, storage::ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, ObStoreRowIterator *&row_iter) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (OB_UNLIKELY(ddl_memtables_.count() == 0)) { + if (OB_FAIL(get_empty_iter(param, context, &rowkey, row_iter))) { + LOG_WARN("fail to get empty iter", K(ret)); + } + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->get(param, context, rowkey, row_iter))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::multi_get(const ObTableIterParam ¶m, ObTableAccessContext &context, + const common::ObIArray &rowkeys, ObStoreRowIterator *&row_iter) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (OB_UNLIKELY(ddl_memtables_.count() == 0)) { + if (OB_FAIL(get_empty_iter(param, context, &rowkeys, row_iter))) { + LOG_WARN("fail to get empty iter", K(ret)); + } + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->multi_get(param, context, rowkeys, row_iter))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::multi_scan(const ObTableIterParam ¶m, ObTableAccessContext &context, + const common::ObIArray &ranges, ObStoreRowIterator *&row_iter) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (OB_UNLIKELY(ddl_memtables_.count() == 0)) { + if (OB_FAIL(get_empty_iter(param, context, &ranges, row_iter))) { + LOG_WARN("fail to get empty iter", K(ret)); + } + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->multi_scan(param, context, ranges, row_iter))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::get(const storage::ObTableIterParam ¶m, storage::ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, blocksstable::ObDatumRow &row) +{ + int ret = OB_SUCCESS; + ObStoreRowIterator *row_iter = nullptr; + const ObDatumRow *row_ptr= nullptr; + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (OB_FAIL(get(param, context, rowkey, row_iter))) { + LOG_WARN("fail to get row", K(ret)); + } else if (OB_FAIL(row_iter->get_next_row(row_ptr))) { + LOG_WARN("fail to get row", K(ret)); + } else if (OB_ISNULL(row_ptr) || row_ptr->row_flag_.is_not_exist()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected row", K(ret)); + } else if (OB_FAIL(row.deep_copy(*row_ptr, *context.stmt_allocator_))) { + LOG_WARN("fail to copy datum", K(ret)); + } + if (OB_NOT_NULL(row_iter)) { + row_iter->~ObStoreRowIterator(); + row_iter = nullptr; + } + return ret; +} + +int ObDDLKV::get_empty_iter(const ObTableIterParam ¶m, ObTableAccessContext &context, + const void *ranges, ObStoreRowIterator *&row_iter) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!context.is_valid() || OB_ISNULL(ranges) || !param.is_valid())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("Invalid argument", K(ret), K(context)); + } else { + void *buf = nullptr; + ObStoreRowIterator *empty_row_iter = nullptr; + ALLOCATE_TABLE_STORE_ROW_IETRATOR(context, + ObDDLKVEmptyIterator, + empty_row_iter); + + if (OB_SUCC(ret)) { + if (OB_ISNULL(empty_row_iter)) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "unexpected error, row_scanner is nullptr", K(ret), KP(empty_row_iter)); + } else if (OB_FAIL(empty_row_iter->init(param, context, this, ranges))) { + LOG_WARN("Fail to open row scanner", K(ret), K(param), K(context), KP(ranges), K(*this)); + } + } + + if (OB_FAIL(ret)) { + if (nullptr != empty_row_iter) { + empty_row_iter->~ObStoreRowIterator(); + FREE_TABLE_STORE_ROW_IETRATOR(context, empty_row_iter); + empty_row_iter = nullptr; + } + } else { + row_iter = empty_row_iter; + } + } + return ret; +} + +int ObDDLKV::check_row_locked(const ObTableIterParam ¶m, const blocksstable::ObDatumRowkey &rowkey, + ObTableAccessContext &context, ObStoreRowLockState &lock_state, ObRowState &row_state, bool check_exist) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (ddl_memtables_.count() == 0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support to check lock when memtable count is 0", K(ret)); + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->check_row_locked(param, rowkey, context, lock_state, row_state, check_exist))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} + +int ObDDLKV::check_rows_locked(const bool check_exist, ObTableAccessContext &context, + SCN &max_trans_version, ObRowsInfo &rows_info) +{ + int ret = OB_SUCCESS; + TCRLockGuard guard(lock_); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + } else if (OB_UNLIKELY(!is_inc_ddl_kv())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support get for full direct load", K(ret)); + } else if (ddl_memtables_.count() == 0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support to check lock when memtable count is 0", K(ret)); + } else if (ddl_memtables_.count() != 1) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("inc direct load do not support column store yet", K(ret)); + } else if (OB_FAIL(ddl_memtables_.at(0)->check_rows_locked(check_exist, context, max_trans_version, rows_info))) { + LOG_WARN("fail to get row", K(ret)); + } + return ret; +} diff --git a/src/storage/ddl/ob_tablet_ddl_kv.h b/src/storage/ddl/ob_tablet_ddl_kv.h index e62eb9b8c..d72bc4dd9 100644 --- a/src/storage/ddl/ob_tablet_ddl_kv.h +++ b/src/storage/ddl/ob_tablet_ddl_kv.h @@ -26,6 +26,7 @@ #include "storage/blocksstable/ob_logic_macro_id.h" #include "storage/ddl/ob_ddl_struct.h" #include "storage/blocksstable/ob_sstable.h" +#include "storage/access/ob_store_row_iterator.h" namespace oceanbase { @@ -41,6 +42,24 @@ class ObDataMacroBlockMeta; namespace storage { +class ObDDLKVEmptyIterator : public ObStoreRowIterator +{ +public: + ObDDLKVEmptyIterator() {}; + virtual ~ObDDLKVEmptyIterator() {} + void reset() {} + void reuse() {} + int get_next_row(const blocksstable::ObDatumRow *&store_row) { return OB_ITER_END; } +protected: + int inner_open( + const ObTableIterParam &iter_param, + ObTableAccessContext &access_ctx, + ObITable *table, + const void *query_range) { return OB_SUCCESS; } + virtual int inner_get_next_row(const blocksstable::ObDatumRow *&store_row) { return OB_ITER_END; } + +}; + class ObBlockMetaTreeValue final { public: @@ -198,18 +217,92 @@ private: ObBlockMetaTree block_meta_tree_; }; -class ObDDLKV +class ObDDLKV : public ObITabletMemtable { public: ObDDLKV(); ~ObDDLKV(); +// full direct load. int init(const share::ObLSID &ls_id, const common::ObTabletID &tablet_id, const share::SCN &ddl_start_scn, const int64_t snapshot_version, const share::SCN &last_freezed_scn, const uint64_t data_format_version); + +public : // derived from ObITabletMemtable + virtual int init(const ObITable::TableKey &table_key, + ObLSHandle &ls_handle, + ObFreezer *freezer, + ObTabletMemtableMgr *memtable_mgr, + const int64_t schema_version, + const uint32_t freeze_clock) override; + virtual void print_ready_for_flush() override; + virtual bool is_inited() const override { return is_inited_; } + virtual bool is_frozen_memtable() override; + +public: // derived from ObSSTable + virtual int exist( + const ObTableIterParam ¶m, + ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, + bool &is_exist, + bool &has_found); + + virtual int exist( + ObRowsInfo &rowsInfo, + bool &is_exist, + bool &has_found); + + virtual int scan( + const ObTableIterParam ¶m, + ObTableAccessContext &context, + const blocksstable::ObDatumRange &key_range, + ObStoreRowIterator *&row_iter) override; + virtual int get( + const storage::ObTableIterParam ¶m, + storage::ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, + ObStoreRowIterator *&row_iter) override; + + virtual int get(const storage::ObTableIterParam ¶m, + storage::ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, + blocksstable::ObDatumRow &row) override; + virtual int multi_get( + const ObTableIterParam ¶m, + ObTableAccessContext &context, + const common::ObIArray &rowkeys, + ObStoreRowIterator *&row_iter) override; + + virtual int multi_scan( + const ObTableIterParam ¶m, + ObTableAccessContext &context, + const common::ObIArray &ranges, + ObStoreRowIterator *&row_iter) override; + virtual int get_frozen_schema_version(int64_t &schema_version) const; + int check_row_locked( + const ObTableIterParam ¶m, + const blocksstable::ObDatumRowkey &rowkey, + ObTableAccessContext &context, + ObStoreRowLockState &lock_state, + ObRowState &row_state, + bool check_exist = false); + int check_rows_locked( + const bool check_exist, + storage::ObTableAccessContext &context, + share::SCN &max_trans_version, + ObRowsInfo &rows_info); + +public: // derived from ObFreezeCheckpoint + virtual int flush(share::ObLSID ls_id) override; + virtual bool ready_for_flush() override; + virtual bool rec_scn_is_stable() override; + virtual void set_allow_freeze(const bool allow_freeze) override; + +public: void reset(); + void set_freeze_need_retry() { ATOMIC_STORE(&is_independent_freezed_, false); } int set_macro_block( ObTablet &tablet, const ObDDLMacroBlock ¯o_block, @@ -217,55 +310,75 @@ public: const uint64_t data_format_version, const bool can_freeze); - int freeze(const share::SCN &freeze_scn); - bool is_freezed() const { return ATOMIC_LOAD(&is_freezed_); } + int freeze(const share::SCN &freeze_scn = share::SCN::min_scn()); + bool is_freezed(); int close(); int prepare_sstable(const bool need_check = true); + int decide_right_boundary(); bool is_closed() const { return is_closed_; } share::SCN get_min_scn() const { return min_scn_; } share::SCN get_freeze_scn() const { return freeze_scn_; } share::SCN get_ddl_start_scn() const { return ddl_start_scn_; } - share::SCN get_start_scn() const { return last_freezed_scn_; } - share::SCN get_end_scn() const { return freeze_scn_; } int64_t get_macro_block_cnt() const { return macro_block_count_; } int create_ddl_memtable(ObTablet &tablet, const ObITable::TableKey &table_key, ObDDLMemtable *&ddl_memtable); int get_ddl_memtable(const int64_t cg_idx, ObDDLMemtable *&ddl_memtable); ObIArray &get_ddl_memtables() { return ddl_memtables_; } void inc_pending_cnt(); // used by ddl kv pending guard void dec_pending_cnt(); - void inc_ref(); - int64_t dec_ref(); - int64_t get_ref() { return ATOMIC_LOAD(&ref_cnt_); } - const common::ObTabletID &get_tablet_id() const { return tablet_id_; } - int64_t get_snapshot_version() const { return snapshot_version_; } + // const common::ObTabletID &get_tablet_id() const { return tablet_id_; } + int64_t get_snapshot_version() const { return ddl_snapshot_version_; } + uint64_t get_data_format_version() const { return data_format_version_; } + const transaction::ObTransID &get_trans_id() const { return trans_id_; } int64_t get_memory_used() const; - TO_STRING_KV(K_(is_inited), K_(is_closed), K_(ref_cnt), K_(ls_id), K_(tablet_id), - K_(ddl_start_scn), K_(snapshot_version), K_(data_format_version), - K_(is_freezed), K_(last_freezed_scn), K_(min_scn), K_(max_scn), K_(freeze_scn), K_(pending_cnt), - K_(macro_block_count), K_(ddl_memtables)); + OB_INLINE bool is_inc_ddl_kv() const { return is_inc_ddl_kv_; } + virtual int set_frozen() override { ATOMIC_SET(&is_independent_freezed_, true);; return OB_SUCCESS; } + + INHERIT_TO_STRING_KV("ObITabletMemtable", + ObITabletMemtable, + K_(is_inited), + K_(is_closed), + K_(is_inc_ddl_kv), + K_(is_independent_freezed), + K_(ls_id), + K_(tablet_id), + K_(ddl_start_scn), + K_(snapshot_version), + K_(data_format_version), + K_(trans_id), + K_(min_scn), + K_(max_scn), + K_(freeze_scn), + K_(pending_cnt), + K_(macro_block_count), + K_(ddl_memtables)); + private: bool is_pending() const { return ATOMIC_LOAD(&pending_cnt_) > 0; } + bool ready_for_flush_(); int wait_pending(); + int full_load_freeze_(const share::SCN &freeze_scn); + int inc_load_freeze_(); + + int get_empty_iter(const ObTableIterParam ¶m, ObTableAccessContext &context, + const void *anges, ObStoreRowIterator *&row_iter); private: static const int64_t TOTAL_LIMIT = 10 * 1024 * 1024 * 1024L; static const int64_t HOLD_LIMIT = 10 * 1024 * 1024 * 1024L; bool is_inited_; bool is_closed_; - int64_t ref_cnt_; + bool is_inc_ddl_kv_; + bool is_independent_freezed_; common::TCRWLock lock_; // lock for block_meta_tree_ and freeze_log_ts_ common::ObArenaAllocator arena_allocator_; - share::ObLSID ls_id_; common::ObTabletID tablet_id_; share::SCN ddl_start_scn_; // the log ts of ddl start log - int64_t snapshot_version_; // the snapshot version for major sstable which is completed by ddl + int64_t ddl_snapshot_version_; // the snapshot version for major sstable which is completed by ddl uint64_t data_format_version_; + transaction::ObTransID trans_id_; // for incremental direct load only // freeze related - bool is_freezed_; - share::SCN last_freezed_scn_; // the freezed log ts of last ddl kv. the log ts range of this ddl kv is (last_freezed_log_ts_, freeze_log_ts_] share::SCN min_scn_; // the min log ts of macro blocks share::SCN max_scn_; // the max log ts of macro blocks - share::SCN freeze_scn_; // ddl kv refuse data larger than freeze log ts, freeze_log_ts >= max_log_ts int64_t pending_cnt_; // the amount of kvs that are replaying int64_t macro_block_count_; diff --git a/src/storage/direct_load/ob_direct_load_fast_heap_table.cpp b/src/storage/direct_load/ob_direct_load_fast_heap_table.cpp index 3be315ca7..6dd8ef269 100644 --- a/src/storage/direct_load/ob_direct_load_fast_heap_table.cpp +++ b/src/storage/direct_load/ob_direct_load_fast_heap_table.cpp @@ -12,7 +12,6 @@ #define USING_LOG_PREFIX STORAGE #include "storage/direct_load/ob_direct_load_fast_heap_table.h" -#include "share/rc/ob_tenant_base.h" namespace oceanbase { @@ -25,7 +24,7 @@ using namespace common; */ ObDirectLoadFastHeapTableCreateParam::ObDirectLoadFastHeapTableCreateParam() - : row_count_(0) , column_stat_array_(nullptr) + : row_count_(0) { } @@ -35,7 +34,7 @@ ObDirectLoadFastHeapTableCreateParam::~ObDirectLoadFastHeapTableCreateParam() bool ObDirectLoadFastHeapTableCreateParam::is_valid() const { - return tablet_id_.is_valid() && row_count_ >= 0 && nullptr != column_stat_array_ ; + return tablet_id_.is_valid() && row_count_ >= 0; } /** @@ -43,47 +42,14 @@ bool ObDirectLoadFastHeapTableCreateParam::is_valid() const */ ObDirectLoadFastHeapTable::ObDirectLoadFastHeapTable() - : allocator_("TLD_FastHTable"), is_inited_(false) + : is_inited_(false) { - allocator_.set_tenant_id(MTL_ID()); - column_stat_array_.set_tenant_id(MTL_ID()); } ObDirectLoadFastHeapTable::~ObDirectLoadFastHeapTable() { - for (int64_t i = 0; i < column_stat_array_.count(); ++i) { - ObOptOSGColumnStat *col_stat = column_stat_array_.at(i); - col_stat->~ObOptOSGColumnStat(); - col_stat = nullptr; - } } -int ObDirectLoadFastHeapTable::copy_col_stat(const ObDirectLoadFastHeapTableCreateParam ¶m) -{ - int ret = OB_SUCCESS; - for (int64_t i = 0; OB_SUCC(ret)&& i < param.column_stat_array_->count(); ++i) { - ObOptOSGColumnStat *col_stat = param.column_stat_array_->at(i); - ObOptOSGColumnStat *copied_col_stat = NULL; - if (OB_ISNULL(col_stat)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null"); - } else if (OB_ISNULL(copied_col_stat = ObOptOSGColumnStat::create_new_osg_col_stat(allocator_))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory"); - } else if (OB_FAIL(copied_col_stat->deep_copy(*col_stat))) { - LOG_WARN("fail to copy colstat", KR(ret)); - } else if (OB_FAIL(column_stat_array_.push_back(copied_col_stat))) { - LOG_WARN("fail to add table", KR(ret)); - } - if (OB_FAIL(ret) && OB_NOT_NULL(copied_col_stat)) { - copied_col_stat->~ObOptOSGColumnStat(); - copied_col_stat = nullptr; - } - } - return ret; -} - - int ObDirectLoadFastHeapTable::init(const ObDirectLoadFastHeapTableCreateParam ¶m) { int ret = OB_SUCCESS; @@ -96,11 +62,7 @@ int ObDirectLoadFastHeapTable::init(const ObDirectLoadFastHeapTableCreateParam & } else { meta_.tablet_id_ = param.tablet_id_; meta_.row_count_ = param.row_count_; - if (OB_FAIL(copy_col_stat(param))){ - LOG_WARN("fail to inner init", KR(ret), K(param)); - } else { - is_inited_ = true; - } + is_inited_ = true; } return ret; } diff --git a/src/storage/direct_load/ob_direct_load_fast_heap_table.h b/src/storage/direct_load/ob_direct_load_fast_heap_table.h index a3a5b88d7..65772683f 100644 --- a/src/storage/direct_load/ob_direct_load_fast_heap_table.h +++ b/src/storage/direct_load/ob_direct_load_fast_heap_table.h @@ -13,8 +13,6 @@ #include "common/ob_tablet_id.h" #include "storage/direct_load/ob_direct_load_i_table.h" -#include "share/stat/ob_opt_column_stat.h" -#include "share/stat/ob_opt_osg_column_stat.h" namespace oceanbase { @@ -31,7 +29,6 @@ public: public: common::ObTabletID tablet_id_; int64_t row_count_; - common::ObArray *column_stat_array_; }; struct ObDirectLoadFastHeapTableMeta @@ -47,22 +44,14 @@ public: ObDirectLoadFastHeapTable(); virtual ~ObDirectLoadFastHeapTable(); int init(const ObDirectLoadFastHeapTableCreateParam ¶m); - const common::ObIArray &get_column_stat_array() const - { - return column_stat_array_; - } const common::ObTabletID &get_tablet_id() const override { return meta_.tablet_id_; } int64_t get_row_count() const override { return meta_.row_count_; } bool is_valid() const override { return is_inited_; } void release_data() override { /*do nothing*/ } const ObDirectLoadFastHeapTableMeta &get_meta() const { return meta_; } TO_STRING_KV(K_(meta)); -private: - int copy_col_stat(const ObDirectLoadFastHeapTableCreateParam ¶m); private: ObDirectLoadFastHeapTableMeta meta_; - common::ObArenaAllocator allocator_; - common::ObArray column_stat_array_; bool is_inited_; DISABLE_COPY_ASSIGN(ObDirectLoadFastHeapTable); }; diff --git a/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.cpp b/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.cpp index e915109ef..7c4d27eed 100644 --- a/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.cpp +++ b/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.cpp @@ -12,8 +12,6 @@ #define USING_LOG_PREFIX STORAGE #include "storage/direct_load/ob_direct_load_fast_heap_table_builder.h" -#include "share/stat/ob_opt_column_stat.h" -#include "share/stat/ob_stat_define.h" #include "share/table/ob_table_load_define.h" #include "storage/direct_load/ob_direct_load_dml_row_handler.h" #include "storage/direct_load/ob_direct_load_fast_heap_table.h" @@ -26,101 +24,76 @@ namespace storage using namespace common; using namespace blocksstable; using namespace share; +using namespace table; /** * ObDirectLoadFastHeapTableBuildParam */ ObDirectLoadFastHeapTableBuildParam::ObDirectLoadFastHeapTableBuildParam() - : snapshot_version_(0), - lob_column_cnt_(0), - datum_utils_(nullptr), - col_descs_(nullptr), - cmp_funcs_(nullptr), - insert_table_ctx_(nullptr), - dml_row_handler_(nullptr), - online_opt_stat_gather_(false), - px_mode_(false) + : insert_table_ctx_(nullptr), dml_row_handler_(nullptr) { } -ObDirectLoadFastHeapTableBuildParam::~ObDirectLoadFastHeapTableBuildParam() -{ -} +ObDirectLoadFastHeapTableBuildParam::~ObDirectLoadFastHeapTableBuildParam() {} bool ObDirectLoadFastHeapTableBuildParam::is_valid() const { - return tablet_id_.is_valid() && snapshot_version_ > 0 && table_data_desc_.is_valid() && - nullptr != col_descs_ && nullptr != cmp_funcs_ && - nullptr != insert_table_ctx_ && nullptr != dml_row_handler_ && nullptr != datum_utils_; + return tablet_id_.is_valid() && table_data_desc_.is_valid() && nullptr != insert_table_ctx_ && + nullptr != dml_row_handler_; } /** * RowIterator */ -ObDirectLoadFastHeapTableBuilder::RowIterator::RowIterator() - :iter_end_(false), is_inited_(false) -{} +ObDirectLoadFastHeapTableBuilder::RowIterator::RowIterator() : datum_row_(nullptr) {} -ObDirectLoadFastHeapTableBuilder::RowIterator::~RowIterator() -{ -} +ObDirectLoadFastHeapTableBuilder::RowIterator::~RowIterator() {} -void ObDirectLoadFastHeapTableBuilder::RowIterator::reset() -{ - datum_row_ = nullptr; - iter_end_ = false; - is_inited_ = false; -} - -void ObDirectLoadFastHeapTableBuilder::RowIterator::reuse() -{ - iter_end_ = false; -} - - -int ObDirectLoadFastHeapTableBuilder::RowIterator::init(const ObDirectLoadFastHeapTableBuildParam ¶m, ObDatumRow &row, - ObIArray &column_stat_array, ObDirectLoadLobBuilder &lob_builder) +int ObDirectLoadFastHeapTableBuilder::RowIterator::init( + ObDirectLoadInsertTabletContext *insert_tablet_ctx, + ObTableLoadSqlStatistics *sql_statistics, + ObDirectLoadLobBuilder &lob_builder) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("ObDirectLoadFastHeapTableBuilder init twice", KR(ret), KP(this)); + } else if (OB_FAIL(inner_init(insert_tablet_ctx, sql_statistics, lob_builder))) { + LOG_WARN("fail to inner init", KR(ret)); } else { - // init row iterator - ObDirectLoadInsertTableRowIteratorParam row_iterator_param; - row_iterator_param.table_data_desc_ = param.table_data_desc_; - row_iterator_param.datum_utils_ = param.datum_utils_; - row_iterator_param.col_descs_ = param.col_descs_; - row_iterator_param.lob_column_cnt_ = param.lob_column_cnt_; - row_iterator_param.cmp_funcs_ = param.cmp_funcs_; - row_iterator_param.column_stat_array_ = &column_stat_array; - row_iterator_param.lob_builder_ = &lob_builder; - row_iterator_param.is_heap_table_ = true; - row_iterator_param.online_opt_stat_gather_ = param.online_opt_stat_gather_; - row_iterator_param.px_mode_ = param.px_mode_; - if (OB_FAIL(inner_init(row_iterator_param))) { - LOG_WARN("fail to inner init", KR(ret)); - } else { - datum_row_ = &row; - is_inited_ = true; - } + is_inited_ = true; } return ret; } -int ObDirectLoadFastHeapTableBuilder::RowIterator::inner_get_next_row(blocksstable::ObDatumRow *&row) +int ObDirectLoadFastHeapTableBuilder::RowIterator::set_row(ObDatumRow &row) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("RowIterator not init", KR(ret), KP(this)); - } else if (iter_end_) { + } else if (OB_UNLIKELY(nullptr != datum_row_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected set row twice", KR(ret)); + } else { + datum_row_ = &row; + } + return ret; +} + +int ObDirectLoadFastHeapTableBuilder::RowIterator::inner_get_next_row(ObDatumRow *&row) +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("RowIterator not init", KR(ret), KP(this)); + } else if (nullptr == datum_row_) { ret = OB_ITER_END; } else { row = datum_row_; - iter_end_ = true; + datum_row_ = nullptr; } return ret; } @@ -130,61 +103,18 @@ int ObDirectLoadFastHeapTableBuilder::RowIterator::inner_get_next_row(blocksstab */ ObDirectLoadFastHeapTableBuilder::ObDirectLoadFastHeapTableBuilder() - : allocator_("TLD_FastHTable"), - insert_tablet_ctx_(nullptr), + : insert_tablet_ctx_(nullptr), + sql_statistics_(nullptr), current_slice_id_(0), row_count_(0), + has_lob_(false), is_closed_(false), is_inited_(false) { - allocator_.set_tenant_id(MTL_ID()); - column_stat_array_.set_tenant_id(MTL_ID()); } ObDirectLoadFastHeapTableBuilder::~ObDirectLoadFastHeapTableBuilder() { - int ret = OB_SUCCESS; - for (int64_t i = 0; i < column_stat_array_.count(); ++i) { - ObOptOSGColumnStat *col_stat = column_stat_array_.at(i); - col_stat->~ObOptOSGColumnStat(); - allocator_.free(col_stat); - col_stat = nullptr; - } -} - -int ObDirectLoadFastHeapTableBuilder::init_sql_statistics() -{ - int ret = OB_SUCCESS; - for (int64_t i = 0; OB_SUCC(ret) && i < param_.table_data_desc_.column_count_; ++i) { - ObOptOSGColumnStat *new_osg_col_stat = ObOptOSGColumnStat::create_new_osg_col_stat(allocator_); - if (OB_ISNULL(new_osg_col_stat)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate col stat"); - } else if (OB_FAIL(column_stat_array_.push_back(new_osg_col_stat))) { - LOG_WARN("fail to push back", KR(ret)); - } - if (OB_FAIL(ret)) { - if (new_osg_col_stat != nullptr) { - new_osg_col_stat->~ObOptOSGColumnStat(); - allocator_.free(new_osg_col_stat); - new_osg_col_stat = nullptr; - } - } - } - return ret; -} - -int ObDirectLoadFastHeapTableBuilder::init_lob_builder() -{ - int ret = OB_SUCCESS; - ObDirectLoadLobBuildParam param; - param.tablet_id_ = param_.tablet_id_; - param.insert_table_ctx_ = param_.insert_table_ctx_; - param.lob_column_cnt_ = param_.lob_column_cnt_; - if (OB_FAIL(lob_builder_.init(param))) { - LOG_WARN("fail to init lob builder", KR(ret)); - } - return ret; } int ObDirectLoadFastHeapTableBuilder::init(const ObDirectLoadFastHeapTableBuildParam ¶m) @@ -196,29 +126,25 @@ int ObDirectLoadFastHeapTableBuilder::init(const ObDirectLoadFastHeapTableBuildP } else if (OB_UNLIKELY(!param.is_valid())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", KR(ret), K(param)); + } else if (OB_FAIL( + param.insert_table_ctx_->get_tablet_context(param.tablet_id_, insert_tablet_ctx_))) { + LOG_WARN("fail to get tablet context", KR(ret)); } else { - bool has_lob_storage = param.lob_column_cnt_ > 0? true :false; param_ = param; - if (param.online_opt_stat_gather_ && OB_FAIL(init_sql_statistics())) { - LOG_WARN("fail to inner init sql statistics", KR(ret)); - } else if (OB_FAIL(param_.insert_table_ctx_->get_tablet_context( - param_.tablet_id_, insert_tablet_ctx_))) { - LOG_WARN("fail to get tablet context", KR(ret)); - } else if (has_lob_storage && OB_FAIL(init_lob_builder())) { + const bool online_opt_stat_gather = insert_tablet_ctx_->get_online_opt_stat_gather(); + has_lob_ = insert_tablet_ctx_->has_lob_storage(); + if (online_opt_stat_gather && + OB_FAIL(param.insert_table_ctx_->get_sql_statistics(sql_statistics_))) { + LOG_WARN("fail to get sql statistics", KR(ret)); + } else if (has_lob_ && OB_FAIL(lob_builder_.init(insert_tablet_ctx_))) { LOG_WARN("fail to inner init sql statistics", KR(ret)); } else if (OB_FAIL(init_sstable_slice_ctx())) { LOG_WARN("fail to init sstable slice ctx", KR(ret)); - } else if (OB_FAIL(datum_row_.init(param.table_data_desc_.column_count_ + - HIDDEN_ROWKEY_COLUMN_NUM + - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) { + } else if (OB_FAIL(insert_tablet_ctx_->init_datum_row(datum_row_))) { LOG_WARN("fail to init datum row", KR(ret)); - } else if (OB_FAIL(row_iter_.init(param_, datum_row_, column_stat_array_ ,lob_builder_))) { + } else if (OB_FAIL(row_iter_.init(insert_tablet_ctx_, sql_statistics_, lob_builder_))) { LOG_WARN("fail to init row iter", KR(ret)); } else { - datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); - datum_row_.mvcc_row_flag_.set_last_multi_version_row(true); - datum_row_.storage_datums_[HIDDEN_ROWKEY_COLUMN_NUM].set_int(-param_.snapshot_version_); // fill trans_version - datum_row_.storage_datums_[HIDDEN_ROWKEY_COLUMN_NUM + 1].set_int(0); // fill sql_no is_inited_ = true; } } @@ -230,9 +156,8 @@ int ObDirectLoadFastHeapTableBuilder::init_sstable_slice_ctx() int ret = OB_SUCCESS; if (OB_FAIL(insert_tablet_ctx_->get_write_ctx(write_ctx_))) { LOG_WARN("fail to get write ctx", KR(ret)); - } else if (OB_FAIL(insert_tablet_ctx_->open_sstable_slice( - write_ctx_.start_seq_, - current_slice_id_))) { + } else if (OB_FAIL( + insert_tablet_ctx_->open_sstable_slice(write_ctx_.start_seq_, current_slice_id_))) { LOG_WARN("fail to open sstable slice", KR(ret)); } return ret; @@ -269,7 +194,6 @@ int ObDirectLoadFastHeapTableBuilder::append_row(const ObTabletID &tablet_id, } else { uint64_t pk_seq = OB_INVALID_ID; int64_t affected_rows = 0; - row_iter_.reuse(); if (OB_FAIL(write_ctx_.pk_interval_.next_value(pk_seq))) { if (OB_UNLIKELY(OB_EAGAIN != ret)) { LOG_WARN("fail to get next pk seq", KR(ret)); @@ -286,7 +210,10 @@ int ObDirectLoadFastHeapTableBuilder::append_row(const ObTabletID &tablet_id, i < datum_row.count_; ++i, ++j) { datum_row_.storage_datums_[j] = datum_row.storage_datums_[i]; } - if (OB_FAIL(insert_tablet_ctx_->fill_sstable_slice(current_slice_id_, row_iter_, affected_rows))) { + if (OB_FAIL(row_iter_.set_row(datum_row_))) { + LOG_WARN("fail to set row", KR(ret)); + } else if (OB_FAIL(insert_tablet_ctx_->fill_sstable_slice(current_slice_id_, row_iter_, + affected_rows))) { LOG_WARN("fail to fill sstable slice", KR(ret)); } else { ++row_count_; @@ -311,14 +238,14 @@ int ObDirectLoadFastHeapTableBuilder::close() ret = OB_ERR_UNEXPECTED; LOG_WARN("fast heap table builder is closed", KR(ret)); } else { - const bool has_lob_storage = param_.lob_column_cnt_ > 0; - if (has_lob_storage && OB_FAIL(lob_builder_.close())) { + if (has_lob_ && OB_FAIL(lob_builder_.close())) { LOG_WARN("fail to close lob_builder", KR(ret)); } else if (OB_FAIL(insert_tablet_ctx_->close_sstable_slice(current_slice_id_))) { LOG_WARN("fail to close sstable slice builder", KR(ret)); } else { current_slice_id_ = 0; is_closed_ = true; + insert_tablet_ctx_->inc_row_count(row_count_); } } return ret; @@ -338,7 +265,6 @@ int ObDirectLoadFastHeapTableBuilder::get_tables( ObDirectLoadFastHeapTableCreateParam create_param; create_param.tablet_id_ = param_.tablet_id_; create_param.row_count_ = row_count_; - create_param.column_stat_array_ = &column_stat_array_; ObDirectLoadFastHeapTable *fast_heap_table = nullptr; if (OB_ISNULL(fast_heap_table = OB_NEWx(ObDirectLoadFastHeapTable, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; diff --git a/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.h b/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.h index 29fe2c012..7a6e143e0 100644 --- a/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.h +++ b/src/storage/direct_load/ob_direct_load_fast_heap_table_builder.h @@ -13,18 +13,17 @@ #include "common/ob_tablet_id.h" #include "storage/direct_load/ob_direct_load_i_table.h" -#include "storage/direct_load/ob_direct_load_table_data_desc.h" +#include "storage/direct_load/ob_direct_load_insert_table_ctx.h" #include "storage/direct_load/ob_direct_load_insert_table_row_iterator.h" #include "storage/direct_load/ob_direct_load_lob_builder.h" -#include "sql/engine/expr/ob_expr_sys_op_opnsize.h" -#include "storage/direct_load/ob_direct_load_insert_table_ctx.h" +#include "storage/direct_load/ob_direct_load_table_data_desc.h" namespace oceanbase { -namespace common +namespace table { -class ObOptOSGColumnStat; -} // namespace common +class ObTableLoadSqlStatistics; +} // namespace table namespace storage { class ObDirectLoadInsertTableContext; @@ -35,21 +34,15 @@ public: ObDirectLoadFastHeapTableBuildParam(); ~ObDirectLoadFastHeapTableBuildParam(); bool is_valid() const; - TO_STRING_KV(K_(tablet_id), K_(snapshot_version), K_(table_data_desc), KP_(datum_utils), - KP_(col_descs), KP_(lob_column_cnt), KP_(cmp_funcs), KP_(dml_row_handler), - K_(online_opt_stat_gather), K_(px_mode)); + TO_STRING_KV(K_(tablet_id), + K_(table_data_desc), + KP_(insert_table_ctx), + KP_(dml_row_handler)); public: common::ObTabletID tablet_id_; - int64_t snapshot_version_; - int64_t lob_column_cnt_; ObDirectLoadTableDataDesc table_data_desc_; - const blocksstable::ObStorageDatumUtils *datum_utils_; - const common::ObIArray *col_descs_; - const blocksstable::ObStoreCmpFuncs *cmp_funcs_; ObDirectLoadInsertTableContext *insert_table_ctx_; ObDirectLoadDMLRowHandler *dml_row_handler_; - bool online_opt_stat_gather_; - bool px_mode_; }; class ObDirectLoadFastHeapTableBuilder : public ObIDirectLoadPartitionTableBuilder @@ -59,46 +52,41 @@ public: ObDirectLoadFastHeapTableBuilder(); virtual ~ObDirectLoadFastHeapTableBuilder(); int init(const ObDirectLoadFastHeapTableBuildParam ¶m); - int append_row(const common::ObTabletID &tablet_id, - const table::ObTableLoadSequenceNo &seq_no, + int append_row(const common::ObTabletID &tablet_id, const table::ObTableLoadSequenceNo &seq_no, const blocksstable::ObDatumRow &datum_row) override; int close() override; int64_t get_row_count() const override { return row_count_; } int get_tables(common::ObIArray &table_array, common::ObIAllocator &allocator) override; private: - int init_sql_statistics(); - int init_lob_builder(); int init_sstable_slice_ctx(); int switch_sstable_slice(); private: class RowIterator : public ObDirectLoadInsertTableRowIterator - { - public: - RowIterator(); - virtual ~RowIterator(); - void reuse(); - void reset(); - int init(const ObDirectLoadFastHeapTableBuildParam ¶m, blocksstable::ObDatumRow &row, - common::ObIArray &column_stat_array, ObDirectLoadLobBuilder &lob_builder); - protected: - int inner_get_next_row(blocksstable::ObDatumRow *&row) override; - private: - blocksstable::ObDatumRow *datum_row_; - bool iter_end_; - bool is_inited_; - }; + { + public: + RowIterator(); + virtual ~RowIterator(); + int init(ObDirectLoadInsertTabletContext *insert_tablet_ctx, + table::ObTableLoadSqlStatistics *sql_statistics, + ObDirectLoadLobBuilder &lob_builder); + int set_row(blocksstable::ObDatumRow &row); + protected: + int inner_get_next_row(blocksstable::ObDatumRow *&row) override; + private: + blocksstable::ObDatumRow *datum_row_; + }; private: ObDirectLoadFastHeapTableBuildParam param_; - common::ObArenaAllocator allocator_; ObDirectLoadInsertTabletContext *insert_tablet_ctx_; + table::ObTableLoadSqlStatistics *sql_statistics_; + ObDirectLoadLobBuilder lob_builder_; ObDirectLoadInsertTabletWriteCtx write_ctx_; blocksstable::ObDatumRow datum_row_; - common::ObArray column_stat_array_; - ObDirectLoadLobBuilder lob_builder_; RowIterator row_iter_; int64_t current_slice_id_; int64_t row_count_; + bool has_lob_; bool is_closed_; bool is_inited_; DISALLOW_COPY_AND_ASSIGN(ObDirectLoadFastHeapTableBuilder); diff --git a/src/storage/direct_load/ob_direct_load_insert_table_ctx.cpp b/src/storage/direct_load/ob_direct_load_insert_table_ctx.cpp index 47238aee8..7af041724 100644 --- a/src/storage/direct_load/ob_direct_load_insert_table_ctx.cpp +++ b/src/storage/direct_load/ob_direct_load_insert_table_ctx.cpp @@ -13,8 +13,12 @@ #include "storage/direct_load/ob_direct_load_insert_table_ctx.h" #include "share/ob_tablet_autoincrement_service.h" -#include "storage/tx_storage/ob_ls_service.h" #include "storage/tablet/ob_tablet.h" +#include "storage/tx_storage/ob_ls_service.h" +#include "share/table/ob_table_load_dml_stat.h" +#include "share/table/ob_table_load_sql_statistics.h" +#include "share/stat/ob_stat_item.h" +#include "storage/direct_load/ob_direct_load_origin_table.h" namespace oceanbase { @@ -33,74 +37,45 @@ using namespace share; ObDirectLoadInsertTableParam::ObDirectLoadInsertTableParam() : table_id_(OB_INVALID_ID), - schema_version_(0), + lob_meta_tid_(OB_INVALID_ID), + schema_version_(OB_INVALID_VERSION), snapshot_version_(0), - execution_id_(0), ddl_task_id_(0), data_version_(0), + parallel_(0), reserved_parallel_(0), - ls_partition_ids_(), - target_ls_partition_ids_() + rowkey_column_count_(0), + column_count_(0), + lob_column_count_(0), + is_partitioned_table_(false), + is_heap_table_(false), + is_column_store_(false), + online_opt_stat_gather_(false), + is_incremental_(false), + datum_utils_(nullptr), + col_descs_(nullptr), + cmp_funcs_(nullptr) { - ls_partition_ids_.set_attr(ObMemAttr(MTL_ID(), "DLITP_ids")); - target_ls_partition_ids_.set_attr(ObMemAttr(MTL_ID(), "DLITP_t_ids")); } -ObDirectLoadInsertTableParam::~ObDirectLoadInsertTableParam() -{ -} +ObDirectLoadInsertTableParam::~ObDirectLoadInsertTableParam() {} bool ObDirectLoadInsertTableParam::is_valid() const { - return OB_INVALID_ID != table_id_ && schema_version_ >= 0 && snapshot_version_ >= 0 && - execution_id_ >= 0 && ddl_task_id_ > 0 && data_version_ >= 0 && reserved_parallel_ >= 0 && - ls_partition_ids_.count() > 0 && - ls_partition_ids_.count() == target_ls_partition_ids_.count(); -} - -int ObDirectLoadInsertTableParam::assign(const ObDirectLoadInsertTableParam &other) -{ - int ret = OB_SUCCESS; - table_id_ = other.table_id_; - schema_version_ = other.schema_version_; - snapshot_version_ = other.snapshot_version_; - execution_id_ = other.execution_id_; - ddl_task_id_ = other.ddl_task_id_; - data_version_ = other.data_version_; - reserved_parallel_ = other.reserved_parallel_; - if (OB_FAIL(ls_partition_ids_.assign(other.ls_partition_ids_))) { - LOG_WARN("fail to assign ls tablet ids", KR(ret)); - } else if (OB_FAIL(target_ls_partition_ids_.assign(other.target_ls_partition_ids_))) { - LOG_WARN("fail to assign ls tablet ids", KR(ret)); - } - return ret; -} - -/** - * ObDirectLoadInsertTabletParam - */ - -ObDirectLoadInsertTabletParam::ObDirectLoadInsertTabletParam() - : tenant_id_(OB_INVALID_TENANT_ID), - table_id_(OB_INVALID_ID), - schema_version_(0), - snapshot_version_(0), - execution_id_(0), - ddl_task_id_(0), - data_version_(0), - reserved_parallel_(0), - context_id_(0) -{ -} - -ObDirectLoadInsertTabletParam::~ObDirectLoadInsertTabletParam() {} - -bool ObDirectLoadInsertTabletParam::is_valid() const -{ - return OB_INVALID_TENANT_ID != tenant_id_ && ls_id_.is_valid() && OB_INVALID_ID != table_id_ && - tablet_id_.is_valid() && origin_tablet_id_.is_valid() && schema_version_ >= 0 && - snapshot_version_ >= 0 && execution_id_ >= 0 && ddl_task_id_ > 0 && data_version_ >= 0 && - reserved_parallel_ >= 0 && context_id_ >= 0; + return OB_INVALID_ID != table_id_ && + OB_INVALID_VERSION != schema_version_ && + snapshot_version_ >= 0 && + ddl_task_id_ > 0 && + data_version_ >= 0 && + parallel_ > 0 && + reserved_parallel_ >= 0 && + rowkey_column_count_ > 0 && + column_count_ > 0 && column_count_ >= rowkey_column_count_ && + lob_column_count_ >= 0 && lob_column_count_ < column_count_ && + (!is_incremental_ || trans_param_.is_valid()) && + nullptr != datum_utils_ && + nullptr != col_descs_ && col_descs_->count() == column_count_ && + nullptr != cmp_funcs_; } /** @@ -108,27 +83,123 @@ bool ObDirectLoadInsertTabletParam::is_valid() const */ ObDirectLoadInsertTabletContext::ObDirectLoadInsertTabletContext() - : is_open_(false), is_inited_(false) + : table_ctx_(nullptr), + param_(nullptr), + context_id_(0), + row_count_(0), + open_err_(OB_SUCCESS), + is_open_(false), + is_create_(false), + is_cancel_(false), + is_inited_(false) { } ObDirectLoadInsertTabletContext::~ObDirectLoadInsertTabletContext() { + int ret = OB_SUCCESS; + if (is_create_) { + ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); + if (OB_FAIL(sstable_insert_mgr->close_tablet_direct_load( + context_id_, !param_->is_incremental_, ls_id_, tablet_id_, false /*need_commit*/, + true /*emergent_finish*/))) { + LOG_WARN("fail to close tablet direct load", KR(ret), K(ls_id_), K(tablet_id_)); + } else { + is_create_ = false; + handle_.reset(); + } + } } -int ObDirectLoadInsertTabletContext::init(const ObDirectLoadInsertTabletParam ¶m) +int ObDirectLoadInsertTabletContext::init(ObDirectLoadInsertTableContext *table_ctx, + const ObLSID &ls_id, + const ObTabletID &origin_tablet_id, + const ObTabletID &tablet_id) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("ObDirectLoadInsertTabletContext init twice", KR(ret), KP(this)); - } else if (OB_UNLIKELY(!param.is_valid())) { + } else if (OB_UNLIKELY(nullptr == table_ctx || !ls_id.is_valid() || + !origin_tablet_id.is_valid() || !tablet_id.is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), K(param)); + LOG_WARN("invalid args", KR(ret), KPC(table_ctx), K(ls_id), K(origin_tablet_id), K(tablet_id)); } else { - param_ = param; - start_seq_.set_parallel_degree(param.reserved_parallel_); - is_inited_ = true; + const uint64_t tenant_id = MTL_ID(); + ObLSService *ls_service = nullptr; + ObLSHandle ls_handle; + ObTabletHandle tablet_handle; + ObTabletBindingMdsUserData ddl_data; + if (OB_ISNULL(ls_service = MTL(ObLSService *))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected err", K(ret), K(MTL_ID())); + } else if (OB_FAIL(ls_service->get_ls(ls_id, ls_handle, ObLSGetMod::DDL_MOD))) { + LOG_WARN("failed to get log stream", K(ret)); + } else if (OB_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, tablet_id, tablet_handle, + ObMDSGetTabletMode::READ_ALL_COMMITED))) { + LOG_WARN("get tablet handle failed", K(ret)); + } else if (OB_FAIL(tablet_handle.get_obj()->get_ddl_data(SCN::max_scn(), ddl_data))) { + LOG_WARN("get ddl data failed", K(ret)); + } else { + table_ctx_ = table_ctx; + param_ = &table_ctx->get_param(); + context_id_ = table_ctx->get_context_id(); + ls_id_ = ls_id; + origin_tablet_id_ = origin_tablet_id; + tablet_id_ = tablet_id; + lob_tablet_id_ = ddl_data.lob_meta_tablet_id_; + start_seq_.set_parallel_degree(param_->reserved_parallel_); + if (param_->is_incremental_ && OB_FAIL(check_lob_meta_empty())) { + LOG_WARN("failed to check lob meta empty", KR(ret)); + } else { + is_inited_ = true; + } + } + } + return ret; +} + +int ObDirectLoadInsertTabletContext::check_lob_meta_empty() +{ + int ret = OB_SUCCESS; + uint64_t lob_meta_tid = param_->lob_meta_tid_; + if (OB_INVALID_ID == lob_meta_tid) { + // bypass + } else { + ObArenaAllocator iter_allocator("TLD_Iter"); + ObDirectLoadOriginTable origin_table; + ObIStoreRowIterator *lob_row_iter = nullptr; + const blocksstable::ObDatumRow *row = nullptr; + blocksstable::ObDatumRange range; + ObDirectLoadOriginTableCreateParam table_param; + table_param.table_id_ = lob_meta_tid; + table_param.tablet_id_ = lob_tablet_id_; + table_param.ls_id_ = ls_id_; + table_param.insert_mode_ = ObDirectLoadInsertMode::NORMAL; + iter_allocator.set_tenant_id(MTL_ID()); + range.set_whole_range(); + + if (OB_FAIL(origin_table.init(table_param))) { + LOG_WARN("failed to init origin table", KR(ret)); + } else if (OB_FAIL(origin_table.scan(range, iter_allocator, lob_row_iter))) { + LOG_WARN("fail to scan origin table", KR(ret)); + } else if (OB_FAIL(lob_row_iter->get_next_row(row))) { + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; // empty table + } else { + LOG_WARN("failed to get next row", KR(ret)); + } + } else { + ret = OB_NOT_SUPPORTED; + LOG_WARN("incremental direct-load to table with outrow lob data is not supported", KR(ret)); + FORWARD_USER_ERROR(ret, "incremental direct-load to table with outrow lob data is not supported"); + } + // release row iter + if (OB_NOT_NULL(lob_row_iter)) { + lob_row_iter->~ObIStoreRowIterator(); + iter_allocator.free(lob_row_iter); + lob_row_iter = nullptr; + } } return ret; } @@ -139,35 +210,53 @@ int ObDirectLoadInsertTabletContext::open() if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); } else if (is_open_) { // do nothing } else { lib::ObMutexGuard guard(mutex_); - if (!is_open_) { + if (OB_FAIL(open_err_)) { + LOG_WARN("open has error", KR(ret), K(origin_tablet_id_), K(tablet_id_)); + } else if (!is_open_) { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); ObTabletDirectLoadInsertParam direct_load_param; direct_load_param.is_replay_ = false; - direct_load_param.common_param_.direct_load_type_ = ObDirectLoadType::DIRECT_LOAD_LOAD_DATA; - direct_load_param.common_param_.data_format_version_ = param_.data_version_; - direct_load_param.common_param_.read_snapshot_ = param_.snapshot_version_; - direct_load_param.common_param_.ls_id_ = param_.ls_id_; - direct_load_param.common_param_.tablet_id_ = param_.tablet_id_; + direct_load_param.common_param_.direct_load_type_ = + param_->is_incremental_ ? ObDirectLoadType::DIRECT_LOAD_INCREMENTAL + : ObDirectLoadType::DIRECT_LOAD_LOAD_DATA; + direct_load_param.common_param_.data_format_version_ = param_->data_version_; + direct_load_param.common_param_.read_snapshot_ = param_->snapshot_version_; + direct_load_param.common_param_.ls_id_ = ls_id_; + direct_load_param.common_param_.tablet_id_ = tablet_id_; direct_load_param.runtime_only_param_.exec_ctx_ = nullptr; - direct_load_param.runtime_only_param_.task_id_ = param_.ddl_task_id_; - direct_load_param.runtime_only_param_.table_id_ = param_.table_id_; - direct_load_param.runtime_only_param_.schema_version_ = param_.schema_version_; + direct_load_param.runtime_only_param_.task_id_ = param_->ddl_task_id_; + direct_load_param.runtime_only_param_.table_id_ = param_->table_id_; + direct_load_param.runtime_only_param_.schema_version_ = param_->schema_version_; direct_load_param.runtime_only_param_.task_cnt_ = 1; // default value. - direct_load_param.runtime_only_param_.parallel_ = param_.reserved_parallel_; - if (OB_FAIL(sstable_insert_mgr->create_tablet_direct_load( - param_.context_id_, param_.execution_id_, direct_load_param))) { - LOG_WARN("create tablet manager failed", K(ret)); - } else if (OB_FAIL(sstable_insert_mgr->open_tablet_direct_load( - true, param_.ls_id_, param_.tablet_id_, param_.context_id_, start_scn_, - handle_))) { - LOG_WARN("fail to open tablet direct load", KR(ret), K(param_.tablet_id_)); + direct_load_param.runtime_only_param_.parallel_ = param_->parallel_; + direct_load_param.runtime_only_param_.tx_desc_ = param_->trans_param_.tx_desc_; + direct_load_param.runtime_only_param_.trans_id_ = param_->trans_param_.tx_id_; + direct_load_param.runtime_only_param_.seq_no_ = param_->trans_param_.tx_seq_.cast_to_int(); + if (OB_FAIL(sstable_insert_mgr->create_tablet_direct_load(context_id_, + context_id_ /*execution_id*/, + direct_load_param))) { + LOG_WARN("create tablet manager failed", KR(ret), K(direct_load_param)); + } else if (FALSE_IT(is_create_ = true)) { + } else if (OB_FAIL(sstable_insert_mgr->open_tablet_direct_load(!param_->is_incremental_, + ls_id_, + tablet_id_, + context_id_, + start_scn_, + handle_))) { + LOG_WARN("fail to open tablet direct load", KR(ret), K(tablet_id_)); } else { is_open_ = true; } + if (OB_FAIL(ret)) { + open_err_ = ret; // avoid open repeatedly when failed + } } } return ret; @@ -179,32 +268,50 @@ int ObDirectLoadInsertTabletContext::close() if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTabletContext not init", KR(ret), KP(this)); - } else if (OB_UNLIKELY(!is_open_)) { + } else if (OB_UNLIKELY(!is_open_ || is_cancel_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("expected does not open", KR(ret)); + LOG_WARN("unexpected to close", KR(ret), K(is_open_), K(is_cancel_)); } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); if (OB_FAIL(sstable_insert_mgr->close_tablet_direct_load( - param_.context_id_, true, param_.ls_id_, param_.tablet_id_, true, true))) { - LOG_WARN("fail to close tablet direct load", KR(ret), K(param_.ls_id_), - K(param_.tablet_id_)); + context_id_, !param_->is_incremental_, ls_id_, tablet_id_, true /*need_commit*/, + true /*emergent_finish*/))) { + LOG_WARN("fail to close tablet direct load", KR(ret), K(ls_id_), K(tablet_id_)); } else { - handle_.reset(); is_open_ = false; + handle_.reset(); + } + } + return ret; +} + +int ObDirectLoadInsertTabletContext::cancel() +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDirectLoadInsertTableContext not init", K(ret), KP(this)); + } else { + LOG_INFO("start to remove slice writers", K(tablet_id_)); + ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); + if (OB_FAIL(sstable_insert_mgr->cancel(context_id_, ls_id_, tablet_id_, !param_->is_incremental_))) { + LOG_WARN("cancel direct load fill task failed", K(ret), K(context_id_), K(tablet_id_)); + } else { + is_cancel_ = true; } } return ret; } int ObDirectLoadInsertTabletContext::get_pk_interval(uint64_t count, - share::ObTabletCacheInterval &pk_interval) + ObTabletCacheInterval &pk_interval) { int ret = OB_SUCCESS; if (OB_FAIL(pk_cache_.fetch(count, pk_interval))) { if (OB_UNLIKELY(OB_EAGAIN != ret)) { LOG_WARN("fail to fetch from pk cache", KR(ret)); } else { - if (OB_FAIL(refresh_pk_cache(param_.origin_tablet_id_, pk_cache_))) { + if (OB_FAIL(refresh_pk_cache(origin_tablet_id_, pk_cache_))) { LOG_WARN("fail to refresh pk cache", KR(ret)); } else if (OB_FAIL(pk_cache_.fetch(count, pk_interval))) { LOG_WARN("fail to fetch from pk cache", KR(ret)); @@ -215,14 +322,14 @@ int ObDirectLoadInsertTabletContext::get_pk_interval(uint64_t count, } int ObDirectLoadInsertTabletContext::get_lob_pk_interval(uint64_t count, - share::ObTabletCacheInterval &pk_interval) + ObTabletCacheInterval &pk_interval) { int ret = OB_SUCCESS; if (OB_FAIL(lob_pk_cache_.fetch(count, pk_interval))) { if (OB_UNLIKELY(OB_EAGAIN != ret)) { LOG_WARN("fail to fetch from pk cache", KR(ret)); } else { - if (OB_FAIL(refresh_pk_cache(param_.lob_tablet_id_, lob_pk_cache_))) { + if (OB_FAIL(refresh_pk_cache(lob_tablet_id_, lob_pk_cache_))) { LOG_WARN("fail to refresh pk cache", KR(ret)); } else if (OB_FAIL(lob_pk_cache_.fetch(count, pk_interval))) { LOG_WARN("fail to fetch from pk cache", KR(ret)); @@ -258,8 +365,7 @@ int ObDirectLoadInsertTabletContext::get_lob_write_ctx(ObDirectLoadInsertTabletW LOG_WARN("ObDirectLoadLobTabletContext not init", KR(ret), KP(this)); } else { ObMutexGuard guard(mutex_); - if (OB_FAIL( - get_lob_pk_interval(WRITE_BATCH_SIZE, write_ctx.pk_interval_))) { + if (OB_FAIL(get_lob_pk_interval(WRITE_BATCH_SIZE, write_ctx.pk_interval_))) { LOG_WARN("fail to get pk interval", KR(ret), KP(this)); } else { write_ctx.start_seq_.macro_data_seq_ = lob_start_seq_.macro_data_seq_; @@ -269,20 +375,49 @@ int ObDirectLoadInsertTabletContext::get_lob_write_ctx(ObDirectLoadInsertTabletW return ret; } -int ObDirectLoadInsertTabletContext::refresh_pk_cache(const common::ObTabletID &tablet_id, share::ObTabletCacheInterval &pk_cache) +int ObDirectLoadInsertTabletContext::refresh_pk_cache(const ObTabletID &tablet_id, + ObTabletCacheInterval &pk_cache) { int ret = OB_SUCCESS; + const uint64_t tenant_id = MTL_ID(); ObTabletAutoincrementService &auto_inc = ObTabletAutoincrementService::get_instance(); pk_cache.tablet_id_ = tablet_id; pk_cache.cache_size_ = PK_CACHE_SIZE; - if (OB_FAIL(auto_inc.get_tablet_cache_interval(param_.tenant_id_, pk_cache))) { - LOG_WARN("get_autoinc_seq fail", K(ret), K_(param_.tenant_id), K(tablet_id)); + if (OB_FAIL(auto_inc.get_tablet_cache_interval(tenant_id, pk_cache))) { + LOG_WARN("get_autoinc_seq fail", K(ret), K(tenant_id), K(tablet_id)); } else if (OB_UNLIKELY(PK_CACHE_SIZE > pk_cache.count())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected autoincrement value count", K(ret), K(pk_cache)); } return ret; +} +int ObDirectLoadInsertTabletContext::init_datum_row(ObDatumRow &datum_row) +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDirectLoadInsertTableContext not init", K(ret), KP(this)); + } else { + const int64_t real_column_count = + param_->column_count_ + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); + if (OB_FAIL(datum_row.init(real_column_count))) { + LOG_WARN("fail to init datum row", KR(ret), K(real_column_count)); + } else { + const int64_t trans_version = + !param_->is_incremental_ ? param_->snapshot_version_ : INT64_MAX; + datum_row.trans_id_ = param_->trans_param_.tx_id_; + datum_row.row_flag_.set_flag(ObDmlFlag::DF_INSERT, !param_->is_incremental_ ? DF_TYPE_NORMAL : DF_TYPE_INSERT_DELETE); + datum_row.mvcc_row_flag_.set_last_multi_version_row(true); + datum_row.mvcc_row_flag_.set_uncommitted_row(param_->is_incremental_); + // fill trans_version + datum_row.storage_datums_[param_->rowkey_column_count_].set_int(-trans_version); + // fill sql_no + datum_row.storage_datums_[param_->rowkey_column_count_ + 1].set_int( + -param_->trans_param_.tx_seq_.cast_to_int()); + } + } + return ret; } int ObDirectLoadInsertTabletContext::fill_sstable_slice(const int64_t &slice_id, @@ -293,17 +428,22 @@ int ObDirectLoadInsertTabletContext::fill_sstable_slice(const int64_t &slice_id, if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); + } else if (OB_UNLIKELY(!is_open_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected not open", KR(ret)); } else { ObDirectLoadInsertTabletContext *tablet_ctx = nullptr; ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); ObDirectLoadSliceInfo slice_info; - // slice_info.is_full_direct_load_ = !param_.px_mode_; - slice_info.is_full_direct_load_ = true; + slice_info.is_full_direct_load_ = !param_->is_incremental_; slice_info.is_lob_slice_ = false; - slice_info.ls_id_ = param_.ls_id_; - slice_info.data_tablet_id_ = param_.tablet_id_; + slice_info.ls_id_ = ls_id_; + slice_info.data_tablet_id_ = tablet_id_; slice_info.slice_id_ = slice_id; - slice_info.context_id_ = param_.context_id_; + slice_info.context_id_ = context_id_; if (OB_FAIL(sstable_insert_mgr->fill_sstable_slice(slice_info, &iter, affected_rows))) { LOG_WARN("fail to fill sstable slice", KR(ret)); } @@ -313,46 +453,57 @@ int ObDirectLoadInsertTabletContext::fill_sstable_slice(const int64_t &slice_id, int ObDirectLoadInsertTabletContext::fill_lob_sstable_slice(ObIAllocator &allocator, const int64_t &lob_slice_id, - share::ObTabletCacheInterval &pk_interval, - blocksstable::ObDatumRow &datum_row) + ObTabletCacheInterval &pk_interval, + ObDatumRow &datum_row) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); + } else if (OB_UNLIKELY(!is_open_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected not open", KR(ret)); } else { ObDirectLoadSliceInfo slice_info; - // slice_info.is_full_direct_load_ = !param_.px_mode_; - slice_info.is_full_direct_load_ = true; + slice_info.is_full_direct_load_ = !param_->is_incremental_; slice_info.is_lob_slice_ = true; - slice_info.ls_id_ = param_.ls_id_; - slice_info.data_tablet_id_ = param_.tablet_id_; + slice_info.ls_id_ = ls_id_; + slice_info.data_tablet_id_ = tablet_id_; slice_info.slice_id_ = lob_slice_id; - slice_info.context_id_ = param_.context_id_; - if (OB_FAIL(handle_.get_obj()->fill_lob_sstable_slice(allocator, slice_info, start_scn_, pk_interval, datum_row))) { + slice_info.context_id_ = context_id_; + if (OB_UNLIKELY(!handle_.is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected invalid handle", KR(ret)); + } else if (OB_FAIL(handle_.get_obj()->fill_lob_sstable_slice(allocator, slice_info, start_scn_, + pk_interval, datum_row))) { LOG_WARN("fail to fill sstable slice", KR(ret), K(slice_info), K(datum_row)); } } return ret; } -int ObDirectLoadInsertTabletContext::open_sstable_slice( - const blocksstable::ObMacroDataSeq &start_seq, int64_t &slice_id) +int ObDirectLoadInsertTabletContext::open_sstable_slice(const ObMacroDataSeq &start_seq, + int64_t &slice_id) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); ObDirectLoadSliceInfo slice_info; - // slice_info.is_full_direct_load_ = !param_.px_mode_; - slice_info.is_full_direct_load_ = true; + slice_info.is_full_direct_load_ = !param_->is_incremental_; slice_info.is_lob_slice_ = false; - slice_info.ls_id_ = param_.ls_id_; - slice_info.data_tablet_id_ = param_.tablet_id_; + slice_info.ls_id_ = ls_id_; + slice_info.data_tablet_id_ = tablet_id_; slice_info.slice_id_ = slice_id; - slice_info.context_id_ = param_.context_id_; + slice_info.context_id_ = context_id_; if (OB_FAIL(open())) { LOG_WARN("fail to open tablet direct load", KR(ret)); } else if (OB_FAIL(sstable_insert_mgr->open_sstable_slice(start_seq, slice_info))) { @@ -364,23 +515,25 @@ int ObDirectLoadInsertTabletContext::open_sstable_slice( return ret; } -int ObDirectLoadInsertTabletContext::open_lob_sstable_slice( - const blocksstable::ObMacroDataSeq &start_seq, int64_t &slice_id) +int ObDirectLoadInsertTabletContext::open_lob_sstable_slice(const ObMacroDataSeq &start_seq, + int64_t &slice_id) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); ObDirectLoadSliceInfo slice_info; - // slice_info.is_full_direct_load_ = !param_.px_mode_; - slice_info.is_full_direct_load_ = true; + slice_info.is_full_direct_load_ = !param_->is_incremental_; slice_info.is_lob_slice_ = true; - slice_info.ls_id_ = param_.ls_id_; - slice_info.data_tablet_id_ = param_.tablet_id_; + slice_info.ls_id_ = ls_id_; + slice_info.data_tablet_id_ = tablet_id_; slice_info.slice_id_ = slice_id; - slice_info.context_id_ = param_.context_id_; + slice_info.context_id_ = context_id_; if (OB_FAIL(open())) { LOG_WARN("fail to open tablet direct load", KR(ret)); } else if (OB_FAIL(sstable_insert_mgr->open_sstable_slice(start_seq, slice_info))) { @@ -401,16 +554,15 @@ int ObDirectLoadInsertTabletContext::close_sstable_slice(const int64_t slice_id) } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); ObDirectLoadSliceInfo slice_info; - slice_info.is_full_direct_load_ = true; + slice_info.is_full_direct_load_ = !param_->is_incremental_; slice_info.is_lob_slice_ = false; - slice_info.ls_id_ = param_.ls_id_; - slice_info.data_tablet_id_ = param_.tablet_id_; + slice_info.ls_id_ = ls_id_; + slice_info.data_tablet_id_ = tablet_id_; slice_info.slice_id_ = slice_id; - slice_info.context_id_ = param_.context_id_; + slice_info.context_id_ = context_id_; blocksstable::ObMacroDataSeq unused_seq; if (OB_FAIL(sstable_insert_mgr->close_sstable_slice(slice_info, nullptr/*insert_monitor*/, unused_seq))) { - LOG_WARN("fail to close tablet direct load", KR(ret), K(slice_id), - K(param_.tablet_id_)); + LOG_WARN("fail to close tablet direct load", KR(ret), K(slice_id), K(tablet_id_)); } } return ret; @@ -425,16 +577,15 @@ int ObDirectLoadInsertTabletContext::close_lob_sstable_slice(const int64_t slice } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); ObDirectLoadSliceInfo slice_info; - slice_info.is_full_direct_load_ = true; + slice_info.is_full_direct_load_ = !param_->is_incremental_; slice_info.is_lob_slice_ = true; - slice_info.ls_id_ = param_.ls_id_; - slice_info.data_tablet_id_ = param_.tablet_id_; + slice_info.ls_id_ = ls_id_; + slice_info.data_tablet_id_ = tablet_id_; slice_info.slice_id_ = slice_id; - slice_info.context_id_ = param_.context_id_; + slice_info.context_id_ = context_id_; blocksstable::ObMacroDataSeq unused_seq; if (OB_FAIL(sstable_insert_mgr->close_sstable_slice(slice_info, nullptr/*insert_monitor*/, unused_seq))) { - LOG_WARN("fail to close tablet direct load", KR(ret), K(slice_id), - K(param_.tablet_id_)); + LOG_WARN("fail to close tablet direct load", KR(ret), K(slice_id), K(tablet_id_)); } } return ret; @@ -446,43 +597,36 @@ int ObDirectLoadInsertTabletContext::calc_range(const int64_t thread_cnt) if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); - if (OB_FAIL(sstable_insert_mgr->calc_range(param_.ls_id_, param_.tablet_id_, thread_cnt, true))) { - LOG_WARN("fail to calc range", KR(ret), K(param_.tablet_id_)); + if (OB_FAIL(sstable_insert_mgr->calc_range(ls_id_, tablet_id_, thread_cnt, + !param_->is_incremental_))) { + LOG_WARN("fail to calc range", KR(ret), K(tablet_id_)); } else { - LOG_INFO("success to calc range", K(param_.tablet_id_)); + LOG_INFO("success to calc range", K(tablet_id_)); } } return ret; } -int ObDirectLoadInsertTabletContext::fill_column_group(const int64_t thread_cnt, const int64_t thread_id) +int ObDirectLoadInsertTabletContext::fill_column_group(const int64_t thread_cnt, + const int64_t thread_id) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(is_cancel_)) { + ret = OB_CANCELED; + LOG_WARN("task is cancel", KR(ret)); } else { ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); - if (OB_FAIL(sstable_insert_mgr->fill_column_group(param_.ls_id_, param_.tablet_id_, true/*is direct load*/, thread_cnt, thread_id))) { - LOG_WARN("fail to fill column group", KR(ret), K(param_.tablet_id_), K(thread_cnt), K(thread_id)); - } - } - return ret; -} - -int ObDirectLoadInsertTabletContext::cancel() -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObDirectLoadInsertTableContext not init", K(ret), KP(this)); - } else { - LOG_INFO("start to remove slice writers", K(param_.tablet_id_)); - ObTenantDirectLoadMgr *sstable_insert_mgr = MTL(ObTenantDirectLoadMgr *); - if (OB_FAIL(sstable_insert_mgr->cancel(param_.ls_id_, param_.tablet_id_, true/*is direct load*/))) { - LOG_WARN("cancel direct load fill task failed", K(ret), K(param_.tablet_id_)); + if (OB_FAIL(sstable_insert_mgr->fill_column_group(ls_id_, tablet_id_, !param_->is_incremental_, + thread_cnt, thread_id))) { + LOG_WARN("fail to fill column group", KR(ret), K(tablet_id_), K(thread_cnt), K(thread_id)); } } return ret; @@ -493,7 +637,7 @@ int ObDirectLoadInsertTabletContext::cancel() */ ObDirectLoadInsertTableContext::ObDirectLoadInsertTableContext() - : allocator_("TLD_InsertTbl"), is_inited_(false) + : allocator_("TLD_InsTblCtx"), safe_allocator_(allocator_), is_inited_(false) { allocator_.set_tenant_id(MTL_ID()); } @@ -502,95 +646,80 @@ ObDirectLoadInsertTableContext::~ObDirectLoadInsertTableContext() { destory(); } void ObDirectLoadInsertTableContext::destory() { - int ret = OB_SUCCESS; - for (TABLET_CTX_MAP::iterator iter = tablet_ctx_map_.begin(); iter != tablet_ctx_map_.end(); - ++iter) { + FOREACH(iter, tablet_ctx_map_) + { ObDirectLoadInsertTabletContext *tablet_ctx = iter->second; tablet_ctx->~ObDirectLoadInsertTabletContext(); allocator_.free(tablet_ctx); } tablet_ctx_map_.destroy(); + FOREACH(iter, sql_stat_map_) + { + ObTableLoadSqlStatistics *sql_statistics = iter->second; + sql_statistics->~ObTableLoadSqlStatistics(); + allocator_.free(sql_statistics); + } + sql_stat_map_.destroy(); allocator_.reset(); is_inited_ = false; } -int ObDirectLoadInsertTableContext::init(const ObDirectLoadInsertTableParam ¶m) +int ObDirectLoadInsertTableContext::init( + const ObDirectLoadInsertTableParam ¶m, + const ObIArray &ls_partition_ids, + const ObIArray &target_ls_partition_ids) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("ObDirectLoadInsertTableContext init twice", KR(ret), KP(this)); - } else if (OB_UNLIKELY(!param.is_valid())) { + } else if (OB_UNLIKELY(!param.is_valid() || ls_partition_ids.empty() || + target_ls_partition_ids.empty() || + ls_partition_ids.count() != target_ls_partition_ids.count())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), K(param)); - } else if (OB_FAIL(param_.assign(param))) { - LOG_WARN("fail to assign param", KR(ret)); - } else if (OB_FAIL(tablet_ctx_map_.create(1024, "TLD_InsTabCtx", - "TLD_InsTabCtx", MTL_ID()))) { - LOG_WARN("fail to create tablet ctx map", KR(ret)); - } else if (OB_FAIL(MTL(ObTenantDirectLoadMgr *)->alloc_execution_context_id(ddl_ctrl_.context_id_))) { - LOG_WARN("alloc execution context id failed", K(ret)); - } else if (OB_FAIL(create_all_tablet_contexts())) { - LOG_WARN("fail to create all tablet contexts", KR(ret)); + LOG_WARN("invalid args", KR(ret), K(param), K(ls_partition_ids), K(target_ls_partition_ids)); } else { - is_inited_ = true; + param_ = param; + if (OB_FAIL(tablet_ctx_map_.create(1024, "TLD_InsTabCtx", "TLD_InsTabCtx", MTL_ID()))) { + LOG_WARN("fail to create tablet ctx map", KR(ret)); + } else if (OB_FAIL( + MTL(ObTenantDirectLoadMgr *)->alloc_execution_context_id(ddl_ctrl_.context_id_))) { + LOG_WARN("alloc execution context id failed", K(ret)); + } else if (OB_FAIL(create_all_tablet_contexts(ls_partition_ids, target_ls_partition_ids))) { + LOG_WARN("fail to create all tablet contexts", KR(ret)); + } else if (param_.online_opt_stat_gather_ && + sql_stat_map_.create(1024, "TLD_SqlStatMap", "TLD_SqlStatMap", MTL_ID())) { + LOG_WARN("fail to create sql stat map", KR(ret)); + } else { + is_inited_ = true; + } } return ret; } -int ObDirectLoadInsertTableContext::create_all_tablet_contexts() +int ObDirectLoadInsertTableContext::create_all_tablet_contexts( + const ObIArray &ls_partition_ids, + const ObIArray &target_ls_partition_ids) { int ret = OB_SUCCESS; - uint64_t tenant_id = MTL_ID(); - for (int64_t i = 0; OB_SUCC(ret) && i < param_.ls_partition_ids_.count(); ++i) { - const ObLSID &target_ls_id = param_.target_ls_partition_ids_.at(i).ls_id_; - const ObTabletID &tablet_id = param_.ls_partition_ids_.at(i).part_tablet_id_.tablet_id_; - const ObTabletID &target_tablet_id = - param_.target_ls_partition_ids_.at(i).part_tablet_id_.tablet_id_; + for (int64_t i = 0; OB_SUCC(ret) && i < ls_partition_ids.count(); ++i) { + const ObTabletID &origin_tablet_id = ls_partition_ids.at(i).part_tablet_id_.tablet_id_; + const ObLSID &ls_id = target_ls_partition_ids.at(i).ls_id_; + const ObTabletID &tablet_id = target_ls_partition_ids.at(i).part_tablet_id_.tablet_id_; ObDirectLoadInsertTabletContext *tablet_ctx = nullptr; - ObLSService *ls_service = nullptr; - ObLSHandle ls_handle; - ObTabletHandle tablet_handle; - if (OB_ISNULL(ls_service = MTL(ObLSService *))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected err", K(ret), K(MTL_ID())); - } else if (OB_FAIL(ls_service->get_ls(target_ls_id, ls_handle, ObLSGetMod::DDL_MOD))) { - LOG_WARN("failed to get log stream", K(ret)); - } else if (OB_FAIL(ObDDLUtil::ddl_get_tablet(ls_handle, target_tablet_id, tablet_handle, - ObMDSGetTabletMode::READ_ALL_COMMITED))) { - LOG_WARN("get tablet handle failed", K(ret)); - } else { - ObTabletBindingMdsUserData ddl_data; - ObDirectLoadInsertTabletParam insert_tablet_param; - insert_tablet_param.tenant_id_ = tenant_id; - insert_tablet_param.ls_id_ = target_ls_id; - insert_tablet_param.table_id_ = param_.table_id_; - insert_tablet_param.tablet_id_ = target_tablet_id; - insert_tablet_param.origin_tablet_id_ = tablet_id; - insert_tablet_param.schema_version_ = param_.schema_version_; - insert_tablet_param.snapshot_version_ = param_.snapshot_version_; - insert_tablet_param.execution_id_ = param_.execution_id_; - insert_tablet_param.ddl_task_id_ = param_.ddl_task_id_; - insert_tablet_param.data_version_ = param_.data_version_; - insert_tablet_param.reserved_parallel_ = param_.reserved_parallel_; - insert_tablet_param.context_id_ = ddl_ctrl_.context_id_; - if (OB_FAIL(tablet_handle.get_obj()->get_ddl_data(SCN::max_scn(), ddl_data))) { - LOG_WARN("get ddl data failed", K(ret)); - } else if (OB_ISNULL(tablet_ctx = OB_NEWx(ObDirectLoadInsertTabletContext, (&allocator_)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to new ObDirectLoadInsertTabletContext", KR(ret)); - } else if (OB_FALSE_IT(insert_tablet_param.lob_tablet_id_ = ddl_data.lob_meta_tablet_id_)) { - } else if (OB_FAIL(tablet_ctx->init(insert_tablet_param))) { - LOG_WARN("fail to init fast heap table tablet ctx", KR(ret)); - } else if (OB_FAIL(tablet_ctx_map_.set_refactored(tablet_id, tablet_ctx))) { - LOG_WARN("fail to set tablet ctx map", KR(ret)); - } - if (OB_FAIL(ret)) { - if (nullptr != tablet_ctx) { - tablet_ctx->~ObDirectLoadInsertTabletContext(); - allocator_.free(tablet_ctx); - tablet_ctx = nullptr; - } + if (OB_ISNULL(tablet_ctx = OB_NEWx(ObDirectLoadInsertTabletContext, (&allocator_)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObDirectLoadInsertTabletContext", KR(ret)); + } else if (OB_FAIL(tablet_ctx->init(this, ls_id, origin_tablet_id, tablet_id))) { + LOG_WARN("fail to init fast heap table tablet ctx", KR(ret)); + } else if (OB_FAIL(tablet_ctx_map_.set_refactored(origin_tablet_id, tablet_ctx))) { + LOG_WARN("fail to set tablet ctx map", KR(ret)); + } + if (OB_FAIL(ret)) { + if (nullptr != tablet_ctx) { + tablet_ctx->~ObDirectLoadInsertTabletContext(); + allocator_.free(tablet_ctx); + tablet_ctx = nullptr; } } } @@ -617,6 +746,23 @@ int ObDirectLoadInsertTableContext::get_tablet_context( return ret; } +int ObDirectLoadInsertTableContext::commit(ObTableLoadDmlStat &dml_stats, + ObTableLoadSqlStatistics &sql_statistics) +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else { + if (OB_FAIL(collect_dml_stat(dml_stats))) { + LOG_WARN("fail to collect dml stat", KR(ret)); + } else if (param_.online_opt_stat_gather_ && collect_sql_statistics(sql_statistics)) { + LOG_WARN("fail to collect sql statistics", KR(ret)); + } + } + return ret; +} + void ObDirectLoadInsertTableContext::cancel() { int ret = OB_SUCCESS; @@ -624,7 +770,8 @@ void ObDirectLoadInsertTableContext::cancel() ret = OB_NOT_INIT; LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); } else { - FOREACH(iter, tablet_ctx_map_) { + FOREACH(iter, tablet_ctx_map_) + { const ObTabletID &tablet_id = iter->first; ObDirectLoadInsertTabletContext *tablet_ctx = iter->second; if (OB_ISNULL(tablet_ctx)) { @@ -637,5 +784,192 @@ void ObDirectLoadInsertTableContext::cancel() } } +int64_t ObDirectLoadInsertTableContext::get_sql_stat_column_count() const +{ + int64_t column_count = 0; + if (!param_.is_heap_table_) { + column_count = param_.column_count_; + } else { + column_count = param_.column_count_ - param_.rowkey_column_count_; + } + return column_count; +} + +int ObDirectLoadInsertTableContext::get_sql_statistics(ObTableLoadSqlStatistics *&sql_statistics) +{ + int ret = OB_SUCCESS; + sql_statistics = nullptr; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(!param_.online_opt_stat_gather_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected no gather sql stat", KR(ret), K(param_)); + } else { + const int64_t part_id = get_tid_cache(); + if (OB_FAIL(sql_stat_map_.get_refactored(part_id, sql_statistics))) { + if (OB_UNLIKELY(OB_HASH_NOT_EXIST != ret)) { + LOG_WARN("fail to get sql stat", KR(ret), K(part_id)); + } else { + ret = OB_SUCCESS; + const int64_t column_count = get_sql_stat_column_count(); + ObTableLoadSqlStatistics *new_sql_statistics = nullptr; + if (OB_ISNULL(new_sql_statistics = OB_NEWx(ObTableLoadSqlStatistics, (&safe_allocator_)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to new ObTableLoadSqlStatistics", KR(ret)); + } else if (OB_FAIL(new_sql_statistics->create(column_count))) { + LOG_WARN("fail to create sql stat", KR(ret), K(column_count)); + } else if (OB_FAIL(sql_stat_map_.set_refactored(part_id, new_sql_statistics))) { + LOG_WARN("fail to set sql stat back", KR(ret), K(part_id)); + } else { + sql_statistics = new_sql_statistics; + } + if (OB_FAIL(ret)) { + if (nullptr != new_sql_statistics) { + new_sql_statistics->~ObTableLoadSqlStatistics(); + safe_allocator_.free(new_sql_statistics); + new_sql_statistics = nullptr; + } + } + } + } + } + return ret; +} + +int ObDirectLoadInsertTableContext::update_sql_statistics(ObTableLoadSqlStatistics &sql_statistics, + const ObDatumRow &datum_row) +{ + int ret = OB_SUCCESS; + const int64_t extra_rowkey_cnt = ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDirectLoadInsertTableContext not init", KR(ret), KP(this)); + } else if (OB_UNLIKELY(!param_.online_opt_stat_gather_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected not gather sql stat", KR(ret), K(param_)); + } else if (OB_UNLIKELY(datum_row.get_column_count() != param_.column_count_ + extra_rowkey_cnt)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid datum row", KR(ret), K(param_), K(datum_row)); + } else { + ObOptOSGColumnStat *col_stat = nullptr; + for (int64_t i = 0; OB_SUCC(ret) && i < param_.column_count_; i++) { + if (i < param_.rowkey_column_count_ && param_.is_heap_table_) { + // ignore heap table hidden pk + } else { + const int64_t datum_idx = i < param_.rowkey_column_count_ ? i : i + extra_rowkey_cnt; + const int64_t col_stat_idx = param_.is_heap_table_ ? i - 1 : i; + const ObStorageDatum &datum = datum_row.storage_datums_[datum_idx]; + const ObCmpFunc &cmp_func = param_.cmp_funcs_->at(i).get_cmp_func(); + const ObColDesc &col_desc = param_.col_descs_->at(i); + const bool is_valid = ObColumnStatParam::is_valid_opt_col_type(col_desc.col_type_.get_type()); + if (is_valid) { + if (OB_FAIL(sql_statistics.get_col_stat(col_stat_idx, col_stat))) { + LOG_WARN("fail to get col stat", KR(ret), K(col_stat_idx)); + } else if (OB_ISNULL(col_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected col stat is null", KR(ret), K(col_stat_idx)); + } else if (OB_FAIL(col_stat->update_column_stat_info(&datum, + col_desc.col_type_, + cmp_func.cmp_func_))) { + LOG_WARN("fail to merge obj", KR(ret), KP(col_stat)); + } + } + } + } + } + return ret; +} + +int ObDirectLoadInsertTableContext::collect_dml_stat(ObTableLoadDmlStat &dml_stats) +{ + int ret = OB_SUCCESS; + const uint64_t tenant_id = MTL_ID(); + dml_stats.reset(); + FOREACH_X(iter, tablet_ctx_map_, OB_SUCC(ret)) { + ObDirectLoadInsertTabletContext *tablet_ctx = iter->second; + ObOptDmlStat *dml_stat = nullptr; + if (OB_FAIL(dml_stats.allocate_dml_stat(dml_stat))) { + LOG_WARN("fail to allocate table stat", KR(ret)); + } else { + dml_stat->tenant_id_ = tenant_id; + dml_stat->table_id_ = param_.table_id_; + dml_stat->tablet_id_ = tablet_ctx->get_tablet_id().id(); + dml_stat->insert_row_count_ = tablet_ctx->get_row_count(); + } + } + return ret; +} + +int ObDirectLoadInsertTableContext::collect_sql_statistics(ObTableLoadSqlStatistics &sql_statistics) +{ + int ret = OB_SUCCESS; + const int64_t column_count = get_sql_stat_column_count(); + sql_statistics.reset(); + if (OB_UNLIKELY(!param_.online_opt_stat_gather_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected no gather sql stat", KR(ret), K(param_)); + } else if (OB_FAIL(sql_statistics.create(column_count))) { + LOG_WARN("fail to create sql stat", KR(ret), K(column_count)); + } else { + const StatLevel stat_level = TABLE_LEVEL; + const int64_t partition_id = !param_.is_partitioned_table_ ? param_.table_id_ : -1; + int64_t table_avg_len = 0; + for (int64_t i = 0; OB_SUCC(ret) && i < column_count; ++i) { + ObOptOSGColumnStat *osg_col_stat = nullptr; + const ObColDesc &col_desc = param_.col_descs_->at(!param_.is_heap_table_ ? i : i + 1); + if (OB_FAIL(sql_statistics.get_col_stat(i, osg_col_stat))) { + LOG_WARN("fail to get col stat", KR(ret), K(i)); + } + FOREACH_X(iter, sql_stat_map_, OB_SUCC(ret)) { + const int64_t part_id = iter->first; + ObTableLoadSqlStatistics *part_sql_statistics = iter->second; + ObOptOSGColumnStat *part_osg_col_stat = nullptr; + if (OB_ISNULL(part_sql_statistics)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected sql stat is null", KR(ret), K(part_id)); + } else if (OB_FAIL(part_sql_statistics->get_col_stat(i, part_osg_col_stat))) { + LOG_WARN("fail to get col stat", KR(ret), K(i)); + } else if (OB_FAIL(osg_col_stat->merge_column_stat(*part_osg_col_stat))) { + LOG_WARN("fail to merge column stat", KR(ret)); + } + } + if (OB_SUCC(ret)) { + osg_col_stat->col_stat_->calc_avg_len(); + osg_col_stat->col_stat_->set_table_id(param_.table_id_); + osg_col_stat->col_stat_->set_partition_id(partition_id); + osg_col_stat->col_stat_->set_stat_level(stat_level); + osg_col_stat->col_stat_->set_column_id(col_desc.col_id_); + osg_col_stat->col_stat_->set_num_distinct( + ObGlobalNdvEval::get_ndv_from_llc(osg_col_stat->col_stat_->get_llc_bitmap())); + if (OB_FAIL(osg_col_stat->set_min_max_datum_to_obj())) { + LOG_WARN("failed to set min max datum to obj", K(ret)); + } else { + table_avg_len += osg_col_stat->col_stat_->get_avg_len(); + } + } + } + if (OB_SUCC(ret)) { + ObOptTableStat *table_stat = nullptr; + if (OB_FAIL(sql_statistics.get_table_stat(0, table_stat))) { + LOG_WARN("fail to get table stat", KR(ret)); + } else { + int64_t row_count = 0; + FOREACH(iter, tablet_ctx_map_) + { + ObDirectLoadInsertTabletContext *tablet_ctx = iter->second; + row_count += tablet_ctx->get_row_count(); + } + table_stat->set_table_id(param_.table_id_); + table_stat->set_partition_id(partition_id); + table_stat->set_object_type(stat_level); + table_stat->set_row_count(row_count); + table_stat->set_avg_row_size(table_avg_len); + } + } + } + return ret; +} + } // namespace storage } // namespace oceanbase diff --git a/src/storage/direct_load/ob_direct_load_insert_table_ctx.h b/src/storage/direct_load/ob_direct_load_insert_table_ctx.h index 63e7b36a0..aa2cb035f 100644 --- a/src/storage/direct_load/ob_direct_load_insert_table_ctx.h +++ b/src/storage/direct_load/ob_direct_load_insert_table_ctx.h @@ -16,67 +16,90 @@ #include "share/ob_ls_id.h" #include "share/ob_tablet_autoincrement_param.h" #include "share/table/ob_table_load_define.h" -#include "storage/blocksstable/ob_block_sstable_struct.h" -#include "storage/access/ob_store_row_iterator.h" -#include "storage/ddl/ob_direct_insert_sstable_ctx_new.h" #include "sql/engine/px/ob_sub_trans_ctrl.h" +#include "storage/access/ob_store_row_iterator.h" +#include "storage/blocksstable/ob_block_sstable_struct.h" +#include "storage/ddl/ob_direct_insert_sstable_ctx_new.h" namespace oceanbase { -namespace sql +namespace table { -class ObDDLCtrl; -} - +class ObTableLoadDmlStat; +class ObTableLoadSqlStatistics; +} // namespace table namespace storage { -struct ObDirectLoadInsertTableRowIteratorParam; +class ObDirectLoadInsertTableContext; + +struct ObDirectLoadTransParam +{ +public: + ObDirectLoadTransParam() : tx_desc_(nullptr) {} + ~ObDirectLoadTransParam() {} + void reset() + { + tx_desc_ = nullptr; + tx_id_.reset(); + tx_seq_.reset(); + } + bool is_valid() const { return nullptr != tx_desc_ && tx_id_.is_valid() && tx_seq_.is_valid(); } + TO_STRING_KV(KPC_(tx_desc), K_(tx_id), K_(tx_seq)); + +public: + transaction::ObTxDesc *tx_desc_; + transaction::ObTransID tx_id_; + transaction::ObTxSEQ tx_seq_; +}; + struct ObDirectLoadInsertTableParam { public: ObDirectLoadInsertTableParam(); ~ObDirectLoadInsertTableParam(); - int assign(const ObDirectLoadInsertTableParam &other); bool is_valid() const; - TO_STRING_KV(K_(table_id), K_(schema_version), K_(snapshot_version), K_(execution_id), - K_(ddl_task_id), K_(data_version), K_(reserved_parallel), K_(ls_partition_ids), - K_(target_ls_partition_ids)); + TO_STRING_KV(K_(table_id), + K_(lob_meta_tid), + K_(schema_version), + K_(snapshot_version), + K_(ddl_task_id), + K_(data_version), + K_(parallel), + K_(reserved_parallel), + K_(rowkey_column_count), + K_(column_count), + K_(lob_column_count), + K_(is_partitioned_table), + K_(is_heap_table), + K_(is_column_store), + K_(online_opt_stat_gather), + K_(is_incremental), + K_(trans_param), + KP_(datum_utils), + KP_(col_descs), + KP_(cmp_funcs)); public: - uint64_t table_id_; + uint64_t table_id_; // dest_table_id + uint64_t lob_meta_tid_; // dest_table_lob_meta_tid int64_t schema_version_; int64_t snapshot_version_; - int64_t execution_id_; int64_t ddl_task_id_; int64_t data_version_; + int64_t parallel_; int64_t reserved_parallel_; - common::ObArray ls_partition_ids_; - common::ObArray target_ls_partition_ids_; -}; - -struct ObDirectLoadInsertTabletParam -{ -public: - ObDirectLoadInsertTabletParam(); - ~ObDirectLoadInsertTabletParam(); - bool is_valid() const; - TO_STRING_KV(K_(tenant_id), K_(table_id), K_(ls_id), K_(table_id), K_(origin_tablet_id), K_(tablet_id), - K_(lob_tablet_id), K_(schema_version), K_(snapshot_version), K_(execution_id), K_(ddl_task_id), - K_(data_version), K_(reserved_parallel), K_(context_id)); -public: - uint64_t tenant_id_; - uint64_t table_id_; - share::ObLSID ls_id_; - common::ObTabletID tablet_id_; - common::ObTabletID lob_tablet_id_; - common::ObTabletID origin_tablet_id_; - int64_t schema_version_; - int64_t snapshot_version_; - int64_t execution_id_; - int64_t ddl_task_id_; - int64_t data_version_; - int64_t reserved_parallel_; - int64_t context_id_; + int64_t rowkey_column_count_; + int64_t column_count_; // 不包含多版本列 + int64_t lob_column_count_; + bool is_partitioned_table_; + bool is_heap_table_; + bool is_column_store_; + bool online_opt_stat_gather_; + bool is_incremental_; + ObDirectLoadTransParam trans_param_; + const blocksstable::ObStorageDatumUtils *datum_utils_; + const common::ObIArray *col_descs_; + const blocksstable::ObStoreCmpFuncs *cmp_funcs_; }; struct ObDirectLoadInsertTabletWriteCtx @@ -93,34 +116,95 @@ class ObDirectLoadInsertTabletContext public: ObDirectLoadInsertTabletContext(); ~ObDirectLoadInsertTabletContext(); - bool is_open() const { return is_open_; } - const common::ObTabletID &get_tablet_id() const { return param_.tablet_id_; } + OB_INLINE bool is_valid() const { return is_inited_; } + + OB_INLINE const share::ObLSID &get_ls_id() const { return ls_id_; } + OB_INLINE const common::ObTabletID &get_origin_tablet_id() const { return origin_tablet_id_; } + OB_INLINE const common::ObTabletID &get_tablet_id() const { return tablet_id_; } + OB_INLINE const common::ObTabletID &get_lob_tablet_id() const { return lob_tablet_id_; } + + OB_INLINE ObDirectLoadInsertTableContext *get_table_ctx() { return table_ctx_; } + OB_INLINE const ObDirectLoadInsertTableParam *get_param() const { return param_; } + +#define DEFINE_INSERT_TABLE_PARAM_GETTER(type, name, def) \ + OB_INLINE type get_##name() const { return nullptr != param_ ? param_->name##_ : def; } + + DEFINE_INSERT_TABLE_PARAM_GETTER(uint64_t, table_id, OB_INVALID_ID); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, schema_version, OB_INVALID_VERSION); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, snapshot_version, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, ddl_task_id, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, data_version, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, parallel, 0) + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, reserved_parallel, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, rowkey_column_count, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, column_count, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(int64_t, lob_column_count, 0); + DEFINE_INSERT_TABLE_PARAM_GETTER(bool, is_partitioned_table, false); + DEFINE_INSERT_TABLE_PARAM_GETTER(bool, is_heap_table, false); + DEFINE_INSERT_TABLE_PARAM_GETTER(bool, is_column_store, false); + DEFINE_INSERT_TABLE_PARAM_GETTER(bool, online_opt_stat_gather, false); + DEFINE_INSERT_TABLE_PARAM_GETTER(bool, is_incremental, false); + // ObDirectLoadTransParam trans_param_; + DEFINE_INSERT_TABLE_PARAM_GETTER(const blocksstable::ObStorageDatumUtils *, datum_utils, nullptr); + DEFINE_INSERT_TABLE_PARAM_GETTER(const common::ObIArray *, col_descs, nullptr); + DEFINE_INSERT_TABLE_PARAM_GETTER(const blocksstable::ObStoreCmpFuncs *, cmp_funcs, nullptr); + +#undef DEFINE_INSERT_TABLE_PARAM_GETTER + + OB_INLINE bool has_lob_storage() const { return get_lob_column_count() > 0; } + OB_INLINE bool need_rescan() const { return nullptr != param_ ? (!param_->is_incremental_ && param_->is_column_store_) : false; } + public: - int init(const ObDirectLoadInsertTabletParam ¶m); + int init(ObDirectLoadInsertTableContext *table_ctx, + const share::ObLSID &ls_id, + const common::ObTabletID &origin_tablet_id, + const common::ObTabletID &tablet_id); int open(); int close(); + int cancel(); + int get_write_ctx(ObDirectLoadInsertTabletWriteCtx &write_ctx); + int get_lob_write_ctx(ObDirectLoadInsertTabletWriteCtx &write_ctx); + int init_datum_row(blocksstable::ObDatumRow &datum_row); int open_sstable_slice(const blocksstable::ObMacroDataSeq &start_seq, int64_t &slice_id); int close_sstable_slice(const int64_t slice_id); int fill_sstable_slice(const int64_t &slice_id, ObIStoreRowIterator &iter, int64_t &affected_rows); - int get_write_ctx(ObDirectLoadInsertTabletWriteCtx &write_ctx); int open_lob_sstable_slice(const blocksstable::ObMacroDataSeq &start_seq, int64_t &slice_id); int close_lob_sstable_slice(const int64_t slice_id); - int fill_lob_sstable_slice(ObIAllocator &allocator, const int64_t &lob_slice_id, share::ObTabletCacheInterval &pk_interval, + int fill_lob_sstable_slice(ObIAllocator &allocator, const int64_t &lob_slice_id, + share::ObTabletCacheInterval &pk_interval, blocksstable::ObDatumRow &datum_row); - - int get_lob_write_ctx(ObDirectLoadInsertTabletWriteCtx &write_ctx); int calc_range(const int64_t thread_cnt); int fill_column_group(const int64_t thread_cnt, const int64_t thread_id); - int cancel(); - TO_STRING_KV(K_(param), K_(is_open)); + + void inc_row_count(const int64_t row_count) { ATOMIC_AAF(&row_count_, row_count); } + int64_t get_row_count() const { return ATOMIC_LOAD(&row_count_); } + + TO_STRING_KV(KPC_(table_ctx), + KP_(param), + K_(context_id), + K_(ls_id), + K_(origin_tablet_id), + K_(tablet_id), + K_(lob_tablet_id), + K_(start_scn), + K_(handle), + K_(row_count), + K_(is_open), + K_(is_cancel)); private: int get_pk_interval(uint64_t count, share::ObTabletCacheInterval &pk_interval); int get_lob_pk_interval(uint64_t count, share::ObTabletCacheInterval &pk_interval); int refresh_pk_cache(const common::ObTabletID &tablet_id, share::ObTabletCacheInterval &pk_cache); + int check_lob_meta_empty(); private: - ObDirectLoadInsertTabletParam param_; - volatile bool is_open_; + ObDirectLoadInsertTableContext *table_ctx_; + const ObDirectLoadInsertTableParam *param_; + int64_t context_id_; + share::ObLSID ls_id_; + common::ObTabletID origin_tablet_id_; + common::ObTabletID tablet_id_; + common::ObTabletID lob_tablet_id_; lib::ObMutex mutex_; blocksstable::ObMacroDataSeq start_seq_; blocksstable::ObMacroDataSeq lob_start_seq_; @@ -128,6 +212,11 @@ private: share::ObTabletCacheInterval lob_pk_cache_; share::SCN start_scn_; ObTabletDirectLoadMgrHandle handle_; + int64_t row_count_; + int open_err_; + volatile bool is_open_; + bool is_create_; + bool is_cancel_; bool is_inited_; }; @@ -136,21 +225,44 @@ class ObDirectLoadInsertTableContext private: typedef common::hash::ObHashMap TABLET_CTX_MAP; + typedef common::hash::ObHashMap SQL_STAT_MAP; public: ObDirectLoadInsertTableContext(); ~ObDirectLoadInsertTableContext(); void destory(); - int init(const ObDirectLoadInsertTableParam ¶m); + int init(const ObDirectLoadInsertTableParam ¶m, + const common::ObIArray &ls_partition_ids, + const common::ObIArray &target_ls_partition_ids); int get_tablet_context(const common::ObTabletID &tablet_id, ObDirectLoadInsertTabletContext *&tablet_ctx) const; + int commit(table::ObTableLoadDmlStat &dml_stats, + table::ObTableLoadSqlStatistics &sql_statistics); void cancel(); - TO_STRING_KV(K_(param)); + + OB_INLINE bool is_valid() const { return is_inited_; } + OB_INLINE ObDirectLoadInsertTableParam &get_param() { return param_; } + OB_INLINE int64_t get_context_id() const { return ddl_ctrl_.context_id_; } + + OB_INLINE bool need_rescan() const { return (!param_.is_incremental_ && param_.is_column_store_); } + + int64_t get_sql_stat_column_count() const; + int get_sql_statistics(table::ObTableLoadSqlStatistics *&sql_statistics); + int update_sql_statistics(table::ObTableLoadSqlStatistics &sql_statistics, + const blocksstable::ObDatumRow &datum_row); + + TO_STRING_KV(K_(param), K_(ddl_ctrl)); private: - int create_all_tablet_contexts(); + int create_all_tablet_contexts( + const common::ObIArray &ls_partition_ids, + const common::ObIArray &target_ls_partition_ids); + int collect_dml_stat(table::ObTableLoadDmlStat &dml_stats); + int collect_sql_statistics(table::ObTableLoadSqlStatistics &sql_statistics); private: - ObDirectLoadInsertTableParam param_; - TABLET_CTX_MAP tablet_ctx_map_; common::ObArenaAllocator allocator_; + common::ObSafeArenaAllocator safe_allocator_; + ObDirectLoadInsertTableParam param_; + TABLET_CTX_MAP tablet_ctx_map_; // origin_tablet_id => tablet_ctx + SQL_STAT_MAP sql_stat_map_; sql::ObDDLCtrl ddl_ctrl_; bool is_inited_; }; diff --git a/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.cpp b/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.cpp index 7983443b2..466013ac1 100644 --- a/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.cpp +++ b/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.cpp @@ -13,6 +13,7 @@ #define USING_LOG_PREFIX STORAGE #include "storage/direct_load/ob_direct_load_insert_table_row_iterator.h" +#include "storage/direct_load/ob_direct_load_lob_builder.h" namespace oceanbase { @@ -20,130 +21,73 @@ namespace storage { using namespace common; using namespace blocksstable; - -/** - * ObDirectLoadInsertTableRowIteratorParam - */ - -ObDirectLoadInsertTableRowIteratorParam::ObDirectLoadInsertTableRowIteratorParam() - : lob_column_cnt_(0), - datum_utils_(nullptr), - col_descs_(nullptr), - cmp_funcs_(nullptr), - column_stat_array_(nullptr), - lob_builder_(nullptr), - is_heap_table_(false), - online_opt_stat_gather_(false), - px_mode_(false) -{ -} - -ObDirectLoadInsertTableRowIteratorParam::~ObDirectLoadInsertTableRowIteratorParam() -{ -} +using namespace table; /** * ObDirectLoadInsertTableRowIterator */ ObDirectLoadInsertTableRowIterator::ObDirectLoadInsertTableRowIterator() -: lob_allocator_(ObModIds::OB_LOB_ACCESS_BUFFER, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()) + : insert_tablet_ctx_(nullptr), + sql_statistics_(nullptr), + lob_builder_(nullptr), + lob_allocator_(ObModIds::OB_LOB_ACCESS_BUFFER, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()), + is_inited_(false) { } -ObDirectLoadInsertTableRowIterator::~ObDirectLoadInsertTableRowIterator() -{ -} +ObDirectLoadInsertTableRowIterator::~ObDirectLoadInsertTableRowIterator() {} int ObDirectLoadInsertTableRowIterator::inner_init( - const ObDirectLoadInsertTableRowIteratorParam ¶m) + ObDirectLoadInsertTabletContext *insert_tablet_ctx, + ObTableLoadSqlStatistics *sql_statistics, + ObDirectLoadLobBuilder &lob_builder) { int ret = OB_SUCCESS; - param_ = param; - return ret; -} - -int ObDirectLoadInsertTableRowIterator::get_next_row(const blocksstable::ObDatumRow *&result_row) -{ - int ret = OB_SUCCESS; - ObDatumRow *datum_row = nullptr; - if (OB_FAIL(inner_get_next_row(datum_row))) { - if (OB_UNLIKELY(OB_ITER_END != ret)) { - LOG_WARN("fail to do inner get next row", KR(ret)); - } - } - if (OB_SUCC(ret)) { - if (param_.online_opt_stat_gather_ && OB_FAIL(collect_obj(*datum_row))) { - LOG_WARN("fail to collect obj", KR(ret)); - } - } - if (OB_SUCC(ret) && param_.lob_column_cnt_ > 0) { - lob_allocator_.reuse(); - if (OB_FAIL(handle_lob(*datum_row))) { - LOG_WARN("fail to handle lob", KR(ret)); - } - } - if (OB_SUCC(ret)) { - result_row = datum_row; - } - return ret; -} - -int ObDirectLoadInsertTableRowIterator::collect_obj(const blocksstable::ObDatumRow &datum_row) -{ - int ret = OB_SUCCESS; - const int64_t extra_rowkey_cnt = ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); - if (param_.is_heap_table_) { - for (int64_t i = 0; OB_SUCC(ret) && i < param_.table_data_desc_.column_count_; i++) { - const ObStorageDatum &datum = datum_row.storage_datums_[i + extra_rowkey_cnt + 1]; - const common::ObCmpFunc &cmp_func = param_.cmp_funcs_->at(i + 1).get_cmp_func(); - const ObColDesc &col_desc = param_.col_descs_->at(i + 1); - ObOptOSGColumnStat *col_stat = param_.column_stat_array_->at(i); - bool is_valid = ObColumnStatParam::is_valid_opt_col_type(col_desc.col_type_.get_type()); - if (col_stat != nullptr && is_valid) { - if (OB_FAIL( - col_stat->update_column_stat_info(&datum, col_desc.col_type_, cmp_func.cmp_func_))) { - LOG_WARN("Failed to merge obj", K(ret), KP(col_stat)); - } - } - } + if (OB_UNLIKELY(nullptr == insert_tablet_ctx || !insert_tablet_ctx->is_valid() || + (insert_tablet_ctx->get_online_opt_stat_gather() && nullptr == sql_statistics))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid args", KR(ret), KPC(insert_tablet_ctx), KP(sql_statistics)); } else { - for (int64_t i = 0; OB_SUCC(ret) && i < param_.table_data_desc_.rowkey_column_num_; i++) { - const ObStorageDatum &datum = datum_row.storage_datums_[i]; - const common::ObCmpFunc &cmp_func = param_.cmp_funcs_->at(i).get_cmp_func(); - const ObColDesc &col_desc = param_.col_descs_->at(i); - ObOptOSGColumnStat *col_stat = param_.column_stat_array_->at(i); - bool is_valid = ObColumnStatParam::is_valid_opt_col_type(col_desc.col_type_.get_type()); - if (col_stat != nullptr && is_valid) { - if (OB_FAIL( - col_stat->update_column_stat_info(&datum, col_desc.col_type_, cmp_func.cmp_func_))) { - LOG_WARN("Failed to merge obj", K(ret), KP(col_stat)); - } - } - } - for (int64_t i = param_.table_data_desc_.rowkey_column_num_; - OB_SUCC(ret) && i < param_.table_data_desc_.column_count_; i++) { - const ObStorageDatum &datum = datum_row.storage_datums_[i + extra_rowkey_cnt]; - const common::ObCmpFunc &cmp_func = param_.cmp_funcs_->at(i).get_cmp_func(); - const ObColDesc &col_desc = param_.col_descs_->at(i); - ObOptOSGColumnStat *col_stat = param_.column_stat_array_->at(i); - bool is_valid = ObColumnStatParam::is_valid_opt_col_type(col_desc.col_type_.get_type()); - if (col_stat != nullptr && is_valid) { - if (OB_FAIL( - col_stat->update_column_stat_info(&datum, col_desc.col_type_, cmp_func.cmp_func_))) { - LOG_WARN("Failed to merge obj", K(ret), KP(col_stat)); - } + insert_tablet_ctx_ = insert_tablet_ctx; + sql_statistics_ = sql_statistics; + lob_builder_ = &lob_builder; + } + return ret; +} + +int ObDirectLoadInsertTableRowIterator::get_next_row(const ObDatumRow *&result_row) +{ + int ret = OB_SUCCESS; + result_row = nullptr; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + LOG_WARN("ObDirectLoadInsertTableRowIterator not init", KR(ret), KP(this)); + } else { + ObDatumRow *datum_row = nullptr; + if (OB_FAIL(inner_get_next_row(datum_row))) { + if (OB_UNLIKELY(OB_ITER_END != ret)) { + LOG_WARN("fail to do inner get next row", KR(ret)); } + } else if (insert_tablet_ctx_->get_online_opt_stat_gather() && + OB_FAIL(insert_tablet_ctx_->get_table_ctx()->update_sql_statistics(*sql_statistics_, + *datum_row))) { + LOG_WARN("fail to update sql statistics", KR(ret)); + } else if (insert_tablet_ctx_->has_lob_storage() && OB_FAIL(handle_lob(*datum_row))) { + LOG_WARN("fail to handle lob", KR(ret)); + } else { + result_row = datum_row; } } return ret; } -int ObDirectLoadInsertTableRowIterator::handle_lob(blocksstable::ObDatumRow &datum_row) +int ObDirectLoadInsertTableRowIterator::handle_lob(ObDatumRow &datum_row) { int ret = OB_SUCCESS; - if (OB_FAIL(param_.lob_builder_->append_lob(lob_allocator_, datum_row))) { - LOG_WARN("fail to append lob", KR(ret), K(param_.tablet_id_), K(datum_row)); + lob_allocator_.reuse(); + if (OB_FAIL(lob_builder_->append_lob(lob_allocator_, datum_row))) { + LOG_WARN("fail to append lob", KR(ret), K(datum_row)); } return ret; } diff --git a/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.h b/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.h index 31def1d3c..7a0b8cbc0 100644 --- a/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.h +++ b/src/storage/direct_load/ob_direct_load_insert_table_row_iterator.h @@ -12,38 +12,18 @@ #pragma once -#include "share/stat/ob_opt_osg_column_stat.h" -#include "storage/direct_load/ob_direct_load_lob_builder.h" -#include "storage/direct_load/ob_direct_load_merge_ctx.h" -#include "storage/direct_load/ob_direct_load_table_data_desc.h" +#include "storage/access/ob_store_row_iterator.h" namespace oceanbase { -namespace blocksstable +namespace table { -class ObIStoreRowIterator; -} // namespace blocksstable +class ObTableLoadSqlStatistics; +} // namespace table namespace storage { -struct ObDirectLoadInsertTableRowIteratorParam -{ -public: - ObDirectLoadInsertTableRowIteratorParam(); - ~ObDirectLoadInsertTableRowIteratorParam(); - TO_STRING_KV(K_(tablet_id), K_(table_data_desc), K_(is_heap_table), K_(online_opt_stat_gather), K_(px_mode)); -public: - ObTabletID tablet_id_; - ObDirectLoadTableDataDesc table_data_desc_; - int64_t lob_column_cnt_; - const blocksstable::ObStorageDatumUtils *datum_utils_; - const common::ObIArray *col_descs_; - const blocksstable::ObStoreCmpFuncs *cmp_funcs_; - common::ObIArray *column_stat_array_; - ObDirectLoadLobBuilder *lob_builder_; - bool is_heap_table_; - bool online_opt_stat_gather_; - bool px_mode_; -}; +class ObDirectLoadInsertTabletContext; +class ObDirectLoadLobBuilder; class ObDirectLoadInsertTableRowIterator : public ObIStoreRowIterator { @@ -51,15 +31,19 @@ public: ObDirectLoadInsertTableRowIterator(); virtual ~ObDirectLoadInsertTableRowIterator(); int get_next_row(const blocksstable::ObDatumRow *&datum_row) override; -private: - int collect_obj(const blocksstable::ObDatumRow &datum_row); - int handle_lob(blocksstable::ObDatumRow &datum_row); protected: - int inner_init(const ObDirectLoadInsertTableRowIteratorParam ¶m); + int inner_init(ObDirectLoadInsertTabletContext *insert_tablet_ctx, + table::ObTableLoadSqlStatistics *sql_statistics, + ObDirectLoadLobBuilder &lob_builder); virtual int inner_get_next_row(blocksstable::ObDatumRow *&datum_row) = 0; private: - ObDirectLoadInsertTableRowIteratorParam param_; + int handle_lob(blocksstable::ObDatumRow &datum_row); +protected: + ObDirectLoadInsertTabletContext *insert_tablet_ctx_; + table::ObTableLoadSqlStatistics *sql_statistics_; + ObDirectLoadLobBuilder *lob_builder_; common::ObArenaAllocator lob_allocator_; + bool is_inited_; }; } // namespace storage diff --git a/src/storage/direct_load/ob_direct_load_lob_builder.cpp b/src/storage/direct_load/ob_direct_load_lob_builder.cpp index 2c32427d7..787076152 100644 --- a/src/storage/direct_load/ob_direct_load_lob_builder.cpp +++ b/src/storage/direct_load/ob_direct_load_lob_builder.cpp @@ -13,7 +13,6 @@ #define USING_LOG_PREFIX STORAGE #include "storage/direct_load/ob_direct_load_lob_builder.h" -#include "share/stat/ob_stat_define.h" #include "share/table/ob_table_load_define.h" #include "storage/direct_load/ob_direct_load_insert_table_ctx.h" @@ -25,58 +24,39 @@ using namespace common; using namespace blocksstable; using namespace share; -/** - * ObDirectLoadLobBuildParam - */ - -ObDirectLoadLobBuildParam::ObDirectLoadLobBuildParam() - : insert_table_ctx_(nullptr), lob_column_cnt_(0) -{ -} - -ObDirectLoadLobBuildParam::~ObDirectLoadLobBuildParam() -{ -} - -bool ObDirectLoadLobBuildParam::is_valid() const -{ - return tablet_id_.is_valid() && nullptr != insert_table_ctx_; -} - /** * ObDirectLoadLobBuilder */ ObDirectLoadLobBuilder::ObDirectLoadLobBuilder() : insert_tablet_ctx_(nullptr), + lob_column_count_(0), current_lob_slice_id_(0), is_closed_(false), is_inited_(false) { } -ObDirectLoadLobBuilder::~ObDirectLoadLobBuilder() -{ -} +ObDirectLoadLobBuilder::~ObDirectLoadLobBuilder() {} -int ObDirectLoadLobBuilder::init(const ObDirectLoadLobBuildParam ¶m) +int ObDirectLoadLobBuilder::init(ObDirectLoadInsertTabletContext *insert_tablet_ctx) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("ObDirectLoadLobBuilder init twice", KR(ret), KP(this)); - } else if (OB_UNLIKELY(!param.is_valid())) { + } else if (OB_UNLIKELY(nullptr == insert_tablet_ctx || !insert_tablet_ctx->is_valid())) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), K(param)); + LOG_WARN("invalid args", KR(ret), KPC(insert_tablet_ctx)); + } else if (OB_UNLIKELY(!insert_tablet_ctx->has_lob_storage())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected has no lob", KR(ret), KPC(insert_tablet_ctx)); } else { - param_ = param; - if (OB_FAIL(param_.insert_table_ctx_->get_tablet_context( - param_.tablet_id_, insert_tablet_ctx_))) { - LOG_WARN("fail to get tablet context", KR(ret)); - } else if (OB_FAIL(init_sstable_slice_ctx())) { + insert_tablet_ctx_ = insert_tablet_ctx; + lob_column_count_ = insert_tablet_ctx->get_lob_column_count(); + if (OB_FAIL(init_sstable_slice_ctx())) { LOG_WARN("fail to init sstable slice ctx", KR(ret)); } else { - lob_tablet_id_ = insert_tablet_ctx_->get_tablet_id(); is_inited_ = true; } } @@ -88,9 +68,8 @@ int ObDirectLoadLobBuilder::init_sstable_slice_ctx() int ret = OB_SUCCESS; if (OB_FAIL(insert_tablet_ctx_->get_lob_write_ctx(write_ctx_))) { LOG_WARN("fail to get write ctx", KR(ret)); - } else if (OB_FAIL(insert_tablet_ctx_->open_lob_sstable_slice( - write_ctx_.start_seq_, - current_lob_slice_id_))) { + } else if (OB_FAIL(insert_tablet_ctx_->open_lob_sstable_slice(write_ctx_.start_seq_, + current_lob_slice_id_))) { LOG_WARN("fail to construct sstable slice", KR(ret)); } return ret; @@ -101,7 +80,7 @@ int ObDirectLoadLobBuilder::switch_sstable_slice() int ret = OB_SUCCESS; if (OB_FAIL(insert_tablet_ctx_->close_lob_sstable_slice(current_lob_slice_id_))) { LOG_WARN("fail to close sstable slice builder", KR(ret)); - } else if (OB_FAIL(init_sstable_slice_ctx())) { + } else if (OB_FAIL(init_sstable_slice_ctx())) { LOG_WARN("fail to init sstable slice ctx", KR(ret)); } return ret; @@ -117,15 +96,16 @@ int ObDirectLoadLobBuilder::append_lob(ObIAllocator &allocator, blocksstable::Ob ret = OB_ERR_UNEXPECTED; LOG_WARN("lob builder is closed", KR(ret)); } else { - if (write_ctx_.pk_interval_.remain_count() < param_.lob_column_cnt_) { - if (OB_FAIL(switch_sstable_slice())) { + if (write_ctx_.pk_interval_.remain_count() < lob_column_count_) { + if (OB_FAIL(switch_sstable_slice())) { LOG_WARN("fail to switch sstable slice", KR(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(insert_tablet_ctx_->fill_lob_sstable_slice(allocator, current_lob_slice_id_, - write_ctx_.pk_interval_, datum_row))) { - LOG_WARN("fill lob sstable slice failed", K(ret), KP(insert_tablet_ctx_), K(current_lob_slice_id_), K(write_ctx_.pk_interval_), K(datum_row)); + write_ctx_.pk_interval_, datum_row))) { + LOG_WARN("fill lob sstable slice failed", K(ret), KP(insert_tablet_ctx_), + K(current_lob_slice_id_), K(write_ctx_.pk_interval_), K(datum_row)); } } } diff --git a/src/storage/direct_load/ob_direct_load_lob_builder.h b/src/storage/direct_load/ob_direct_load_lob_builder.h index 012b1fc31..c7546cda5 100644 --- a/src/storage/direct_load/ob_direct_load_lob_builder.h +++ b/src/storage/direct_load/ob_direct_load_lob_builder.h @@ -12,50 +12,27 @@ #pragma once -#include "common/ob_tablet_id.h" -#include "storage/direct_load/ob_direct_load_i_table.h" -#include "storage/direct_load/ob_direct_load_table_data_desc.h" #include "storage/direct_load/ob_direct_load_insert_table_ctx.h" namespace oceanbase { -namespace table -{ -} // namespace table -namespace common -{ -} // namespace common namespace storage { -struct ObDirectLoadLobBuildParam -{ -public: - ObDirectLoadLobBuildParam(); - ~ObDirectLoadLobBuildParam(); - bool is_valid() const; - TO_STRING_KV(K_(tablet_id)); -public: - common::ObTabletID tablet_id_; - ObDirectLoadInsertTableContext *insert_table_ctx_; - int64_t lob_column_cnt_; -}; - class ObDirectLoadLobBuilder { public: ObDirectLoadLobBuilder(); ~ObDirectLoadLobBuilder(); - int init(const ObDirectLoadLobBuildParam ¶m); + int init(ObDirectLoadInsertTabletContext *insert_tablet_ctx); int append_lob(common::ObIAllocator &allocator, blocksstable::ObDatumRow &datum_row); - int close(); + int close(); private: int init_sstable_slice_ctx(); int switch_sstable_slice(); private: - ObDirectLoadLobBuildParam param_; - common::ObTabletID lob_tablet_id_; ObDirectLoadInsertTabletContext *insert_tablet_ctx_; + int64_t lob_column_count_; ObDirectLoadInsertTabletWriteCtx write_ctx_; int64_t current_lob_slice_id_; bool is_closed_; diff --git a/src/storage/direct_load/ob_direct_load_merge_ctx.cpp b/src/storage/direct_load/ob_direct_load_merge_ctx.cpp index f7af0ba19..40143bfee 100644 --- a/src/storage/direct_load/ob_direct_load_merge_ctx.cpp +++ b/src/storage/direct_load/ob_direct_load_merge_ctx.cpp @@ -22,11 +22,6 @@ #include "storage/direct_load/ob_direct_load_range_splitter.h" #include "storage/direct_load/ob_direct_load_partition_rescan_task.h" #include "observer/table_load/ob_table_load_schema.h" -#include "share/stat/ob_opt_table_stat.h" -#include "share/stat/ob_opt_stat_monitor_manager.h" -#include "share/stat/ob_opt_stat_manager.h" -#include "share/stat/ob_opt_column_stat.h" -#include "share/stat/ob_stat_item.h" namespace oceanbase { @@ -48,17 +43,12 @@ ObDirectLoadMergeParam::ObDirectLoadMergeParam() target_table_id_(OB_INVALID_ID), rowkey_column_num_(0), store_column_count_(0), - snapshot_version_(0), - lob_column_cnt_(0), fill_cg_thread_cnt_(0), datum_utils_(nullptr), col_descs_(nullptr), - cmp_funcs_(nullptr), is_heap_table_(false), is_fast_heap_table_(false), - is_column_store_(false), - online_opt_stat_gather_(false), - px_mode_(false), + is_incremental_(false), insert_mode_(ObDirectLoadInsertMode::INVALID_INSERT_MODE), insert_table_ctx_(nullptr), dml_row_handler_(nullptr) @@ -71,10 +61,12 @@ ObDirectLoadMergeParam::~ObDirectLoadMergeParam() bool ObDirectLoadMergeParam::is_valid() const { - return OB_INVALID_ID != table_id_ && 0 < rowkey_column_num_ && 0 < store_column_count_ && - snapshot_version_ > 0 && table_data_desc_.is_valid() && nullptr != datum_utils_ && - nullptr != col_descs_ && nullptr != cmp_funcs_ && + return OB_INVALID_ID != table_id_ && OB_INVALID_ID != target_table_id_ && + 0 < rowkey_column_num_ && 0 < store_column_count_ && table_data_desc_.is_valid() && + nullptr != datum_utils_ && nullptr != col_descs_ && ObDirectLoadInsertMode::is_type_valid(insert_mode_) && + (ObDirectLoadInsertMode::INC_REPLACE == insert_mode_ ? is_incremental_ : true) && + (ObDirectLoadInsertMode::OVERWRITE == insert_mode_ ? !is_incremental_ : true) && nullptr != insert_table_ctx_ && nullptr != dml_row_handler_; } @@ -227,121 +219,6 @@ int ObDirectLoadTabletMergeCtx::init(ObTableLoadTableCtx *ctx, return ret; } -int ObDirectLoadTabletMergeCtx::collect_sql_statistics( - const ObIArray &fast_heap_table_array, ObTableLoadSqlStatistics &sql_statistics) -{ - int ret = OB_SUCCESS; - const uint64_t tenant_id = MTL_ID(); - ObSchemaGetterGuard schema_guard; - const ObTableSchema *table_schema = nullptr; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - LOG_WARN("ObDirectLoadTabletMergeCtx not init", KR(ret), KP(this)); - } else if (OB_FAIL(ObTableLoadSchema::get_table_schema(tenant_id, param_.target_table_id_, schema_guard, - table_schema))) { - LOG_WARN("fail to get table schema", KR(ret), K(param_)); - } else if (OB_ISNULL(table_schema)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected error", K(ret)); - } else { - int64_t table_row_cnt = 0; - int64_t table_avg_len = 0; - int64_t col_cnt = param_.table_data_desc_.column_count_; - ObOptTableStat *table_stat = nullptr; - StatLevel stat_level; - if (table_schema->get_part_level() == PARTITION_LEVEL_ZERO) { - stat_level = TABLE_LEVEL; - } else if (table_schema->get_part_level() == PARTITION_LEVEL_ONE) { - stat_level = PARTITION_LEVEL; - } else if (table_schema->get_part_level() == PARTITION_LEVEL_TWO) { - stat_level = SUBPARTITION_LEVEL; - } else { - stat_level = INVALID_LEVEL; - } - if (OB_FAIL(sql_statistics.allocate_table_stat(table_stat))) { - LOG_WARN("fail to allocate table stat", KR(ret)); - } else { - for (int64_t i = 0; OB_SUCC(ret) && i < col_cnt; ++i) { - int64_t col_id = param_.is_heap_table_ ? i + 1 : i; - int64_t row_count = 0; - ObOptOSGColumnStat *osg_col_stat = nullptr; - if (OB_FAIL(sql_statistics.allocate_col_stat(osg_col_stat))) { - LOG_WARN("fail to allocate table stat", KR(ret)); - } - // scan task_array - for (int64_t j = 0; OB_SUCC(ret) && j < task_array_.count(); ++j) { - ObOptOSGColumnStat *tmp_col_stat = task_array_.at(j)->get_column_stat_array().at(i); - if (task_array_.at(j)->get_row_count() != 0) { - if (OB_FAIL(osg_col_stat->merge_column_stat(*tmp_col_stat))) { - LOG_WARN("fail to merge column stat", KR(ret)); - } else { - row_count += task_array_.at(j)->get_row_count(); - } - } - } - // scan fast heap table - for (int64_t j = 0; OB_SUCC(ret) && j < fast_heap_table_array.count(); ++j) { - ObOptOSGColumnStat *tmp_col_stat = fast_heap_table_array.at(j)->get_column_stat_array().at(i); - if (fast_heap_table_array.at(j)->get_row_count() != 0) { - if (OB_FAIL(osg_col_stat->merge_column_stat(*tmp_col_stat))) { - LOG_WARN("fail to merge column stat", KR(ret)); - } else { - row_count += fast_heap_table_array.at(j)->get_row_count(); - } - } - } - if (OB_SUCC(ret)) { - table_row_cnt = row_count; - osg_col_stat->col_stat_->calc_avg_len(); - table_avg_len += osg_col_stat->col_stat_->get_avg_len(); - osg_col_stat->col_stat_->set_table_id(param_.target_table_id_); - osg_col_stat->col_stat_->set_partition_id(target_partition_id_); - osg_col_stat->col_stat_->set_stat_level(stat_level); - osg_col_stat->col_stat_->set_column_id(param_.col_descs_->at(col_id).col_id_); - osg_col_stat->col_stat_->set_num_distinct(ObGlobalNdvEval::get_ndv_from_llc(osg_col_stat->col_stat_->get_llc_bitmap())); - if (OB_FAIL(osg_col_stat->set_min_max_datum_to_obj())) { - LOG_WARN("failed to set min max datum to obj", K(ret)); - } - } - } - if (OB_SUCC(ret)) { - table_stat->set_table_id(param_.target_table_id_); - table_stat->set_partition_id(target_partition_id_); - table_stat->set_object_type(stat_level); - table_stat->set_row_count(table_row_cnt); - table_stat->set_avg_row_size(table_avg_len); - } - } - } - return ret; -} - -int ObDirectLoadTabletMergeCtx::collect_dml_stat(const common::ObIArray &fast_heap_table_array, ObTableLoadDmlStat &dml_stats) -{ - int ret = OB_SUCCESS; - const uint64_t tenant_id = MTL_ID(); - int64_t insert_row_cnt = 0; - ObOptDmlStat *dml_stat = nullptr; - if (OB_FAIL(dml_stats.allocate_dml_stat(dml_stat))) { - LOG_WARN("fail to allocate table stat", KR(ret)); - } else { - // scan task_array - for (int64_t i = 0; OB_SUCC(ret) && i < task_array_.count(); ++i) { - insert_row_cnt += task_array_.at(i)->get_row_count(); - } - // scan fast heap table - for (int64_t i = 0; OB_SUCC(ret) && i < fast_heap_table_array.count(); ++i) { - insert_row_cnt += fast_heap_table_array.at(i)->get_row_count(); - } - dml_stat->tenant_id_ = tenant_id; - dml_stat->table_id_ = param_.target_table_id_; - dml_stat->tablet_id_ = target_tablet_id_.id(); - dml_stat->insert_row_count_ = insert_row_cnt; - } - return ret; -} - - int ObDirectLoadTabletMergeCtx::init_sstable_array( const ObIArray &table_array) { diff --git a/src/storage/direct_load/ob_direct_load_merge_ctx.h b/src/storage/direct_load/ob_direct_load_merge_ctx.h index 2d8303918..4e9b7e59b 100644 --- a/src/storage/direct_load/ob_direct_load_merge_ctx.h +++ b/src/storage/direct_load/ob_direct_load_merge_ctx.h @@ -14,13 +14,7 @@ #include "lib/allocator/ob_allocator.h" #include "share/ob_tablet_autoincrement_param.h" #include "share/schema/ob_table_param.h" -#include "share/stat/ob_stat_define.h" -#include "share/stat/ob_opt_column_stat.h" -#include "share/stat/ob_opt_osg_column_stat.h" -#include "share/stat/ob_opt_table_stat.h" #include "share/table/ob_table_load_define.h" -#include "share/table/ob_table_load_dml_stat.h" -#include "share/table/ob_table_load_sql_statistics.h" #include "storage/direct_load/ob_direct_load_origin_table.h" #include "storage/direct_load/ob_direct_load_struct.h" #include "storage/direct_load/ob_direct_load_table_data_desc.h" @@ -52,30 +46,32 @@ public: ObDirectLoadMergeParam(); ~ObDirectLoadMergeParam(); bool is_valid() const; - TO_STRING_KV(K_(table_id), K_(target_table_id), K_(rowkey_column_num), K_(store_column_count), - K_(snapshot_version), K_(table_data_desc), KP_(datum_utils), KP_(col_descs), - KP_(lob_column_cnt), KP_(cmp_funcs), K_(is_heap_table), K_(is_fast_heap_table), - K_(is_column_store), K_(online_opt_stat_gather), - "insert_mode", ObDirectLoadInsertMode::get_type_string(insert_mode_), - KP_(insert_table_ctx), - KP_(dml_row_handler)); + TO_STRING_KV(K_(table_id), + K_(target_table_id), + K_(rowkey_column_num), + K_(store_column_count), + K_(fill_cg_thread_cnt), + K_(table_data_desc), + KP_(datum_utils), + KP_(col_descs), + K_(is_heap_table), + K_(is_fast_heap_table), + K_(is_incremental), + "insert_mode", ObDirectLoadInsertMode::get_type_string(insert_mode_), + KP_(insert_table_ctx), + KP_(dml_row_handler)); public: uint64_t table_id_; uint64_t target_table_id_; int64_t rowkey_column_num_; int64_t store_column_count_; - int64_t snapshot_version_; - int64_t lob_column_cnt_; int64_t fill_cg_thread_cnt_; storage::ObDirectLoadTableDataDesc table_data_desc_; const blocksstable::ObStorageDatumUtils *datum_utils_; const common::ObIArray *col_descs_; - const blocksstable::ObStoreCmpFuncs *cmp_funcs_; bool is_heap_table_; bool is_fast_heap_table_; - bool is_column_store_; - bool online_opt_stat_gather_; - bool px_mode_; + bool is_incremental_; ObDirectLoadInsertMode::Type insert_mode_; ObDirectLoadInsertTableContext *insert_table_ctx_; ObDirectLoadDMLRowHandler *dml_row_handler_; @@ -126,10 +122,6 @@ public: const common::ObIArray &table_array); int inc_finish_count(bool &is_ready); int inc_rescan_finish_count(bool &is_ready); - int collect_sql_statistics( - const common::ObIArray &fast_heap_table_array, table::ObTableLoadSqlStatistics &sql_statistics); - int collect_dml_stat(const common::ObIArray &fast_heap_table_array, - table::ObTableLoadDmlStat &dml_stats); const ObDirectLoadMergeParam &get_param() const { return param_; } const common::ObTabletID &get_tablet_id() const { return tablet_id_; } const common::ObTabletID &get_target_tablet_id() const { return target_tablet_id_; } diff --git a/src/storage/direct_load/ob_direct_load_partition_merge_task.cpp b/src/storage/direct_load/ob_direct_load_partition_merge_task.cpp index 80814dea5..606fb3332 100644 --- a/src/storage/direct_load/ob_direct_load_partition_merge_task.cpp +++ b/src/storage/direct_load/ob_direct_load_partition_merge_task.cpp @@ -12,15 +12,12 @@ #define USING_LOG_PREFIX STORAGE #include "storage/direct_load/ob_direct_load_partition_merge_task.h" -#include "share/stat/ob_opt_column_stat.h" -#include "share/stat/ob_stat_define.h" #include "storage/direct_load/ob_direct_load_external_table.h" #include "storage/direct_load/ob_direct_load_insert_table_ctx.h" #include "storage/direct_load/ob_direct_load_merge_ctx.h" #include "storage/direct_load/ob_direct_load_multiple_heap_table.h" #include "storage/direct_load/ob_direct_load_origin_table.h" - namespace oceanbase { namespace storage @@ -28,6 +25,7 @@ namespace storage using namespace common; using namespace blocksstable; using namespace share; +using namespace table; using namespace observer; /** @@ -41,22 +39,16 @@ ObDirectLoadPartitionMergeTask::ObDirectLoadPartitionMergeTask() parallel_idx_(-1), affected_rows_(0), allocator_("TLD_ParMT"), + insert_tablet_ctx_(nullptr), + sql_statistics_(nullptr), is_stop_(false), is_inited_(false) { allocator_.set_tenant_id(MTL_ID()); - column_stat_array_.set_tenant_id(MTL_ID()); } ObDirectLoadPartitionMergeTask::~ObDirectLoadPartitionMergeTask() { - for (int64_t i = 0; i < column_stat_array_.count(); ++i) { - ObOptOSGColumnStat *col_stat = column_stat_array_.at(i); - if (col_stat != nullptr) { - col_stat->~ObOptOSGColumnStat(); - col_stat = nullptr; - } - } } class ObStoreRowIteratorWrapper : public ObIStoreRowIterator @@ -89,37 +81,35 @@ int ObDirectLoadPartitionMergeTask::process() } else { int64_t slice_id = 0; const ObTabletID &tablet_id = merge_ctx_->get_tablet_id(); - ObDirectLoadInsertTabletContext *tablet_ctx = nullptr; ObIStoreRowIterator *row_iter = nullptr; - bool has_lob_storage = merge_param_->lob_column_cnt_ > 0 ? true :false; ObMacroDataSeq block_start_seq; block_start_seq.set_parallel_degree(parallel_idx_); - if (merge_param_->online_opt_stat_gather_ && OB_FAIL(init_sql_statistics())) { - LOG_WARN("fail to inner init sql statistics", KR(ret)); - } else if (has_lob_storage && OB_FAIL(init_lob_builder())) { + if (OB_FAIL( + merge_param_->insert_table_ctx_->get_tablet_context(tablet_id, insert_tablet_ctx_))) { + LOG_WARN("fail to get tablet context ", KR(ret), K(tablet_id), K(block_start_seq)); + } else if (insert_tablet_ctx_->get_online_opt_stat_gather() && + OB_FAIL(merge_param_->insert_table_ctx_->get_sql_statistics(sql_statistics_))) { + LOG_WARN("fail to get sql statistics", KR(ret)); + } else if (insert_tablet_ctx_->has_lob_storage() && OB_FAIL(lob_builder_.init(insert_tablet_ctx_))) { LOG_WARN("fail to inner init lob builder", KR(ret)); } else if (OB_FAIL(construct_row_iter(allocator_, row_iter))) { LOG_WARN("fail to construct row iter", KR(ret)); - } else if (OB_FAIL(merge_param_->insert_table_ctx_->get_tablet_context( - tablet_id, tablet_ctx))) { - LOG_WARN("fail to get tablet context ", KR(ret), K(tablet_id), - K(block_start_seq)); - } else if (OB_FAIL(tablet_ctx->open_sstable_slice( - block_start_seq, slice_id))) { - LOG_WARN("fail to construct sstable slice ", KR(ret), K(slice_id), - K(block_start_seq)); + } else if (OB_FAIL(insert_tablet_ctx_->open_sstable_slice(block_start_seq, slice_id))) { + LOG_WARN("fail to construct sstable slice ", KR(ret), K(slice_id), K(block_start_seq)); } else { - LOG_INFO("add sstable slice begin", KP(tablet_ctx), K(slice_id)); + LOG_INFO("add sstable slice begin", K(tablet_id), K(parallel_idx_), K(slice_id)); ObStoreRowIteratorWrapper row_iter_wrapper(ctx_, row_iter); if (OB_UNLIKELY(is_stop_)) { ret = OB_CANCELED; LOG_WARN("merge task canceled", KR(ret)); - } else if (OB_FAIL(tablet_ctx->fill_sstable_slice(slice_id, row_iter_wrapper, affected_rows_))) { + } else if (OB_FAIL(insert_tablet_ctx_->fill_sstable_slice(slice_id, row_iter_wrapper, affected_rows_))) { LOG_WARN("fail to fill sstable slice", KR(ret)); - } else if (OB_FAIL(tablet_ctx->close_sstable_slice(slice_id))) { + } else if (OB_FAIL(insert_tablet_ctx_->close_sstable_slice(slice_id))) { LOG_WARN("fail to close writer", KR(ret)); - } else if (has_lob_storage && OB_FAIL(lob_builder_.close())) { + } else if (insert_tablet_ctx_->has_lob_storage() && OB_FAIL(lob_builder_.close())) { LOG_WARN("fail to close lob_builder", KR(ret)); + } else { + insert_tablet_ctx_->inc_row_count(affected_rows_); } LOG_INFO("add sstable slice end", KR(ret), K(tablet_id), K(parallel_idx_), K(affected_rows_)); } @@ -133,11 +123,11 @@ int ObDirectLoadPartitionMergeTask::process() if (OB_FAIL(merge_ctx_->inc_finish_count(is_ready))) { LOG_WARN("fail to inc finish count", KR(ret)); } else if (is_ready) { - if (merge_param_->is_column_store_) { - if (OB_FAIL(tablet_ctx->calc_range(merge_param_->fill_cg_thread_cnt_))) { + if (insert_tablet_ctx_->need_rescan()) { + if (OB_FAIL(insert_tablet_ctx_->calc_range(merge_param_->fill_cg_thread_cnt_))) { LOG_WARN("fail to calc range", KR(ret)); } - } else if (OB_FAIL(tablet_ctx->close())) { + } else if (OB_FAIL(insert_tablet_ctx_->close())) { LOG_WARN("fail to close", KR(ret)); } } @@ -146,41 +136,6 @@ int ObDirectLoadPartitionMergeTask::process() return ret; } -int ObDirectLoadPartitionMergeTask::init_sql_statistics() -{ - int ret = OB_SUCCESS; - for (int64_t i = 0; OB_SUCC(ret)&& i < merge_param_->table_data_desc_.column_count_; ++i) { - ObOptOSGColumnStat *col_stat = ObOptOSGColumnStat::create_new_osg_col_stat(allocator_); - if (OB_ISNULL(col_stat)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to allocate buffer", KR(ret)); - } else if (OB_FAIL(column_stat_array_.push_back(col_stat))){ - LOG_WARN("fail to push back", KR(ret)); - } - if (OB_FAIL(ret)) { - if (col_stat != nullptr) { - col_stat->~ObOptOSGColumnStat(); - allocator_.free(col_stat); - col_stat = nullptr; - } - } - } - return ret; -} - -int ObDirectLoadPartitionMergeTask::init_lob_builder() -{ - int ret = OB_SUCCESS; - ObDirectLoadLobBuildParam param; - param.tablet_id_ = merge_ctx_->get_tablet_id(); - param.insert_table_ctx_ = merge_param_->insert_table_ctx_; - param.lob_column_cnt_ = merge_param_->lob_column_cnt_; - if (OB_FAIL(lob_builder_.init(param))) { - LOG_WARN("fail to init lob builder", KR(ret)); - } - return ret; -} - void ObDirectLoadPartitionMergeTask::stop() { int ret = OB_SUCCESS; @@ -190,8 +145,7 @@ void ObDirectLoadPartitionMergeTask::stop() } else { ObDirectLoadInsertTabletContext *tablet_ctx = nullptr; const ObTabletID &tablet_id = merge_ctx_->get_tablet_id(); - if (OB_FAIL(merge_param_->insert_table_ctx_->get_tablet_context( - tablet_id, tablet_ctx))) { + if (OB_FAIL(merge_param_->insert_table_ctx_->get_tablet_context(tablet_id, tablet_ctx))) { LOG_WARN("fail to get tablet context ", KR(ret), K(tablet_id)); } else if (OB_FAIL(tablet_ctx->cancel())) { LOG_WARN("fail to cancel fill task", K(ret)); @@ -199,7 +153,7 @@ void ObDirectLoadPartitionMergeTask::stop() is_stop_ = true; } } - //ignore ret + // ignore ret } /** @@ -207,45 +161,33 @@ void ObDirectLoadPartitionMergeTask::stop() */ ObDirectLoadPartitionRangeMergeTask::RowIterator::RowIterator() - : rowkey_column_num_(0), is_inited_(false) + : rowkey_column_num_(0) { } -ObDirectLoadPartitionRangeMergeTask::RowIterator::~RowIterator() -{ -} +ObDirectLoadPartitionRangeMergeTask::RowIterator::~RowIterator() {} int ObDirectLoadPartitionRangeMergeTask::RowIterator::init( const ObDirectLoadMergeParam &merge_param, const ObTabletID &tablet_id, ObDirectLoadOriginTable *origin_table, - ObIArray &column_stat_array, + ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, const ObIArray &sstable_array, - const ObDatumRange &range) + const ObDatumRange &range, + ObDirectLoadInsertTabletContext *insert_tablet_ctx) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("ObDirectLoadPartitionRangeMergeTask::RowIterator init twice", KR(ret), KP(this)); } else if (OB_UNLIKELY(!merge_param.is_valid() || !tablet_id.is_valid() || - nullptr == origin_table || !range.is_valid())) { + nullptr == origin_table || !range.is_valid() || + nullptr == insert_tablet_ctx)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), K(sstable_array), K(range)); + LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), K(sstable_array), K(range), + KP(insert_tablet_ctx)); } else { - // init row iterator - ObDirectLoadInsertTableRowIteratorParam row_iterator_param; - row_iterator_param.tablet_id_ = tablet_id; - row_iterator_param.table_data_desc_ = merge_param.table_data_desc_; - row_iterator_param.datum_utils_ = merge_param.datum_utils_; - row_iterator_param.col_descs_ = merge_param.col_descs_; - row_iterator_param.lob_column_cnt_ = merge_param.lob_column_cnt_; - row_iterator_param.cmp_funcs_ = merge_param.cmp_funcs_; - row_iterator_param.column_stat_array_ = &column_stat_array; - row_iterator_param.lob_builder_ = &lob_builder; - row_iterator_param.is_heap_table_ = merge_param.is_heap_table_; - row_iterator_param.online_opt_stat_gather_ = merge_param.online_opt_stat_gather_; - row_iterator_param.px_mode_ = merge_param.px_mode_; // init data_fuse_ ObDirectLoadDataFuseParam data_fuse_param; data_fuse_param.tablet_id_ = tablet_id; @@ -253,21 +195,15 @@ int ObDirectLoadPartitionRangeMergeTask::RowIterator::init( data_fuse_param.table_data_desc_ = merge_param.table_data_desc_; data_fuse_param.datum_utils_ = merge_param.datum_utils_; data_fuse_param.dml_row_handler_ = merge_param.dml_row_handler_; - if (OB_FAIL(inner_init(row_iterator_param))) { + if (OB_FAIL(inner_init(insert_tablet_ctx, sql_statistics, lob_builder))) { LOG_WARN("fail to inner init", KR(ret)); } else if (OB_FAIL(data_fuse_.init(data_fuse_param, origin_table, sstable_array, range))) { LOG_WARN("fail to init data fuse", KR(ret)); } // init datum_row_ - else if (OB_FAIL(datum_row_.init(merge_param.store_column_count_ + - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) { + else if (OB_FAIL(insert_tablet_ctx->init_datum_row(datum_row_))) { LOG_WARN("fail to init datum row", KR(ret)); } else { - datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); - datum_row_.mvcc_row_flag_.set_last_multi_version_row(true); - datum_row_.storage_datums_[merge_param.rowkey_column_num_].set_int( - -merge_param.snapshot_version_); // fill trans_version - datum_row_.storage_datums_[merge_param.rowkey_column_num_ + 1].set_int(0); // fill sql_no rowkey_column_num_ = merge_param.rowkey_column_num_; is_inited_ = true; } @@ -310,9 +246,7 @@ ObDirectLoadPartitionRangeMergeTask::ObDirectLoadPartitionRangeMergeTask() { } -ObDirectLoadPartitionRangeMergeTask::~ObDirectLoadPartitionRangeMergeTask() -{ -} +ObDirectLoadPartitionRangeMergeTask::~ObDirectLoadPartitionRangeMergeTask() {} int ObDirectLoadPartitionRangeMergeTask::init(ObTableLoadTableCtx *ctx, const ObDirectLoadMergeParam &merge_param, @@ -357,8 +291,9 @@ int ObDirectLoadPartitionRangeMergeTask::construct_row_iter(ObIAllocator &alloca if (OB_ISNULL(row_iter = OB_NEWx(RowIterator, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to new RowIterator", KR(ret)); - } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_, column_stat_array_, lob_builder_, - *sstable_array_, *range_))) { + } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_, + sql_statistics_, lob_builder_, *sstable_array_, *range_, + insert_tablet_ctx_))) { LOG_WARN("fail to init row iter", KR(ret)); } else { result_row_iter = row_iter; @@ -379,22 +314,21 @@ int ObDirectLoadPartitionRangeMergeTask::construct_row_iter(ObIAllocator &alloca */ ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator::RowIterator() - : rowkey_column_num_(0), is_inited_(false) + : rowkey_column_num_(0) { } -ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator::~RowIterator() -{ -} +ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator::~RowIterator() {} int ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator::init( const ObDirectLoadMergeParam &merge_param, const ObTabletID &tablet_id, ObDirectLoadOriginTable *origin_table, - ObIArray &column_stat_array, + ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, const ObIArray &sstable_array, - const ObDatumRange &range) + const ObDatumRange &range, + ObDirectLoadInsertTabletContext *insert_tablet_ctx) { int ret = OB_SUCCESS; if (IS_INIT) { @@ -402,23 +336,12 @@ int ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator::init( LOG_WARN("ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator init twice", KR(ret), KP(this)); } else if (OB_UNLIKELY(!merge_param.is_valid() || !tablet_id.is_valid() || - nullptr == origin_table || !range.is_valid())) { + nullptr == origin_table || !range.is_valid() || + nullptr == insert_tablet_ctx)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), K(sstable_array), K(range)); + LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), K(sstable_array), K(range), + KP(insert_tablet_ctx)); } else { - // init row iterator - ObDirectLoadInsertTableRowIteratorParam row_iterator_param; - row_iterator_param.tablet_id_ = tablet_id; - row_iterator_param.table_data_desc_ = merge_param.table_data_desc_; - row_iterator_param.datum_utils_ = merge_param.datum_utils_; - row_iterator_param.col_descs_ = merge_param.col_descs_; - row_iterator_param.lob_column_cnt_ = merge_param.lob_column_cnt_; - row_iterator_param.cmp_funcs_ = merge_param.cmp_funcs_; - row_iterator_param.column_stat_array_ = &column_stat_array; - row_iterator_param.lob_builder_ = &lob_builder; - row_iterator_param.is_heap_table_ = merge_param.is_heap_table_; - row_iterator_param.online_opt_stat_gather_ = merge_param.online_opt_stat_gather_; - row_iterator_param.px_mode_ = merge_param.px_mode_; // init data_fuse_ ObDirectLoadDataFuseParam data_fuse_param; data_fuse_param.tablet_id_ = tablet_id; @@ -426,21 +349,15 @@ int ObDirectLoadPartitionRangeMultipleMergeTask::RowIterator::init( data_fuse_param.table_data_desc_ = merge_param.table_data_desc_; data_fuse_param.datum_utils_ = merge_param.datum_utils_; data_fuse_param.dml_row_handler_ = merge_param.dml_row_handler_; - if (OB_FAIL(inner_init(row_iterator_param))) { + if (OB_FAIL(inner_init(insert_tablet_ctx, sql_statistics, lob_builder))) { LOG_WARN("fail to inner init", KR(ret)); } else if (OB_FAIL(data_fuse_.init(data_fuse_param, origin_table, sstable_array, range))) { LOG_WARN("fail to init data fuse", KR(ret)); } // init datum_row_ - else if (OB_FAIL(datum_row_.init(merge_param.store_column_count_ + - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) { + else if (OB_FAIL(insert_tablet_ctx->init_datum_row(datum_row_))) { LOG_WARN("fail to init datum row", KR(ret)); } else { - datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); - datum_row_.mvcc_row_flag_.set_last_multi_version_row(true); - datum_row_.storage_datums_[merge_param.rowkey_column_num_].set_int( - -merge_param.snapshot_version_); // fill trans_version - datum_row_.storage_datums_[merge_param.rowkey_column_num_ + 1].set_int(0); // fill sql_no rowkey_column_num_ = merge_param.rowkey_column_num_; is_inited_ = true; } @@ -485,9 +402,7 @@ ObDirectLoadPartitionRangeMultipleMergeTask::ObDirectLoadPartitionRangeMultipleM { } -ObDirectLoadPartitionRangeMultipleMergeTask::~ObDirectLoadPartitionRangeMultipleMergeTask() -{ -} +ObDirectLoadPartitionRangeMultipleMergeTask::~ObDirectLoadPartitionRangeMultipleMergeTask() {} int ObDirectLoadPartitionRangeMultipleMergeTask::init( ObTableLoadTableCtx *ctx, @@ -533,8 +448,9 @@ int ObDirectLoadPartitionRangeMultipleMergeTask::construct_row_iter( if (OB_ISNULL(row_iter = OB_NEWx(RowIterator, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to new RowIterator", KR(ret)); - } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_, column_stat_array_, lob_builder_, - *sstable_array_, *range_))) { + } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_, + sql_statistics_, lob_builder_, *sstable_array_, *range_, + insert_tablet_ctx_))) { LOG_WARN("fail to init row iter", KR(ret)); } else { result_row_iter = row_iter; @@ -557,65 +473,46 @@ int ObDirectLoadPartitionRangeMultipleMergeTask::construct_row_iter( ObDirectLoadPartitionHeapTableMergeTask::RowIterator::RowIterator() : deserialize_datums_(nullptr), deserialize_datum_cnt_(0), - dml_row_handler_(nullptr), - is_inited_(false) + dml_row_handler_(nullptr) { } -ObDirectLoadPartitionHeapTableMergeTask::RowIterator::~RowIterator() -{ -} +ObDirectLoadPartitionHeapTableMergeTask::RowIterator::~RowIterator() {} int ObDirectLoadPartitionHeapTableMergeTask::RowIterator::init( const ObDirectLoadMergeParam &merge_param, const ObTabletID &tablet_id, ObDirectLoadExternalTable *external_table, - ObIArray &column_stat_array, + ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, - const ObTabletCacheInterval &pk_interval) + const ObTabletCacheInterval &pk_interval, + ObDirectLoadInsertTabletContext *insert_tablet_ctx) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("ObDirectLoadPartitionHeapTableMergeTask::RowIterator init twice", KR(ret), KP(this)); } else if (OB_UNLIKELY(!merge_param.is_valid() || !tablet_id.is_valid() || - nullptr == external_table || 0 == pk_interval.count())) { + nullptr == external_table || 0 == pk_interval.count() || + nullptr == insert_tablet_ctx)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), KP(external_table), - K(pk_interval)); + K(pk_interval), KP(insert_tablet_ctx)); } else { // init row iterator - ObDirectLoadInsertTableRowIteratorParam row_iterator_param; - row_iterator_param.tablet_id_ = tablet_id; - row_iterator_param.table_data_desc_ = merge_param.table_data_desc_; - row_iterator_param.datum_utils_ = merge_param.datum_utils_; - row_iterator_param.col_descs_ = merge_param.col_descs_; - row_iterator_param.lob_column_cnt_ = merge_param.lob_column_cnt_; - row_iterator_param.cmp_funcs_ = merge_param.cmp_funcs_; - row_iterator_param.column_stat_array_ = &column_stat_array; - row_iterator_param.lob_builder_ = &lob_builder; - row_iterator_param.is_heap_table_ = merge_param.is_heap_table_; - row_iterator_param.online_opt_stat_gather_ = merge_param.online_opt_stat_gather_; - row_iterator_param.px_mode_ = merge_param.px_mode_; - if (OB_FAIL(inner_init(row_iterator_param))) { + if (OB_FAIL(inner_init(insert_tablet_ctx, sql_statistics, lob_builder))) { LOG_WARN("fail to inner init", KR(ret)); } // init scanner_ else if (OB_FAIL(scanner_.init(merge_param.table_data_desc_.external_data_block_size_, - merge_param.table_data_desc_.compressor_type_, - external_table->get_fragments()))) { + merge_param.table_data_desc_.compressor_type_, + external_table->get_fragments()))) { LOG_WARN("fail to init fragment scanner", KR(ret)); } // init datum_row_ - else if (OB_FAIL(datum_row_.init(merge_param.store_column_count_ + - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) { + else if (OB_FAIL(insert_tablet_ctx->init_datum_row(datum_row_))) { LOG_WARN("fail to init datum row", KR(ret)); } else { - datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); - datum_row_.mvcc_row_flag_.set_last_multi_version_row(true); - datum_row_.storage_datums_[merge_param.rowkey_column_num_].set_int( - -merge_param.snapshot_version_); // fill trans_version - datum_row_.storage_datums_[merge_param.rowkey_column_num_ + 1].set_int(0); // fill sql_no deserialize_datums_ = datum_row_.storage_datums_ + merge_param.rowkey_column_num_ + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); deserialize_datum_cnt_ = merge_param.store_column_count_ - merge_param.rowkey_column_num_; @@ -660,16 +557,12 @@ int ObDirectLoadPartitionHeapTableMergeTask::RowIterator::inner_get_next_row( return ret; } - - ObDirectLoadPartitionHeapTableMergeTask::ObDirectLoadPartitionHeapTableMergeTask() : external_table_(nullptr) { } -ObDirectLoadPartitionHeapTableMergeTask::~ObDirectLoadPartitionHeapTableMergeTask() -{ -} +ObDirectLoadPartitionHeapTableMergeTask::~ObDirectLoadPartitionHeapTableMergeTask() {} int ObDirectLoadPartitionHeapTableMergeTask::init(ObTableLoadTableCtx *ctx, const ObDirectLoadMergeParam &merge_param, @@ -713,8 +606,9 @@ int ObDirectLoadPartitionHeapTableMergeTask::construct_row_iter( if (OB_ISNULL(row_iter = OB_NEWx(RowIterator, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to new RowIterator", KR(ret)); - } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), external_table_, column_stat_array_, lob_builder_, - pk_interval_))) { + } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), external_table_, + sql_statistics_, lob_builder_, pk_interval_, + insert_tablet_ctx_))) { LOG_WARN("fail to init row iter", KR(ret)); } else { result_row_iter = row_iter; @@ -737,22 +631,20 @@ int ObDirectLoadPartitionHeapTableMergeTask::construct_row_iter( ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::RowIterator() : deserialize_datums_(nullptr), deserialize_datum_cnt_(0), - dml_row_handler_(nullptr), - is_inited_(false) + dml_row_handler_(nullptr) { } -ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::~RowIterator() -{ -} +ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::~RowIterator() {} int ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::init( const ObDirectLoadMergeParam &merge_param, const ObTabletID &tablet_id, ObDirectLoadMultipleHeapTable *heap_table, - ObIArray &column_stat_array, + ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, - const ObTabletCacheInterval &pk_interval) + const ObTabletCacheInterval &pk_interval, + ObDirectLoadInsertTabletContext *insert_tablet_ctx) { int ret = OB_SUCCESS; if (IS_INIT) { @@ -760,25 +652,14 @@ int ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::init( LOG_WARN("ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator init twice", KR(ret), KP(this)); } else if (OB_UNLIKELY(!merge_param.is_valid() || !tablet_id.is_valid() || - nullptr == heap_table || 0 == pk_interval.count())) { + nullptr == heap_table || 0 == pk_interval.count() || + nullptr == insert_tablet_ctx)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), KPC(heap_table), - K(pk_interval)); + LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), KPC(heap_table), K(pk_interval), + KP(insert_tablet_ctx)); } else { // init row iterator - ObDirectLoadInsertTableRowIteratorParam row_iterator_param; - row_iterator_param.tablet_id_ = tablet_id; - row_iterator_param.table_data_desc_ = merge_param.table_data_desc_; - row_iterator_param.datum_utils_ = merge_param.datum_utils_; - row_iterator_param.col_descs_ = merge_param.col_descs_; - row_iterator_param.lob_column_cnt_ = merge_param.lob_column_cnt_; - row_iterator_param.cmp_funcs_ = merge_param.cmp_funcs_; - row_iterator_param.column_stat_array_ = &column_stat_array; - row_iterator_param.lob_builder_ = &lob_builder; - row_iterator_param.is_heap_table_ = merge_param.is_heap_table_; - row_iterator_param.online_opt_stat_gather_ = merge_param.online_opt_stat_gather_; - row_iterator_param.px_mode_ = merge_param.px_mode_; - if (OB_FAIL(inner_init(row_iterator_param))) { + if (OB_FAIL(inner_init(insert_tablet_ctx, sql_statistics, lob_builder))) { LOG_WARN("fail to inner init", KR(ret)); } // init scanner_ @@ -786,15 +667,9 @@ int ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::init( LOG_WARN("fail to init tablet whole scanner", KR(ret)); } // init datum_row_ - else if (OB_FAIL(datum_row_.init(merge_param.store_column_count_ + - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) { + else if (OB_FAIL(insert_tablet_ctx->init_datum_row(datum_row_))) { LOG_WARN("fail to init datum row", KR(ret)); } else { - datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); - datum_row_.mvcc_row_flag_.set_last_multi_version_row(true); - datum_row_.storage_datums_[merge_param.rowkey_column_num_].set_int( - -merge_param.snapshot_version_); // fill trans_version - datum_row_.storage_datums_[merge_param.rowkey_column_num_ + 1].set_int(0); // fill sql_no deserialize_datums_ = datum_row_.storage_datums_ + merge_param.rowkey_column_num_ + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); deserialize_datum_cnt_ = merge_param.store_column_count_ - merge_param.rowkey_column_num_; @@ -806,7 +681,6 @@ int ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::init( return ret; } - int ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator::inner_get_next_row( ObDatumRow *&result_row) { @@ -892,8 +766,9 @@ int ObDirectLoadPartitionHeapTableMultipleMergeTask::construct_row_iter( if (OB_ISNULL(row_iter = OB_NEWx(RowIterator, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to new RowIterator", KR(ret)); - } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), heap_table_, column_stat_array_, lob_builder_, - pk_interval_))) { + } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), heap_table_, + sql_statistics_, lob_builder_, pk_interval_, + insert_tablet_ctx_))) { LOG_WARN("fail to init row iter", KR(ret)); } else { result_row_iter = row_iter; @@ -922,8 +797,7 @@ ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::RowIterat pos_(0), deserialize_datums_(nullptr), deserialize_datum_cnt_(0), - dml_row_handler_(nullptr), - is_inited_(false) + dml_row_handler_(nullptr) { allocator_.set_tenant_id(MTL_ID()); } @@ -937,12 +811,14 @@ ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::~RowItera } int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::init( - const ObDirectLoadMergeParam &merge_param, const ObTabletID &tablet_id, + const ObDirectLoadMergeParam &merge_param, + const ObTabletID &tablet_id, ObDirectLoadOriginTable *origin_table, - ObIArray &column_stat_array, + ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, const ObIArray *heap_table_array, - const ObTabletCacheInterval &pk_interval) + const ObTabletCacheInterval &pk_interval, + ObDirectLoadInsertTabletContext *insert_tablet_ctx) { int ret = OB_SUCCESS; if (IS_INIT) { @@ -950,40 +826,23 @@ int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::RowIterator::init( LOG_WARN("ObDirectLoadPartitionHeapTableMultipleMergeTask::RowIterator init twice", KR(ret), KP(this)); } else if (OB_UNLIKELY(!merge_param.is_valid() || !tablet_id.is_valid() || - nullptr == origin_table || nullptr == heap_table_array)) { + nullptr == origin_table || nullptr == heap_table_array || + nullptr == insert_tablet_ctx)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid args", KR(ret), K(merge_param), K(tablet_id), KP(origin_table), - KP(heap_table_array)); + KP(heap_table_array), KP(insert_tablet_ctx)); } else { range_.set_whole_range(); // init row iterator - ObDirectLoadInsertTableRowIteratorParam row_iterator_param; - row_iterator_param.tablet_id_ = tablet_id; - row_iterator_param.table_data_desc_ = merge_param.table_data_desc_; - row_iterator_param.datum_utils_ = merge_param.datum_utils_; - row_iterator_param.col_descs_ = merge_param.col_descs_; - row_iterator_param.lob_column_cnt_ = merge_param.lob_column_cnt_; - row_iterator_param.cmp_funcs_ = merge_param.cmp_funcs_; - row_iterator_param.column_stat_array_ = &column_stat_array; - row_iterator_param.lob_builder_ = &lob_builder; - row_iterator_param.is_heap_table_ = merge_param.is_heap_table_; - row_iterator_param.online_opt_stat_gather_ = merge_param.online_opt_stat_gather_; - row_iterator_param.px_mode_ = merge_param.px_mode_; - if (OB_FAIL(inner_init(row_iterator_param))) { + if (OB_FAIL(inner_init(insert_tablet_ctx, sql_statistics, lob_builder))) { LOG_WARN("fail to inner init", KR(ret)); } else if (OB_FAIL(origin_table->scan(range_, allocator_, origin_iter_))) { LOG_WARN("fail to scan origin table", KR(ret)); } // init datum_row_ - else if (OB_FAIL(datum_row_.init(merge_param.store_column_count_ + - ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt()))) { + else if (OB_FAIL(insert_tablet_ctx->init_datum_row(datum_row_))) { LOG_WARN("fail to init datum row", KR(ret)); } else { - datum_row_.row_flag_.set_flag(ObDmlFlag::DF_INSERT); - datum_row_.mvcc_row_flag_.set_last_multi_version_row(true); - datum_row_.storage_datums_[merge_param.rowkey_column_num_].set_int( - -merge_param.snapshot_version_); // fill trans_version - datum_row_.storage_datums_[merge_param.rowkey_column_num_ + 1].set_int(0); // fill sql_no deserialize_datums_ = datum_row_.storage_datums_ + merge_param.rowkey_column_num_ + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); deserialize_datum_cnt_ = merge_param.store_column_count_ - merge_param.rowkey_column_num_; @@ -1152,8 +1011,9 @@ int ObDirectLoadPartitionHeapTableMultipleAggregateMergeTask::construct_row_iter if (OB_ISNULL(row_iter = OB_NEWx(RowIterator, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to new RowIterator", KR(ret)); - } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_, column_stat_array_, lob_builder_, - heap_table_array_, pk_interval_))) { + } else if (OB_FAIL(row_iter->init(*merge_param_, merge_ctx_->get_tablet_id(), origin_table_, + sql_statistics_, lob_builder_, heap_table_array_, + pk_interval_, insert_tablet_ctx_))) { LOG_WARN("fail to init row iter", KR(ret)); } else { result_row_iter = row_iter; diff --git a/src/storage/direct_load/ob_direct_load_partition_merge_task.h b/src/storage/direct_load/ob_direct_load_partition_merge_task.h index 35b01c1e4..32230ec34 100644 --- a/src/storage/direct_load/ob_direct_load_partition_merge_task.h +++ b/src/storage/direct_load/ob_direct_load_partition_merge_task.h @@ -18,7 +18,7 @@ #include "storage/direct_load/ob_direct_load_merge_ctx.h" #include "storage/direct_load/ob_direct_load_multiple_heap_table_scanner.h" #include "storage/direct_load/ob_direct_load_insert_table_row_iterator.h" -#include "sql/engine/expr/ob_expr_sys_op_opnsize.h" +#include "storage/direct_load/ob_direct_load_lob_builder.h" #include "observer/table_load/ob_table_load_table_ctx.h" namespace oceanbase @@ -27,10 +27,10 @@ namespace blocksstable { class ObDatumRange; } // namespace blocksstable -namespace common +namespace table { -class ObOptOSGColumnStat; -} // namespace common +class ObTableLoadSqlStatistics; +} // namespace table namespace storage { class ObDirectLoadOriginTable; @@ -44,28 +44,22 @@ public: ObDirectLoadPartitionMergeTask(); virtual ~ObDirectLoadPartitionMergeTask(); int process(); - const common::ObIArray &get_column_stat_array() const - { - return column_stat_array_; - } int64_t get_row_count() const { return affected_rows_; } void stop(); TO_STRING_KV(KPC_(merge_param), KPC_(merge_ctx), K_(parallel_idx)); protected: virtual int construct_row_iter(common::ObIAllocator &allocator, ObIStoreRowIterator *&row_iter) = 0; -private: - int init_sql_statistics(); - int init_lob_builder(); protected: observer::ObTableLoadTableCtx *ctx_; const ObDirectLoadMergeParam *merge_param_; ObDirectLoadTabletMergeCtx *merge_ctx_; int64_t parallel_idx_; int64_t affected_rows_; - common::ObArray column_stat_array_; ObDirectLoadLobBuilder lob_builder_; common::ObArenaAllocator allocator_; + ObDirectLoadInsertTabletContext *insert_tablet_ctx_; + table::ObTableLoadSqlStatistics *sql_statistics_; bool is_stop_; bool is_inited_; }; @@ -93,16 +87,16 @@ private: int init(const ObDirectLoadMergeParam &merge_param, const common::ObTabletID &tablet_id, ObDirectLoadOriginTable *origin_table, - common::ObIArray &column_stat_array, + table::ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, const common::ObIArray &sstable_array, - const blocksstable::ObDatumRange &range); + const blocksstable::ObDatumRange &range, + ObDirectLoadInsertTabletContext *insert_tablet_ctx); int inner_get_next_row(blocksstable::ObDatumRow *&datum_row) override; private: ObDirectLoadSSTableDataFuse data_fuse_; blocksstable::ObDatumRow datum_row_; int64_t rowkey_column_num_; - bool is_inited_; }; private: ObDirectLoadOriginTable *origin_table_; @@ -133,16 +127,16 @@ private: int init(const ObDirectLoadMergeParam &merge_param, const common::ObTabletID &tablet_id, ObDirectLoadOriginTable *origin_table, - common::ObIArray &column_stat_array, + table::ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, const common::ObIArray &sstable_array, - const blocksstable::ObDatumRange &range); + const blocksstable::ObDatumRange &range, + ObDirectLoadInsertTabletContext *insert_tablet_ctx); int inner_get_next_row(blocksstable::ObDatumRow *&datum_row) override; private: ObDirectLoadMultipleSSTableDataFuse data_fuse_; blocksstable::ObDatumRow datum_row_; int64_t rowkey_column_num_; - bool is_inited_; }; private: ObDirectLoadOriginTable *origin_table_; @@ -172,9 +166,10 @@ private: int init(const ObDirectLoadMergeParam &merge_param, const common::ObTabletID &tablet_id, ObDirectLoadExternalTable *external_table, - common::ObIArray &column_stat_array, + table::ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, - const share::ObTabletCacheInterval &pk_interval); + const share::ObTabletCacheInterval &pk_interval, + ObDirectLoadInsertTabletContext *insert_tablet_ctx); int inner_get_next_row(blocksstable::ObDatumRow *&datum_row) override; private: ObDirectLoadExternalSequentialScanner scanner_; @@ -183,7 +178,6 @@ private: int64_t deserialize_datum_cnt_; share::ObTabletCacheInterval pk_interval_; ObDirectLoadDMLRowHandler *dml_row_handler_; - bool is_inited_; }; private: ObDirectLoadExternalTable *external_table_; @@ -212,9 +206,10 @@ private: int init(const ObDirectLoadMergeParam &merge_param, const common::ObTabletID &tablet_id, ObDirectLoadMultipleHeapTable *heap_table, - common::ObIArray &column_stat_array, + table::ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, - const share::ObTabletCacheInterval &pk_interval); + const share::ObTabletCacheInterval &pk_interval, + ObDirectLoadInsertTabletContext *insert_tablet_ctx); int inner_get_next_row(blocksstable::ObDatumRow *&datum_row) override; private: ObDirectLoadMultipleHeapTableTabletWholeScanner scanner_; @@ -223,7 +218,6 @@ private: int64_t deserialize_datum_cnt_; share::ObTabletCacheInterval pk_interval_; ObDirectLoadDMLRowHandler *dml_row_handler_; - bool is_inited_; }; private: ObDirectLoadMultipleHeapTable *heap_table_; @@ -251,10 +245,11 @@ private: virtual ~RowIterator(); int init(const ObDirectLoadMergeParam &merge_param, const common::ObTabletID &tablet_id, ObDirectLoadOriginTable *origin_table, - common::ObIArray &column_stat_array, + table::ObTableLoadSqlStatistics *sql_statistics, ObDirectLoadLobBuilder &lob_builder, const common::ObIArray *heap_table_array, - const share::ObTabletCacheInterval &pk_interval); + const share::ObTabletCacheInterval &pk_interval, + ObDirectLoadInsertTabletContext *insert_tablet_ctx); int inner_get_next_row(blocksstable::ObDatumRow *&datum_row) override; private: int switch_next_heap_table(); @@ -276,7 +271,6 @@ private: int64_t deserialize_datum_cnt_; share::ObTabletCacheInterval pk_interval_; ObDirectLoadDMLRowHandler *dml_row_handler_; - bool is_inited_; }; private: ObDirectLoadOriginTable *origin_table_; diff --git a/src/storage/direct_load/ob_direct_load_table_store.cpp b/src/storage/direct_load/ob_direct_load_table_store.cpp index df890df39..dc0ab0b9d 100644 --- a/src/storage/direct_load/ob_direct_load_table_store.cpp +++ b/src/storage/direct_load/ob_direct_load_table_store.cpp @@ -32,16 +32,10 @@ using namespace table; */ ObDirectLoadTableStoreParam::ObDirectLoadTableStoreParam() - : snapshot_version_(0), - lob_column_cnt_(0), - datum_utils_(nullptr), - col_descs_(nullptr), - cmp_funcs_(nullptr), + : datum_utils_(nullptr), file_mgr_(nullptr), is_multiple_mode_(false), is_fast_heap_table_(false), - online_opt_stat_gather_(false), - px_mode_(false), insert_table_ctx_(nullptr), dml_row_handler_(nullptr), extra_buf_(nullptr), @@ -55,8 +49,7 @@ ObDirectLoadTableStoreParam::~ObDirectLoadTableStoreParam() bool ObDirectLoadTableStoreParam::is_valid() const { - return snapshot_version_ > 0 && table_data_desc_.is_valid() && nullptr != datum_utils_ && - nullptr != col_descs_ && nullptr != cmp_funcs_ && + return table_data_desc_.is_valid() && nullptr != datum_utils_ && nullptr != file_mgr_ && (!is_fast_heap_table_ || (nullptr != insert_table_ctx_)) && nullptr != dml_row_handler_; @@ -110,16 +103,9 @@ int ObDirectLoadTableStoreBucket::init(const ObDirectLoadTableStoreParam ¶m, // new fast heap table ObDirectLoadFastHeapTableBuildParam fast_heap_table_build_param; fast_heap_table_build_param.tablet_id_ = tablet_id; - fast_heap_table_build_param.snapshot_version_ = param.snapshot_version_; fast_heap_table_build_param.table_data_desc_ = param.table_data_desc_; - fast_heap_table_build_param.datum_utils_ = param.datum_utils_; - fast_heap_table_build_param.col_descs_ = param.col_descs_; - fast_heap_table_build_param.lob_column_cnt_ = param.lob_column_cnt_; - fast_heap_table_build_param.cmp_funcs_ = param.cmp_funcs_; fast_heap_table_build_param.insert_table_ctx_ = param.insert_table_ctx_; fast_heap_table_build_param.dml_row_handler_ = param.dml_row_handler_; - fast_heap_table_build_param.online_opt_stat_gather_ = param.online_opt_stat_gather_; - fast_heap_table_build_param.px_mode_ = param.px_mode_; ObDirectLoadFastHeapTableBuilder *fast_heap_table_builder = nullptr; if (OB_ISNULL(fast_heap_table_builder = table_builder_allocator_->alloc())) { diff --git a/src/storage/direct_load/ob_direct_load_table_store.h b/src/storage/direct_load/ob_direct_load_table_store.h index 13b50da14..aa91a201a 100644 --- a/src/storage/direct_load/ob_direct_load_table_store.h +++ b/src/storage/direct_load/ob_direct_load_table_store.h @@ -33,22 +33,21 @@ public: ObDirectLoadTableStoreParam(); ~ObDirectLoadTableStoreParam(); bool is_valid() const; - TO_STRING_KV(K_(snapshot_version), K_(table_data_desc), KP_(datum_utils), KP_(col_descs), - KP_(lob_column_cnt), KP_(cmp_funcs), KP_(file_mgr), K_(is_multiple_mode), - K_(is_fast_heap_table), K_(online_opt_stat_gather), K_(px_mode), - KP_(insert_table_ctx), KP_(dml_row_handler), KP_(extra_buf), K_(extra_buf_size)); + TO_STRING_KV(K_(table_data_desc), + KP_(datum_utils), + KP_(file_mgr), + K_(is_multiple_mode), + K_(is_fast_heap_table), + KP_(insert_table_ctx), + KP_(dml_row_handler), + KP_(extra_buf), + K_(extra_buf_size)); public: - int64_t snapshot_version_; - int64_t lob_column_cnt_; ObDirectLoadTableDataDesc table_data_desc_; const blocksstable::ObStorageDatumUtils *datum_utils_; - const common::ObIArray *col_descs_; - const blocksstable::ObStoreCmpFuncs *cmp_funcs_; ObDirectLoadTmpFileManager *file_mgr_; bool is_multiple_mode_; bool is_fast_heap_table_; - bool online_opt_stat_gather_; - bool px_mode_; ObDirectLoadInsertTableContext *insert_table_ctx_; ObDirectLoadDMLRowHandler *dml_row_handler_; char *extra_buf_; diff --git a/src/storage/high_availability/ob_tablet_backfill_tx.cpp b/src/storage/high_availability/ob_tablet_backfill_tx.cpp index c3fb6192c..2fa751768 100644 --- a/src/storage/high_availability/ob_tablet_backfill_tx.cpp +++ b/src/storage/high_availability/ob_tablet_backfill_tx.cpp @@ -582,7 +582,7 @@ int ObTabletBackfillTXTask::get_backfill_tx_memtables_( for (int64_t i = 0; OB_SUCC(ret) && i < memtables.count(); ++i) { ObITable *table = memtables.at(i).get_table(); memtable::ObMemtable *memtable = static_cast(table); - if (OB_ISNULL(table) || !table->is_memtable()) { + if (OB_ISNULL(table) || !table->is_data_memtable()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table should not be NULL or table type is unexpected", K(ret), KP(table)); } else if (table->get_start_scn() >= backfill_tx_ctx_->log_sync_scn_ @@ -935,7 +935,7 @@ int ObTabletTableBackfillTXTask::prepare_merge_ctx_() tablet_merge_ctx_.tablet_handle_ = tablet_handle_; static_param.version_range_.multi_version_start_ = tablet_handle_.get_obj()->get_multi_version_start(); static_param.version_range_.snapshot_version_ = table_handle_.get_table()->is_memtable() ? - static_cast(table_handle_.get_table())->get_snapshot_version() : tablet_handle_.get_obj()->get_snapshot_version(); + static_cast(table_handle_.get_table())->get_snapshot_version() : tablet_handle_.get_obj()->get_snapshot_version(); static_param.scn_range_ = table_handle_.get_table()->get_key().scn_range_; static_param.merge_scn_ = table_handle_.get_table()->is_memtable() ? table_handle_.get_table()->get_key().scn_range_.end_scn_ : backfill_tx_ctx_->log_sync_scn_; static_param.create_snapshot_version_ = 0; diff --git a/src/storage/ls/ob_freezer.cpp b/src/storage/ls/ob_freezer.cpp index 18ceff902..3f030aa4b 100644 --- a/src/storage/ls/ob_freezer.cpp +++ b/src/storage/ls/ob_freezer.cpp @@ -11,27 +11,29 @@ */ #define USING_LOG_PREFIX STORAGE -#include "storage/ls/ob_freezer.h" +#include "common/ob_tablet_id.h" +#include "logservice/ob_log_service.h" #include "share/ob_force_print_log.h" +#include "storage/ls/ob_ls.h" +#include "storage/ls/ob_freezer.h" #include "storage/ls/ob_ls_tx_service.h" -#include "storage/checkpoint/ob_data_checkpoint.h" -#include "storage/memtable/ob_memtable.h" #include "storage/ls/ob_ls_tablet_service.h" +#include "storage/checkpoint/ob_data_checkpoint.h" +#include "storage/compaction/ob_compaction_diagnose.h" +#include "storage/compaction/ob_tenant_tablet_scheduler.h" +#include "storage/ddl/ob_tablet_ddl_kv.h" +#include "storage/memtable/ob_memtable.h" #include "storage/tablet/ob_tablet.h" #include "storage/tablet/ob_tablet_iterator.h" #include "storage/tx/ob_trans_service.h" -#include "storage/compaction/ob_compaction_diagnose.h" -#include "logservice/ob_log_service.h" -#include "storage/ls/ob_ls.h" #include "storage/tx_storage/ob_tenant_freezer.h" -#include "common/ob_tablet_id.h" -#include "storage/compaction/ob_tenant_tablet_scheduler.h" namespace oceanbase { using namespace logservice; using namespace share; using namespace compaction; +using namespace memtable; namespace storage { ObFrozenMemtableInfo::ObFrozenMemtableInfo() @@ -502,8 +504,8 @@ int ObFreezer::logstream_freeze(int64_t trace_id, TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id)); } else if (ObScnRange::MAX_SCN == freeze_snapshot_version || ObScnRange::MIN_SCN >= freeze_snapshot_version) { - ret = OB_NOT_INIT; - LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id), K(freeze_snapshot_version)); + ret = OB_MINOR_FREEZE_NOT_ALLOW; + LOG_WARN("[Freezer] invalid weak read scn", K(ret), K(ls_id), K(freeze_snapshot_version)); } else if (OB_FAIL(set_freeze_flag())) { FLOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id)); } else if (FALSE_IT(max_decided_scn_ = max_decided_scn)) { @@ -551,7 +553,7 @@ int ObFreezer::inner_logstream_freeze(ObFuture *result) if (FALSE_IT(submit_checkpoint_task())) { } else if (FALSE_IT(try_submit_log_for_freeze_(false/*tablet freeze*/))) { - } else if (OB_FAIL(submit_freeze_task(true/*is_ls_freeze*/, result, handle))) { + } else if (OB_FAIL(submit_freeze_task_(true/*is_ls_freeze*/, result, handle))) { TRANS_LOG(ERROR, "failed to submit ls_freeze task", K(ret), K(ls_id)); stat_.add_diagnose_info("fail to submit ls_freeze_task"); ob_abort(); @@ -575,7 +577,7 @@ void ObFreezer::submit_checkpoint_task() } while (OB_FAIL(ret)); } -int ObFreezer::ls_freeze_task() +int ObFreezer::ls_freeze_task_() { int ret = OB_SUCCESS; share::ObLSID ls_id = get_ls_id(); @@ -679,84 +681,6 @@ int ObFreezer::tablet_freeze(const ObTabletID &tablet_id, ObFuture *result) return ret; } -int ObFreezer::freeze_normal_tablet_(const ObTabletID &tablet_id, ObFuture *result) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = get_ls_id(); - ObTabletHandle handle; - ObTablet *tablet = nullptr; - ObTableHandleV2 frozen_memtable_handle; - SCN freeze_snapshot_version; - FLOG_INFO("[Freezer] tablet_freeze start", K(ret), K(ls_id), K(tablet_id)); - int64_t start_time = ObTimeUtility::current_time(); - ObProtectedMemtableMgrHandle *protected_handle = NULL; - - ObTabletFreezeGuard guard(*this, true /* try guard */); - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_UNLIKELY(!enable_)) { - ret = OB_NOT_RUNNING; - LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id)); - } else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) { - // no need freeze now, a ls freeze is running or will be running - ret = OB_SUCCESS; - LOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(set_freeze_flag_without_inc_freeze_clock())) { - LOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id), K(tablet_id)); - } else { - // succeed to set freeze flag - if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) { - TRANS_LOG(WARN, "[Freezer] get ls weak read scn failure", K(ret), K(ls_id)); - } else if (ObScnRange::MAX_SCN == freeze_snapshot_version - || ObScnRange::MIN_SCN >= freeze_snapshot_version) { - ret = OB_NOT_INIT; - LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id)); - } else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) { - } else if (FALSE_IT(set_need_resubmit_log(false))) { - } else if (FALSE_IT(stat_.reset())) { - } else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(), - start_time, - ObFreezeState::NOT_SUBMIT_LOG, - freeze_snapshot_version, - tablet_id, - false/*need_rewrite_meta*/))) { - TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id)); - } else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id, - handle, 0, - ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { - TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to get tablet"); - } else if (FALSE_IT(tablet = handle.get_obj())) { - } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); - } else if (OB_FAIL(protected_handle->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) { - if (ret == OB_ENTRY_NOT_EXIST) { - ret = OB_SUCCESS; - TRANS_LOG(INFO, "[Freezer] no need to freeze", K(ret), - K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("no need to freeze"); - } else { - TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to set is_tablet_freeze"); - } - } else if (FALSE_IT(try_submit_log_for_freeze_(true/*tablet freeze*/))) { - } else if (OB_FAIL(submit_freeze_task(false/*is_ls_freeze*/, result, frozen_memtable_handle))) { - TRANS_LOG(WARN, "[Freezer] fail to submit tablet_freeze_task", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to submit tablet_freeze_task"); - } else { - TRANS_LOG(INFO, "[Freezer] succeed to start tablet_freeze_task", K(ret), K(ls_id), K(tablet_id)); - } - if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) { - stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret); - print_freezer_statistics(); - unset_freeze_(); - } - } - - return ret; -} - int ObFreezer::freeze_ls_inner_tablet_(const ObTabletID &tablet_id) { int ret = OB_SUCCESS; @@ -769,17 +693,130 @@ int ObFreezer::freeze_ls_inner_tablet_(const ObTabletID &tablet_id) return ret; } -int ObFreezer::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id) +/** + * @brief freeze normal tablet logic + * + * @param for_direct_load if this freeze is called by direct load logic, the freeze must be executed even if there is a + * logstream freeze running. So the ret code OB_EAGAIN cannot be reset to OB_SUCCESS + */ +int ObFreezer::freeze_normal_tablet_(const ObTabletID &tablet_id, ObFuture *result, const bool for_direct_load) { int ret = OB_SUCCESS; + const share::ObLSID ls_id = get_ls_id(); + const int64_t start_time = ObClockGenerator::getClock(); + FLOG_INFO("[Freezer] tablet_freeze start", K(ret), K(ls_id), K(tablet_id), KTIME(start_time)); + + ObTabletFreezeGuard guard(*this, true /* try guard */); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_id)); + } else if (OB_UNLIKELY(!enable_)) { + ret = OB_NOT_RUNNING; + LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id)); + } else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) { + if (for_direct_load) { + // ret == OB_EAGAIN, need try freeze again + } else { + ret = OB_SUCCESS; + LOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K(ls_id), K(tablet_id)); + } + } else if (OB_FAIL(set_freeze_flag_without_inc_freeze_clock())) { + LOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id), K(tablet_id)); + } else { + ObTableHandleV2 frozen_memtable_handle; + const bool need_rewrite_meta = false; + if (OB_FAIL(do_tablet_freeze_(need_rewrite_meta, start_time, tablet_id, result, frozen_memtable_handle))) { + STORAGE_LOG(WARN, "tablet freeze failed", KR(ret), K(ls_id), K(tablet_id)); + } + if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) { + stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObClockGenerator::getClock(), ret); + print_freezer_statistics(); + unset_freeze_(); + } + } + return ret; +} + +// Define a functor to avoid using lambda +struct FreezeTaskFunctor { + ObFreezer *freezer_; + const ObTabletID tablet_id_; + const uint64_t epoch_; + // hold ls handle to avoid logstream being destroyed + ObLSHandle ls_handle_; + FreezeTaskFunctor(ObFreezer *freezer, const ObTabletID tablet_id, const uint64_t epoch, ObLSHandle &ls_handle) + : freezer_(freezer), tablet_id_(tablet_id), epoch_(epoch), ls_handle_(ls_handle) {} + int operator()() + { + int ret = OB_SUCCESS; + ObLS *ls = freezer_->ls_; + STORAGE_LOG(INFO, "async tablet freeze task start", K(tablet_id_), K(freezer_->get_ls_id())); + const int64_t RETRY_INTERVAL = 100 * 1000; // 100 ms + if (OB_ISNULL(ls)) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "unexpected nullptr ", KR(ret), KP(this)); + } else if (OB_FAIL(ls->tablet_freeze_task_for_direct_load(tablet_id_, epoch_))) { + // NOTICE : call function on logstream to avoid some concurrent situation, like ls offline + if (REACH_TIME_INTERVAL(1LL * 1000LL * 1000LL /* 1 second */)) { + LOG_INFO("fail to start tablet freeze. need retry", K(ret), K(tablet_id_)); + } + + // sleep for some time and commit another freeze task to avoid occuping this thread for a long time + usleep(RETRY_INTERVAL); + (void)freezer_->commit_async_tablet_freeze_task_once(tablet_id_, epoch_); + } + return ret; + } +}; + +void ObFreezer::commit_async_tablet_freeze_task_once(const ObTabletID &tablet_id, const uint64_t epoch) +{ + int ret = OB_SUCCESS; + ObTenantFreezer *tenant_freezer = nullptr; share::ObLSID ls_id = get_ls_id(); - ObTabletHandle tablet_handle; - ObTablet *tablet = nullptr; - ObTableHandleV2 frozen_memtable_handle; - SCN freeze_snapshot_version; - ObProtectedMemtableMgrHandle *protected_handle = NULL; - FLOG_INFO("[Freezer] tablet_freeze_with_rewrite_meta start", K(ret), K(ls_id), K(tablet_id)); - int64_t start_time = ObTimeUtility::current_time(); + const int64_t start_time = ObClockGenerator::getClock(); + + if (OB_UNLIKELY(!enable_)) { + ret = OB_NOT_RUNNING; + LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id)); + } else if (OB_ISNULL(tenant_freezer = MTL(storage::ObTenantFreezer *))) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "ObTenantFreezer is null", K(ret), K(ls_id)); + } else { + ObSpinLockGuard freeze_thread_pool(tenant_freezer->freeze_thread_pool_lock_); + do { + ObLSHandle ls_handle; + if (OB_FAIL(MTL(ObLSService*)->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD))) { + STORAGE_LOG(WARN, "get ls handle failed. stop async freeze task", KR(ret), K(ls_id)); + break; + } else { + FreezeTaskFunctor freeze_task_functor(this, tablet_id, epoch, ls_handle); + ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret(freeze_task_functor); + + if (OB_FAIL(ret) && REACH_TIME_INTERVAL(10LL * 1000LL * 1000LL /* 10 second */)) { + STORAGE_LOG(WARN, "[Freezer] commit async tablet freeze task failed", KR(ret), K(ls_id), K(tablet_id)); + } + } + } while (OB_FAIL(ret)); + } +} + +/** + * @brief This function is executed in TenantFreezer freeze_thread_pool as an async task and the freeze logic would be + * retried until success or logstream offlined. + * + */ +int ObFreezer::tablet_freeze_task_for_direct_load(const ObTabletID &tablet_id, ObFuture *result) +{ + return freeze_normal_tablet_(tablet_id, result, true /*for_direct_load*/); +} + +int ObFreezer::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, ObFuture *result) +{ + int ret = OB_SUCCESS; + const int64_t start_time = ObClockGenerator::getClock(); + const share::ObLSID ls_id = get_ls_id(); + FLOG_INFO("[Freezer] tablet_freeze_with_rewrite_meta start", K(ret), K(ls_id), K(tablet_id), KTIME(start_time)); ObTabletFreezeGuard guard(*this); if (IS_NOT_INIT) { @@ -791,104 +828,13 @@ int ObFreezer::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id) } else if (OB_FAIL(loop_set_freeze_flag())) { TRANS_LOG(WARN, "[Freezer] failed to set freeze_flag", K(ret), K(ls_id), K(tablet_id)); } else { - // succeed to set freeze flag - if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) { - TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id)); - } else if (ObScnRange::MAX_SCN == freeze_snapshot_version - || ObScnRange::MIN_SCN >= freeze_snapshot_version) { - ret = OB_NOT_INIT; - LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id)); - } else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) { - } else if (FALSE_IT(set_need_resubmit_log(false))) { - } else if (FALSE_IT(stat_.reset())) { - } else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(), - start_time, - ObFreezeState::NOT_SUBMIT_LOG, - freeze_snapshot_version, - tablet_id, - true/*need_rewrite_meta*/))) { - TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id)); - } else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id, - tablet_handle, - ObTabletCommon::DEFAULT_GET_TABLET_NO_WAIT, - ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { - TRANS_LOG(WARN, "[Freezer] fail to get tablet for freeze", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to get tablet"); - } else if (FALSE_IT(tablet = tablet_handle.get_obj())) { - } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); - } else if (OB_FAIL(protected_handle->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) { - if (ret == OB_ENTRY_NOT_EXIST) { - ret = OB_SUCCESS; - ObProtectedMemtableMgrHandle *protected_handle = NULL; - if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); - } else if (!protected_handle->has_memtable()) { - // We need trigger a dag to rewrite the snapshot version of tablet - // meta for the major merge and medium merge. While the implementation - // need pay much attentio. - // 1. If we trigger the dag each time the freeze happened, there may - // be alive dag not finished, and we rewrite the tablet meta first. - // It will cause the snapshot version to be pushed by mistake. - // 2. We need fetch the weak read timestamp at first, otherwise the - // concurrent memtable creation may miscalculate the version - // - // NOTICE: use freeze_snapshot_version as input parameter - - // check exist mini compaction dag running - ObTabletMergeDagParam param; - param.merge_type_ = ObMergeType::MINI_MERGE; - param.merge_version_ = ObVersionRange::MIN_VERSION; - param.ls_id_ = ls_id; - param.tablet_id_ = tablet_id; - param.skip_get_tablet_ = true; - - ObProtectedMemtableMgrHandle *protected_handle = NULL; - ObTabletMiniMergeDag tmp_mini_dag; - bool is_exist = false; - if (OB_FAIL(tmp_mini_dag.init_by_param(¶m))) { - LOG_WARN("failed to init mini dag", K(ret), K(param)); - } else if (OB_FAIL(MTL(ObTenantDagScheduler *)->check_dag_exist(&tmp_mini_dag, is_exist))) { - LOG_WARN("failed to check dag exists", K(ret), K(ls_id), K(tablet_id)); - } else if (is_exist) { - // we need to wait the current mini compaction dag to complete - ret = OB_EAGAIN; - LOG_WARN("exist running mini compaction dag, try later", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(get_ls_tablet_svr()->update_tablet_snapshot_version(tablet_id, freeze_snapshot_version.get_val_for_tx()))) { - LOG_WARN("failed to update tablet snapshot version", K(ret), K(ls_id), K(tablet_id), K(freeze_snapshot_version)); - } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); - } else if (protected_handle->get_max_saved_version_from_medium_info_recorder() >= freeze_snapshot_version.get_val_for_tx()) { - int tmp_ret = OB_SUCCESS; - if (OB_TMP_FAIL(compaction::ObTenantTabletScheduler::schedule_merge_dag( - ls_id, - *tablet, - MEDIUM_MERGE, - freeze_snapshot_version.get_val_for_tx()))) { - if (OB_SIZE_OVERFLOW != tmp_ret && OB_EAGAIN != tmp_ret) { - ret = tmp_ret; - LOG_WARN("failed to schedule medium merge dag", K(ret), K(ls_id), K(tablet_id)); - } - } else { - TRANS_LOG(INFO, "[Freezer] memtable_mgr doesn't have memtable", K(ret), K(ls_id), K(tablet_id)); - } - } - } else { - TRANS_LOG(INFO, "[Freezer] memtable_mgr has memtable", K(ret), K(ls_id), K(tablet_id)); - } - } else { - TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to set is_tablet_freeze"); - } - } else if (FALSE_IT(try_submit_log_for_freeze_(true/*tablet freeze*/))) { - } else if (OB_FAIL(submit_freeze_task(false/*is_ls_freeze*/, nullptr, frozen_memtable_handle))) { - TRANS_LOG(WARN, "[Freezer] fail to submit freeze_task", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to submit freeze_task"); - } else { - TRANS_LOG(INFO, "[Freezer] succeed to start tablet_freeze_with_rewrite_meta", K(ret), K(ls_id), K(tablet_id)); + ObTableHandleV2 frozen_memtable_handle; + const bool need_rewrite_meta = true; + if (OB_FAIL(do_tablet_freeze_(need_rewrite_meta, start_time, tablet_id, result, frozen_memtable_handle))) { + STORAGE_LOG(WARN, "tablet freeze failed", KR(ret), K(ls_id), K(tablet_id)); } if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) { - stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret); + stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObClockGenerator::getClock(), ret); print_freezer_statistics(); unset_freeze_(); } @@ -896,38 +842,188 @@ int ObFreezer::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id) return ret; } -int ObFreezer::tablet_freeze_task(ObTableHandleV2 handle) +int ObFreezer::do_tablet_freeze_(const bool need_rewrite_meta, + const int64_t start_time, + const ObTabletID &tablet_id, + ObFuture *result, + ObTableHandleV2 &frozen_memtable_handle) { int ret = OB_SUCCESS; share::ObLSID ls_id = get_ls_id(); - memtable::ObIMemtable *imemtable = nullptr; - memtable::ObMemtable *memtable = nullptr; + SCN freeze_snapshot_version; + ObTabletHandle tablet_handle; + ObTablet *tablet = nullptr; + ObProtectedMemtableMgrHandle *protected_handle = NULL; + if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) { + TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id)); + } else if (ObScnRange::MAX_SCN == freeze_snapshot_version || ObScnRange::MIN_SCN >= freeze_snapshot_version) { + ret = OB_MINOR_FREEZE_NOT_ALLOW; + LOG_WARN("[Freezer] invalid weak read scn", K(ret), K(ls_id)); + } else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) { + } else if (FALSE_IT(set_need_resubmit_log(false))) { + } else if (FALSE_IT(stat_.reset())) { + } else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(), + start_time, + ObFreezeState::NOT_SUBMIT_LOG, + freeze_snapshot_version, + tablet_id, + need_rewrite_meta))) { + TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id)); + } else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id, + tablet_handle, + ObTabletCommon::DEFAULT_GET_TABLET_NO_WAIT, + ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { + TRANS_LOG(WARN, "[Freezer] fail to get tablet for freeze", K(ret), K(ls_id), K(tablet_id)); + stat_.add_diagnose_info("fail to get tablet"); + } else if (FALSE_IT(tablet = tablet_handle.get_obj())) { + } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { + LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); + } else if (OB_FAIL(protected_handle->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) { + (void)handle_set_tablet_freeze_failed(need_rewrite_meta, tablet_id, ls_id, tablet, freeze_snapshot_version,ret); + } else if (OB_FAIL(submit_log_if_needed_(true /* is_tablet_freeze */, frozen_memtable_handle))) { + TRANS_LOG(WARN, "submit log if needed failed", KR(ret), K(frozen_memtable_handle)); + } else if (OB_FAIL(submit_freeze_task_(false /*is_ls_freeze*/, result, frozen_memtable_handle))) { + TRANS_LOG(WARN, "[Freezer] fail to submit freeze_task", K(ret), K(ls_id), K(tablet_id)); + stat_.add_diagnose_info("fail to submit freeze_task"); + } else { + TRANS_LOG(INFO, + "[Freezer] succeed to start tablet freeze task", + K(ret), + K(ls_id), + K(tablet_id), + K(need_rewrite_meta), + K(frozen_memtable_handle)); + } + return ret; +} + +void ObFreezer::handle_set_tablet_freeze_failed(const bool need_rewrite_meta, + const ObTabletID &tablet_id, + const ObLSID &ls_id, + const ObTablet *tablet, + const share::SCN freeze_snapshot_version, + int &ret) +{ + if (ret == OB_ENTRY_NOT_EXIST) { + if (need_rewrite_meta) { + ret = handle_no_active_memtable_(tablet_id, tablet, freeze_snapshot_version); + } else { + ret = OB_SUCCESS; + TRANS_LOG(INFO, "[Freezer] no need to freeze", K(ret), K(ls_id), K(tablet_id)); + stat_.add_diagnose_info("no need to freeze"); + } + } else { + TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id)); + stat_.add_diagnose_info("fail to set is_tablet_freeze"); + } +} + +int ObFreezer::handle_no_active_memtable_(const ObTabletID &tablet_id, + const ObTablet *tablet, + const SCN freeze_snapshot_version) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + ObProtectedMemtableMgrHandle *protected_handle = NULL; + if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { + LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); + } else if (!protected_handle->has_memtable()) { + // We need trigger a dag to rewrite the snapshot version of tablet + // meta for the major merge and medium merge. While the implementation + // need pay much attentio. + // 1. If we trigger the dag each time the freeze happened, there may + // be alive dag not finished, and we rewrite the tablet meta first. + // It will cause the snapshot version to be pushed by mistake. + // 2. We need fetch the weak read timestamp at first, otherwise the + // concurrent memtable creation may miscalculate the version + // + // NOTICE: use freeze_snapshot_version as input parameter + + // check exist mini compaction dag running + ObTabletMergeDagParam param; + param.merge_type_ = ObMergeType::MINI_MERGE; + param.merge_version_ = ObVersionRange::MIN_VERSION; + param.ls_id_ = ls_id; + param.tablet_id_ = tablet_id; + param.skip_get_tablet_ = true; + + ObProtectedMemtableMgrHandle *protected_handle = NULL; + ObTabletMiniMergeDag tmp_mini_dag; + bool is_exist = false; + if (OB_FAIL(tmp_mini_dag.init_by_param(¶m))) { + LOG_WARN("failed to init mini dag", K(ret), K(param)); + } else if (OB_FAIL(MTL(ObTenantDagScheduler *)->check_dag_exist(&tmp_mini_dag, is_exist))) { + LOG_WARN("failed to check dag exists", K(ret), K(ls_id), K(tablet_id)); + } else if (is_exist) { + // we need to wait the current mini compaction dag to complete + ret = OB_EAGAIN; + LOG_WARN("exist running mini compaction dag, try later", K(ret), K(ls_id), K(tablet_id)); + } else if (OB_FAIL(get_ls_tablet_svr()->update_tablet_snapshot_version(tablet_id, + freeze_snapshot_version.get_val_for_tx()))) { + LOG_WARN("failed to update tablet snapshot version", K(ret), K(ls_id), K(tablet_id), K(freeze_snapshot_version)); + } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { + LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); + } else if (protected_handle->get_max_saved_version_from_medium_info_recorder() >= + freeze_snapshot_version.get_val_for_tx()) { + int tmp_ret = OB_SUCCESS; + if (OB_TMP_FAIL(compaction::ObTenantTabletScheduler::schedule_merge_dag( + ls_id, *tablet, MEDIUM_MERGE, freeze_snapshot_version.get_val_for_tx()))) { + if (OB_SIZE_OVERFLOW != tmp_ret && OB_EAGAIN != tmp_ret) { + ret = tmp_ret; + LOG_WARN("failed to schedule medium merge dag", K(ret), K(ls_id), K(tablet_id)); + } + } else { + TRANS_LOG(INFO, "[Freezer] memtable_mgr doesn't have memtable", K(ret), K(ls_id), K(tablet_id)); + } + } + } else { + TRANS_LOG(INFO, "[Freezer] memtable_mgr has memtable", K(ret), K(ls_id), K(tablet_id)); + } + return ret; +} + +int ObFreezer::submit_log_if_needed_(const bool is_tablet_freeze, ObTableHandleV2 &handle) +{ + int ret = OB_SUCCESS; + ObITabletMemtable *tablet_memtable = nullptr; + + if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { + TRANS_LOG(WARN, "get tablet memtable failed", KR(ret), K(handle)); + } else if (OB_ISNULL(tablet_memtable)) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "tablet memtable is unexpected null", KR(ret), K(handle)); + } else if (tablet_memtable->is_direct_load_memtable()) { + // skip submit log cause direct load memtable unneeded + } else if (tablet_memtable->is_data_memtable()) { + (void)try_submit_log_for_freeze_(true /* is_tablet_freeze */); + } + return ret; +} + +int ObFreezer::tablet_freeze_task_(ObTableHandleV2 handle) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + ObITabletMemtable *tablet_memtable = nullptr; if (!handle.is_valid()) { ret = OB_ERR_UNEXPECTED; TRANS_LOG(WARN, "memtable cannot be null", K(ret), K(ls_id)); + } else if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { + LOG_WARN("fail to get memtable", K(ret), K(handle)); + } else if (OB_ISNULL(tablet_memtable)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get memtable", K(ret), K(handle)); } else { - // succeed to set freeze_flag - if (OB_FAIL(handle.get_memtable(imemtable))) { - LOG_WARN("fail to get memtable", K(ret)); - } else if (FALSE_IT(memtable = static_cast(imemtable))) { - } else if (OB_FAIL(wait_memtable_ready_for_flush_with_ls_lock(memtable))) { - TRANS_LOG(WARN, "[Freezer] fail to wait memtable ready_for_flush", K(ret), K(ls_id)); + if (tablet_memtable->is_data_memtable()) { + ret = do_data_memtable_tablet_freeze_(tablet_memtable); + } else if (tablet_memtable->is_direct_load_memtable()) { + ret = do_direct_load_memtable_tablet_freeze_(tablet_memtable); } else { - int64_t read_lock = LSLOCKALL; - int64_t write_lock = 0; - ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock); - if (OB_FAIL(check_ls_state())) { - } else if (OB_FAIL(memtable->finish_freeze())) { - TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed", - K(ret), K(ls_id), KPC(memtable)); - stat_.add_diagnose_info("memtable cannot be flushed"); - } else { - stat_.add_diagnose_info("tablet_freeze success"); - FLOG_INFO("[Freezer] tablet_freeze_task success", K(ret), K(ls_id), KPC(memtable)); - } + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "unexpected memtable type", KR(ret), KPC(tablet_memtable)); } - stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret); + stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObClockGenerator::getClock(), ret); print_freezer_statistics(); unset_freeze_(); } @@ -935,7 +1031,53 @@ int ObFreezer::tablet_freeze_task(ObTableHandleV2 handle) return ret; } -int ObFreezer::wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable *memtable) +int ObFreezer::do_data_memtable_tablet_freeze_(ObITabletMemtable *tablet_memtable) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + ObMemtable *memtable = static_cast(tablet_memtable); + if (OB_FAIL(wait_memtable_ready_for_flush_with_ls_lock(memtable))) { + TRANS_LOG(WARN, "[Freezer] fail to wait memtable ready_for_flush", K(ret), K(ls_id)); + } else { + int64_t read_lock = LSLOCKALL; + int64_t write_lock = 0; + ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock); + if (OB_FAIL(check_ls_state())) { + } else if (OB_FAIL(memtable->finish_freeze())) { + TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed", K(ret), K(ls_id), KPC(memtable)); + stat_.add_diagnose_info("memtable cannot be flushed"); + } else { + stat_.add_diagnose_info("tablet_freeze success"); + FLOG_INFO("[Freezer] tablet_freeze_task success", K(ret), K(ls_id), KPC(memtable)); + } + } + return ret; +} + +int ObFreezer::do_direct_load_memtable_tablet_freeze_(ObITabletMemtable *tablet_memtable) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + ObDDLKV *direct_load_memtable = static_cast(tablet_memtable); + if (OB_FAIL(direct_load_memtable->decide_right_boundary())) { + STORAGE_LOG(WARN, "freeze direct load memtable failed", KR(ret), K(ls_id), KPC(tablet_memtable)); + } else { + int64_t read_lock = LSLOCKALL; + int64_t write_lock = 0; + ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock); + if (OB_FAIL(check_ls_state())) { + } else if (OB_FAIL(tablet_memtable->finish_freeze())) { + TRANS_LOG(ERROR, "[Freezer] direct load memtable cannot be flushed", K(ret), K(ls_id), KPC(tablet_memtable)); + stat_.add_diagnose_info("direct load memtable cannot be flushed"); + } else { + stat_.add_diagnose_info("tablet_freeze success"); + FLOG_INFO("[Freezer] freeze direct load memtable success", K(ls_id), KP(this), KP(tablet_memtable)); + } + } + return ret; +} + +int ObFreezer::wait_memtable_ready_for_flush_with_ls_lock(ObITabletMemtable *tablet_memtable) { share::ObLSID ls_id = get_ls_id(); const int64_t start = ObTimeUtility::current_time(); @@ -943,7 +1085,7 @@ int ObFreezer::wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable * bool ready_for_flush = false; do { - if (OB_FAIL(try_wait_memtable_ready_for_flush_with_ls_lock(memtable, ready_for_flush, start))) { + if (OB_FAIL(try_wait_memtable_ready_for_flush_with_ls_lock(tablet_memtable, ready_for_flush, start))) { TRANS_LOG(WARN, "[Freezer] memtable is not ready_for_flush", K(ret)); } } while (OB_SUCC(ret) && !ready_for_flush); @@ -951,7 +1093,9 @@ int ObFreezer::wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable * return ret; } -int ObFreezer::try_wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable *memtable, bool &ready_for_flush, const int64_t start) +int ObFreezer::try_wait_memtable_ready_for_flush_with_ls_lock(ObITabletMemtable *tablet_memtable, + bool &ready_for_flush, + const int64_t start) { int ret = OB_SUCCESS; int64_t read_lock = LSLOCKALL; @@ -959,10 +1103,10 @@ int ObFreezer::try_wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtab ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock); if (OB_FAIL(check_ls_state())) { - } else if (OB_ISNULL(memtable)) { + } else if (OB_ISNULL(tablet_memtable)) { ret = OB_ERR_UNEXPECTED; TRANS_LOG(WARN, "[Freezer] memtable cannot be null", K(ret)); - } else if (FALSE_IT(ready_for_flush = memtable->ready_for_flush())) { + } else if (FALSE_IT(ready_for_flush = tablet_memtable->ready_for_flush())) { } else if (!ready_for_flush) { if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) { if (need_resubmit_log()) { @@ -973,7 +1117,7 @@ int ObFreezer::try_wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtab if (cost_time > 5 * 1000 * 1000) { TRANS_LOG(WARN, "[Freezer] ready_for_flush costs too much time", - K(cost_time), KPC(memtable)); + K(cost_time), KPC(tablet_memtable)); stat_.add_diagnose_info("ready_for_flush costs too much time"); } } @@ -984,105 +1128,6 @@ int ObFreezer::try_wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtab return ret; } -int ObFreezer::tablet_freeze_for_replace_tablet_meta(const ObTabletID &tablet_id, ObTableHandleV2 &frozen_memtable_handle) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = get_ls_id(); - ObTabletHandle handle; - ObTablet *tablet = nullptr; - SCN freeze_snapshot_version; - FLOG_INFO("[Freezer] tablet_freeze_for_replace_tablet_meta start", K(ret), K(ls_id), K(tablet_id)); - int64_t start_time = ObTimeUtility::current_time(); - ObProtectedMemtableMgrHandle *protected_handle = NULL; - - ObTabletFreezeGuard guard(*this, true /* try guard */); - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "[Freezer] not inited", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_UNLIKELY(!enable_)) { - ret = OB_NOT_RUNNING; - LOG_WARN("freezer is offline, can not freeze now", K(ret), K(ls_id)); - } else if (OB_FAIL(guard.try_set_tablet_freeze_begin())) { - // no need freeze now, a ls freeze is running or will be running - FLOG_INFO("[Freezer] ls freeze is running, no need freeze again", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(loop_set_freeze_flag())) { - FLOG_INFO("[Freezer] freeze is running", K(ret), K(ls_id), K(tablet_id)); - } else { - // succeed to set freeze flag - if (OB_FAIL(get_ls_weak_read_scn(freeze_snapshot_version))) { - TRANS_LOG(WARN, "[Freezer] get ls weak read ts failure", K(ret), K(ls_id)); - } else if (freeze_snapshot_version.is_max() - || !freeze_snapshot_version.is_valid_and_not_min()) { - ret = OB_NOT_INIT; - LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id)); - } else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) { - } else if (FALSE_IT(set_need_resubmit_log(false))) { - } else if (FALSE_IT(stat_.reset())) { - } else if (OB_FAIL(stat_.begin_set_freeze_stat(get_freeze_clock(), - start_time, - ObFreezeState::NOT_SUBMIT_LOG, - freeze_snapshot_version, - tablet_id, - false/*need_rewrite_meta*/))) { - TRANS_LOG(WARN, "[Freezer] fail to begin_set_freeze_stat", K(ret), K(ls_id)); - } else if (OB_FAIL(get_ls_tablet_svr()->get_tablet(tablet_id, - handle, 0, - ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { - TRANS_LOG(WARN, "[Freezer] fail to get tablet", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to get tablet"); - } else if (FALSE_IT(tablet = handle.get_obj())) { - } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); - } else if (OB_FAIL(protected_handle->set_is_tablet_freeze_for_active_memtable(frozen_memtable_handle))) { - if (ret == OB_ENTRY_NOT_EXIST) { - ret = OB_SUCCESS; - TRANS_LOG(INFO, "[Freezer] no need to freeze", K(ret), - K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("no need to freeze"); - } else { - TRANS_LOG(WARN, "[Freezer] fail to set is_tablet_freeze", K(ret), K(ls_id), K(tablet_id)); - stat_.add_diagnose_info("fail to set is_tablet_freeze"); - } - } - if (OB_FAIL(ret) || !frozen_memtable_handle.is_valid()) { - stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret); - print_freezer_statistics(); - unset_freeze_(); - } - } - - return ret; -} - -// NOTICE: not called by user now -// must ensure that call tablet_freeze_for_replace_tablet_meta() successfully before calling the func -int ObFreezer::handle_frozen_memtable_for_replace_tablet_meta(const ObTabletID &tablet_id, ObTableHandleV2 &handle) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = get_ls_id(); - memtable::ObIMemtable *imemtable = nullptr; - - if (!handle.is_valid()) { - ret = OB_SUCCESS; - FLOG_INFO("[Freezer] no need to tablet_freeze_for_replace_tablet_meta", K(ret), K(ls_id), K(tablet_id)); - } else { - // succeed to set freeze flag - if (OB_FAIL(handle.get_memtable(imemtable))) { - TRANS_LOG(WARN, "[Freezer] fail to get memtable", K(ret)); - } else if (OB_FAIL(handle_memtable_for_tablet_freeze(imemtable))) { - TRANS_LOG(WARN, "[Freezer] fail to handle memtable", K(ret), K(ls_id), K(tablet_id)); - } else { - stat_.add_diagnose_info("tablet_freeze_for_replace_tablet_meta success"); - FLOG_INFO("[Freezer] tablet_freeze_for_replace_tablet_meta success", K(ret), K(ls_id), K(tablet_id)); - } - stat_.end_set_freeze_stat(ObFreezeState::FINISH, ObTimeUtility::current_time(), ret); - print_freezer_statistics(); - unset_freeze_(); - } - - return ret; -} - int ObFreezer::batch_tablet_freeze(const int64_t trace_id, const ObIArray &tablet_ids, ObFuture *result) { int ret = OB_SUCCESS; @@ -1111,8 +1156,8 @@ int ObFreezer::batch_tablet_freeze(const int64_t trace_id, const ObIArray= freeze_snapshot_version) { - ret = OB_NOT_INIT; - LOG_WARN("[Freezer] weak read service not inited", K(ret), K(ls_id)); + ret = OB_MINOR_FREEZE_NOT_ALLOW; + LOG_WARN("[Freezer] invalid weak read scn", K(ret), K(ls_id)); } else if (FALSE_IT(freeze_snapshot_version_ = freeze_snapshot_version)) { } else if (FALSE_IT(set_need_resubmit_log(false))) { } else if (FALSE_IT(stat_.reset())) { @@ -1237,22 +1282,20 @@ int ObFreezer::batch_tablet_freeze_task(ObTableHandleArray tables_array) while (OB_SUCC(ret) && tables_array.count() > 0) { for (int i = 0; OB_SUCC(ret) && i < tables_array.count(); ++i) { ObTableHandleV2 &handle = tables_array.at(i); - memtable::ObIMemtable *imemtable = nullptr; - memtable::ObMemtable *memtable = nullptr; + ObITabletMemtable *tablet_memtable = nullptr; bool ready_for_flush = false; if (!handle.is_valid()) { ret = OB_ERR_UNEXPECTED; TRANS_LOG(WARN, "memtable cannot be null", K(ret), K(ls_id)); - } else if (OB_FAIL(handle.get_memtable(imemtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { LOG_WARN("fail to get memtable", K(ret)); - } else if (FALSE_IT(memtable = static_cast(imemtable))) { - } else if (OB_FAIL(try_wait_memtable_ready_for_flush_with_ls_lock(memtable, ready_for_flush, start))) { + } else if (OB_FAIL(try_wait_memtable_ready_for_flush_with_ls_lock(tablet_memtable, ready_for_flush, start))) { TRANS_LOG(WARN, "[Freezer] fail to wait memtable ready_for_flush", K(ret), K(ls_id)); } else if (!ready_for_flush) { - } else if (OB_FAIL(finish_freeze_with_ls_lock(memtable))) { - TRANS_LOG(WARN, "[Freezer] fail to finish_freeze", K(ret), K(ls_id), KPC(memtable)); + } else if (OB_FAIL(finish_freeze_with_ls_lock(tablet_memtable))) { + TRANS_LOG(WARN, "[Freezer] fail to finish_freeze", K(ret), K(ls_id), KPC(tablet_memtable)); } else if (OB_FAIL(tables_array.pop_back(handle))) { - TRANS_LOG(WARN, "[Freezer] fail to pop_back", K(ret), K(ls_id), K(handle), KPC(memtable)); + TRANS_LOG(WARN, "[Freezer] fail to pop_back", K(ret), K(ls_id), K(handle), KPC(tablet_memtable)); } } } @@ -1268,7 +1311,7 @@ int ObFreezer::batch_tablet_freeze_task(ObTableHandleArray tables_array) return ret; } -int ObFreezer::finish_freeze_with_ls_lock(memtable::ObMemtable *memtable) +int ObFreezer::finish_freeze_with_ls_lock(ObITabletMemtable *tablet_memtable) { int ret = OB_SUCCESS; share::ObLSID ls_id = get_ls_id(); @@ -1277,12 +1320,12 @@ int ObFreezer::finish_freeze_with_ls_lock(memtable::ObMemtable *memtable) ObLSLockGuard lock_ls(ls_, ls_->lock_, read_lock, write_lock); if (OB_FAIL(check_ls_state())) { - } else if (OB_ISNULL(memtable)) { + } else if (OB_ISNULL(tablet_memtable)) { ret = OB_ERR_UNEXPECTED; TRANS_LOG(WARN, "[Freezer] memtable cannot be null", K(ret)); - } else if (OB_FAIL(memtable->finish_freeze())) { + } else if (OB_FAIL(tablet_memtable->finish_freeze())) { TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed", - K(ret), K(ls_id), KPC(memtable)); + K(ret), K(ls_id), KPC(tablet_memtable)); stat_.add_diagnose_info("memtable cannot be flushed"); } @@ -1291,7 +1334,7 @@ int ObFreezer::finish_freeze_with_ls_lock(memtable::ObMemtable *memtable) // NOTICE: not called by user now /* private subfunctions for freeze process */ -int ObFreezer::handle_memtable_for_tablet_freeze(memtable::ObIMemtable *imemtable) +int ObFreezer::handle_memtable_for_tablet_freeze(ObIMemtable *imemtable) { int ret = OB_SUCCESS; share::ObLSID ls_id = get_ls_id(); @@ -1299,16 +1342,16 @@ int ObFreezer::handle_memtable_for_tablet_freeze(memtable::ObIMemtable *imemtabl if (OB_ISNULL(imemtable)) { ret = OB_ERR_UNEXPECTED; } else { - memtable::ObMemtable *memtable = static_cast(imemtable); + ObITabletMemtable *tablet_memtable = static_cast(imemtable); try_submit_log_for_freeze_(true/*tablet freeze*/); - wait_memtable_ready_for_flush(memtable); - if (OB_FAIL(memtable->finish_freeze())) { + wait_memtable_ready_for_flush(tablet_memtable); + if (OB_FAIL(tablet_memtable->finish_freeze())) { TRANS_LOG(ERROR, "[Freezer] memtable cannot be flushed", - K(ret), K(ls_id), K(*memtable)); + K(ret), K(ls_id), KPC(tablet_memtable)); stat_.add_diagnose_info("memtable cannot be flushed"); } else { TRANS_LOG(INFO, "[Freezer] memtable is ready to be flushed", - K(ret), K(ls_id), K(*memtable)); + K(ret), K(ls_id), KPC(tablet_memtable)); } } @@ -1384,7 +1427,9 @@ int ObFreezer::submit_log_for_freeze(const bool is_tablet_freeze, const bool is_ return ret; } -int ObFreezer::submit_freeze_task(const bool is_ls_freeze, ObFuture *result, ObTableHandleV2 &handle) +int ObFreezer::submit_freeze_task_(const bool is_ls_freeze, + ObFuture *result, + ObTableHandleV2 &memtable_handle) { int ret = OB_SUCCESS; ObTenantFreezer *tenant_freezer = nullptr; @@ -1399,19 +1444,49 @@ int ObFreezer::submit_freeze_task(const bool is_ls_freeze, ObFuture *result do { if (OB_ISNULL(result)) { if (is_ls_freeze) { - ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret([this]() { - return ls_freeze_task(); }); + struct TmpFreezerFunc { + int operator() () { + return freezer_->ls_freeze_task_(); + } + TmpFreezerFunc(ObFreezer *freezer) : freezer_(freezer) { + } + ObFreezer *freezer_; + } tmp_freezer_func(this); + ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret(tmp_freezer_func); } else { - ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret([this, handle]() { - return tablet_freeze_task(handle); }); + struct TmpFreezerFunc { + int operator() () { + return freezer_->tablet_freeze_task_(memtable_handle_); + } + TmpFreezerFunc(ObFreezer *freezer, ObTableHandleV2 memtable_handle) : freezer_(freezer), memtable_handle_(memtable_handle) { + } + ObFreezer *freezer_; + ObTableHandleV2 memtable_handle_; + } tmp_freezer_func(this, memtable_handle); + ret = tenant_freezer->freeze_thread_pool_.commit_task_ignore_ret(tmp_freezer_func); } } else { if (is_ls_freeze) { - ret = tenant_freezer->freeze_thread_pool_.commit_task(*result, - [this]() { return ls_freeze_task(); }); + struct TmpFreezerFunc { + int operator() () { + return freezer_->ls_freeze_task_(); + } + TmpFreezerFunc(ObFreezer *freezer) : freezer_(freezer) { + } + ObFreezer *freezer_; + } tmp_freezer_func(this); + ret = tenant_freezer->freeze_thread_pool_.commit_task(*result, tmp_freezer_func); } else { - ret = tenant_freezer->freeze_thread_pool_.commit_task(*result, - [this, handle]() { return tablet_freeze_task(handle); }); + struct TmpFreezerFunc { + int operator() () { + return freezer_->tablet_freeze_task_(memtable_handle_); + } + TmpFreezerFunc(ObFreezer *freezer, ObTableHandleV2 memtable_handle) : freezer_(freezer), memtable_handle_(memtable_handle) { + } + ObFreezer *freezer_; + ObTableHandleV2 memtable_handle_; + } tmp_freezer_func(this, memtable_handle); + ret = tenant_freezer->freeze_thread_pool_.commit_task(*result, tmp_freezer_func); } } @@ -1451,13 +1526,13 @@ int ObFreezer::wait_freeze_finished(ObFuture &result) return ret; } -void ObFreezer::wait_memtable_ready_for_flush(memtable::ObMemtable *memtable) +void ObFreezer::wait_memtable_ready_for_flush(ObITabletMemtable *tablet_memtable) { share::ObLSID ls_id = get_ls_id(); const int64_t start = ObTimeUtility::current_time(); int ret = OB_SUCCESS; - while (!memtable->ready_for_flush()) { + while (!tablet_memtable->ready_for_flush()) { if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) { if (need_resubmit_log()) { submit_log_for_freeze(true/*tablet freeze*/, false/*try*/); @@ -1467,89 +1542,30 @@ void ObFreezer::wait_memtable_ready_for_flush(memtable::ObMemtable *memtable) if (cost_time > 5 * 1000 * 1000) { TRANS_LOG_RET(WARN, OB_ERR_TOO_MUCH_TIME, "[Freezer] ready_for_flush costs too much time", - K(ls_id), K(cost_time), KPC(memtable)); + K(ls_id), K(cost_time), KPC(tablet_memtable)); stat_.add_diagnose_info("ready_for_flush costs too much time"); - memtable->print_ready_for_flush(); + tablet_memtable->print_ready_for_flush(); } } ob_usleep(100); } } -int ObFreezer::create_memtable_if_no_active_memtable(ObTablet *tablet) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = get_ls_id(); - ObTableHandleV2 last_frozen_memtable_handle; - memtable::ObMemtable *last_frozen_memtable = nullptr; - const common::ObTabletID &tablet_id = tablet->get_tablet_meta().tablet_id_; - SCN clog_checkpoint_scn = tablet->get_tablet_meta().clog_checkpoint_scn_; - int64_t schema_version = 0; - SCN max_callbacked_scn = SCN::min_scn(); - bool has_active_memtable = false; - ObProtectedMemtableMgrHandle *protected_handle = NULL; - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - LOG_WARN("[Freezer] not inited", K(ret), K_(is_inited), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(get_max_consequent_callbacked_scn(max_callbacked_scn))) { - LOG_WARN("[Freezer] fail to get max_consequent_callbacked_scn", K(ret), K(ls_id), K(tablet_id)); - } else if (max_callbacked_scn < clog_checkpoint_scn) { - ret = OB_NO_NEED_UPDATE; - LOG_WARN("[Freezer] cannot create memtable because max_callbacked_scn < clog_checkpoint_scn", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(tablet->get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(tablet)); - } else if (protected_handle->has_active_memtable()) { - LOG_INFO("[Freezer] no need to create an active memtable", K(ret), K(ls_id), K(tablet_id)); - } else { // create a new memtable since there is no active memtable - // get schema_version - if (OB_FAIL(protected_handle->get_last_frozen_memtable(last_frozen_memtable_handle))) { - if (OB_ENTRY_NOT_EXIST != ret) { - LOG_WARN("[Freezer] fail to get last frozen memtable", K(ret), K(ls_id), K(tablet_id)); - } else { - ret = OB_SUCCESS; - } - } else if (OB_FAIL(last_frozen_memtable_handle.get_data_memtable(last_frozen_memtable))) { - LOG_WARN("[Freezer] fail to get memtable", K(ret), K(ls_id), K(tablet_id)); - } - if (OB_FAIL(ret)) { - } else if (OB_NOT_NULL(last_frozen_memtable)) { - schema_version = last_frozen_memtable->get_max_schema_version(); - } else { - schema_version = tablet->get_tablet_meta().max_sync_storage_schema_version_; - //do nothing - } - // create new memtable - if (OB_SUCC(ret)) { - if (OB_FAIL(get_ls_tablet_svr()->create_memtable(tablet_id, schema_version))) { - if (OB_MINOR_FREEZE_NOT_ALLOW != ret) { - LOG_WARN("[Freezer] failed to create memtable", K(ret), K(ls_id), K(tablet_id), - K(schema_version)); - } - } else { - LOG_INFO("[Freezer] succeed to create new active memtable", K(ret), K(ls_id), - K(tablet_id), K(schema_version)); - } - } - } - - return ret; -} /* private subfunctions about freeze flag*/ int ObFreezer::loop_set_freeze_flag() { int ret = OB_SUCCESS; share::ObLSID ls_id = get_ls_id(); - const int64_t start = ObTimeUtility::current_time(); + const int64_t start = ObClockGenerator::getClock(); do { ret = OB_SUCCESS; if (OB_FAIL(set_freeze_flag_without_inc_freeze_clock())) { - const int64_t cost_time = ObTimeUtility::current_time() - start; - if (cost_time > 10 * 1000 * 1000) { - TRANS_LOG(WARN, "[Freezer] wait the running freeze too long time", K(ls_id), - K(cost_time)); + const int64_t MAX_LOOP_TIME = 10LL * 1000LL * 1000LL; // 10 seconds + const int64_t cost_time = ObClockGenerator::getClock() - start; + if (cost_time > MAX_LOOP_TIME) { + TRANS_LOG(WARN, "[Freezer] wait the running freeze too long time", K(ls_id), K(cost_time)); break; } ob_usleep(100); @@ -1601,29 +1617,6 @@ int ObFreezer::set_freeze_flag() return ret; } -int ObFreezer::inc_freeze_clock() -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = get_ls_id(); - uint32_t old_v = 0; - uint32_t new_v = 0; - - // inc freeze_clock when freeze_flag has been set - // before used by rewrite_tablet_meta to resolve concurrency problems - do { - old_v = ATOMIC_LOAD(&freeze_flag_); - if (!is_freeze(old_v)) { - ret = OB_ERR_UNEXPECTED; - TRANS_LOG(WARN, "[Freezer] cannot inc freeze clock without setting freeze flag!", - K(ret), K(ls_id)); - break; - } - new_v = old_v + 1; - } while (ATOMIC_CAS(&freeze_flag_, old_v, new_v) != old_v); - - return ret; -} - void ObFreezer::unset_freeze_() { uint32_t old_v; diff --git a/src/storage/ls/ob_freezer.h b/src/storage/ls/ob_freezer.h index 7417f1b9c..7ccfb0011 100644 --- a/src/storage/ls/ob_freezer.h +++ b/src/storage/ls/ob_freezer.h @@ -36,17 +36,17 @@ class ObILogHandler; }; namespace memtable { -class ObIMemtable; class ObMemtable; } namespace storage { +class ObIMemtable; class ObLSTxService; class ObLSTabletService; class ObTablet; class ObLSWRSHandler; class ObTableHandleV2; -class ObLSIterator; +struct FreezeTaskFunctor; namespace checkpoint { class ObDataCheckpoint; @@ -163,6 +163,7 @@ private: class ObFreezer { public: + friend FreezeTaskFunctor; static const int64_t MAX_WAIT_READY_FOR_FLUSH_TIME = 10 * 1000 * 1000; // 10_s typedef common::ObSEArray ObTableHandleArray; @@ -178,11 +179,11 @@ public: public: /* freeze */ + void commit_async_tablet_freeze_task_once(const ObTabletID &tablet_id, const uint64_t epoch); int logstream_freeze(const int64_t trace_id, ObFuture *result = nullptr); int tablet_freeze(const ObTabletID &tablet_id, ObFuture *result = nullptr); - int tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id); - int tablet_freeze_for_replace_tablet_meta(const ObTabletID &tablet_id, ObTableHandleV2 &handle); - int handle_frozen_memtable_for_replace_tablet_meta(const ObTabletID &tablet_id, ObTableHandleV2 &handle); + int tablet_freeze_task_for_direct_load(const ObTabletID &tablet_id, ObFuture *result = nullptr); + int tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, ObFuture *result = nullptr); int batch_tablet_freeze(const int64_t trace_id, const ObIArray &tablet_ids, ObFuture *result = nullptr); /* freeze_flag */ @@ -259,7 +260,6 @@ private: int set_freeze_flag(); int set_freeze_flag_without_inc_freeze_clock(); int loop_set_freeze_flag(); - int inc_freeze_clock(); void unset_freeze_(); void undo_freeze_(); void try_freeze_tx_data_(); @@ -267,27 +267,48 @@ private: /* inner subfunctions for freeze process */ int inner_logstream_freeze(ObFuture *result); int submit_log_for_freeze(const bool is_tablet_freeze, const bool is_try); + int submit_log_if_needed_(const bool is_tablet_freeze, ObTableHandleV2 &handle); void try_submit_log_for_freeze_(const bool is_tablet_freeze); - int ls_freeze_task(); - int tablet_freeze_task(ObTableHandleV2 handle); - int submit_freeze_task(const bool is_ls_freeze, ObFuture *result, ObTableHandleV2 &handle); - void wait_memtable_ready_for_flush(memtable::ObMemtable *memtable); - int wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable *memtable); - int handle_memtable_for_tablet_freeze(memtable::ObIMemtable *imemtable); - int create_memtable_if_no_active_memtable(ObTablet *tablet); + int ls_freeze_task_(); + int tablet_freeze_task_(ObTableHandleV2 handle); + int tablet_freeze_task_for_direct_load_(const ObTabletID &tablet_id, const uint64_t epoch); + int do_data_memtable_tablet_freeze_(ObITabletMemtable *tablet_memtable); + int do_direct_load_memtable_tablet_freeze_(ObITabletMemtable *tablet_memtable); + int do_tablet_freeze_(const bool need_rewrite_meta, + const int64_t start_time, + const ObTabletID &tablet_id, + ObFuture *result, + ObTableHandleV2 &frozen_memtable_handle); + int handle_no_active_memtable_(const ObTabletID &tablet_id, + const ObTablet *tablet, + const share::SCN freeze_snapshot_version); + void handle_set_tablet_freeze_failed(const bool need_rewrite_meta, + const ObTabletID &tablet_id, + const ObLSID &ls_id, + const ObTablet *tablet, + const share::SCN freeze_snapshot_version, + int &ret); + int submit_freeze_task_(const bool is_ls_freeze, ObFuture *result, ObTableHandleV2 &handle); + void wait_memtable_ready_for_flush(ObITabletMemtable *tablet_memtable); + int wait_memtable_ready_for_flush_with_ls_lock(ObITabletMemtable *tablet_memtable); + int handle_memtable_for_tablet_freeze(ObIMemtable *imemtable); int try_set_tablet_freeze_begin_(); void set_tablet_freeze_begin_(); void set_tablet_freeze_end_(); void set_ls_freeze_begin_(); void set_ls_freeze_end_(); int check_ls_state(); // must be used under the protection of ls_lock - int freeze_normal_tablet_(const ObTabletID &tablet_id, ObFuture *result = nullptr); + int freeze_normal_tablet_(const ObTabletID &tablet_id, + ObFuture *result = nullptr, + const bool for_direct_load = false); int freeze_ls_inner_tablet_(const ObTabletID &tablet_id); int batch_tablet_freeze_(const int64_t trace_id, const ObIArray &tablet_ids, ObFuture *result, bool &need_freeze); int submit_batch_tablet_freeze_task(const ObTableHandleArray &tables_array, ObFuture *result); int batch_tablet_freeze_task(ObTableHandleArray tables_array); - int finish_freeze_with_ls_lock(memtable::ObMemtable *memtable); - int try_wait_memtable_ready_for_flush_with_ls_lock(memtable::ObMemtable *memtable, bool &ready_for_flush, const int64_t start); + int finish_freeze_with_ls_lock(ObITabletMemtable *tablet_memtable); + int try_wait_memtable_ready_for_flush_with_ls_lock(ObITabletMemtable *tablet_memtable, + bool &ready_for_flush, + const int64_t start); void submit_checkpoint_task(); private: // flag whether the logsteram is freezing diff --git a/src/storage/ls/ob_ls.cpp b/src/storage/ls/ob_ls.cpp index 400a6f3a0..ced319e4f 100644 --- a/src/storage/ls/ob_ls.cpp +++ b/src/storage/ls/ob_ls.cpp @@ -61,6 +61,7 @@ #include "storage/tx/ob_trans_service.h" #include "storage/tx/ob_tx_log_adapter.h" #include "storage/tx_table/ob_tx_table.h" +#include "storage/tx_storage/ob_tenant_freezer.h" #include "storage/meta_mem/ob_meta_obj_struct.h" #include "storage/meta_mem/ob_tablet_handle.h" #include "storage/meta_mem/ob_tablet_map_key.h" @@ -1836,7 +1837,7 @@ int ObLS::logstream_freeze(const int64_t trace_id, const bool is_sync, const int ret = OB_NOT_INIT; LOG_WARN("ls is not inited", K(ret)); } else if (OB_UNLIKELY(is_offline())) { - ret = OB_MINOR_FREEZE_NOT_ALLOW; + ret = OB_LS_OFFLINE; LOG_WARN("offline ls not allowed freeze", K(ret), K_(ls_meta)); } else if (OB_FAIL(ls_freezer_.logstream_freeze(trace_id, &result))) { LOG_WARN("logstream freeze failed", K(ret), K_(ls_meta)); @@ -1870,7 +1871,7 @@ int ObLS::tablet_freeze(const ObTabletID &tablet_id, ret = OB_NOT_INIT; LOG_WARN("ls is not inited", K(ret)); } else if (OB_UNLIKELY(is_offline())) { - ret = OB_MINOR_FREEZE_NOT_ALLOW; + ret = OB_LS_OFFLINE; LOG_WARN("offline ls not allowed freeze", K(ret), K_(ls_meta)); } else if (OB_FAIL(ls_freezer_.tablet_freeze(tablet_id, &result))) { LOG_WARN("tablet freeze failed", K(ret), K(tablet_id)); @@ -1886,7 +1887,9 @@ int ObLS::tablet_freeze(const ObTabletID &tablet_id, return ret; } -int ObLS::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, const int64_t abs_timeout_ts) +int ObLS::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, + ObFuture *result, + const int64_t abs_timeout_ts) { int ret = OB_SUCCESS; int64_t read_lock = LSLOCKALL; @@ -1899,9 +1902,9 @@ int ObLS::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, const int ret = OB_NOT_INIT; LOG_WARN("ls is not inited", K(ret)); } else if (OB_UNLIKELY(is_offline())) { - ret = OB_MINOR_FREEZE_NOT_ALLOW; + ret = OB_LS_OFFLINE; LOG_WARN("offline ls not allowed freeze", K(ret), K_(ls_meta)); - } else if (OB_FAIL(ls_freezer_.tablet_freeze_with_rewrite_meta(tablet_id))) { + } else if (OB_FAIL(ls_freezer_.tablet_freeze_with_rewrite_meta(tablet_id, result))) { LOG_WARN("tablet force freeze failed", K(ret), K(tablet_id)); } else { // do nothing @@ -1909,6 +1912,78 @@ int ObLS::tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, const int return ret; } +/** + * @brief Used for async freeze task + * + * @param tablet_id tablet to be freezed + * @param epoch to check if logstream has offlined + */ +int ObLS::tablet_freeze_task_for_direct_load(const ObTabletID &tablet_id, const uint64_t epoch, ObFuture *result) +{ + int ret = OB_SUCCESS; + int64_t read_lock = LSLOCKALL; + int64_t write_lock = 0; + ObLSLockGuard lock_myself(this, lock_, read_lock, write_lock); + if (!lock_myself.locked()) { + ret = OB_TIMEOUT; + STORAGE_LOG(WARN, "lock failed, please retry later", K(ret), K(ls_meta_)); + } else if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + STORAGE_LOG(WARN, "ls is not inited", K(ret)); + } else if (OB_UNLIKELY(is_offline()) || ATOMIC_LOAD(&switch_epoch_) != epoch) { + ret = OB_LS_OFFLINE; + LOG_WARN("ls has offlined", K(ret), K_(ls_meta)); + } else if (OB_FAIL(ls_freezer_.tablet_freeze_task_for_direct_load(tablet_id, result))) { + LOG_WARN("tablet force freeze failed", K(ret), K(tablet_id)); + } else { + // freeze success + } + + if (OB_FAIL(ret)) { + if (OB_NOT_INIT == ret || OB_NOT_RUNNING == ret || OB_LS_OFFLINE == ret) { + STORAGE_LOG(INFO, "reset ret code to stop retry", KR(ret)); + ret = OB_SUCCESS; + } else { + // reset ret to EAGAIN to retry freeze + ret = OB_EAGAIN; + } + } + return ret; +} + +int ObLS::sync_tablet_freeze_for_direct_load(const ObTabletID &tablet_id, const int64_t max_retry_time) +{ + int ret = OB_SUCCESS; + const uint64_t epoch = ATOMIC_LOAD(&switch_epoch_); + const int64_t start_time = ObClockGenerator::getClock(); + const int64_t RETRY_INTERVAL = 100 * 1000; // 100 ms + + do { + ret = OB_SUCCESS; + ObFuture result; + if (OB_FAIL(tablet_freeze_task_for_direct_load(tablet_id, epoch, &result))) { + if (REACH_TIME_INTERVAL(1LL * 1000LL * 1000LL /* 1 second */)) { + LOG_INFO("fail to start tablet freeze. need retry", K(ret), K(tablet_id)); + } + usleep(RETRY_INTERVAL); + } else if (OB_FAIL(ls_freezer_.wait_freeze_finished(result))) { + STORAGE_LOG(WARN, "freeze task failed", KR(ret)); + } + } while (OB_FAIL(ret) && ObClockGenerator::getClock() - start_time < max_retry_time); + return ret; +} + +/** + * @brief Record switch_epoch when commit the root freeze task. Async tablet freeze task will check if epoch is the + * same. + */ +void ObLS::async_tablet_freeze_for_direct_load(const ObTabletID &tablet_id) +{ + const uint64_t epoch = ATOMIC_LOAD(&switch_epoch_); + FLOG_INFO("commit root freeze task", K(tablet_id), K(epoch)); + (void)ls_freezer_.commit_async_tablet_freeze_task_once(tablet_id, epoch); +} + int ObLS::batch_tablet_freeze(const int64_t trace_id, const ObIArray &tablet_ids, const bool is_sync, @@ -1928,7 +2003,7 @@ int ObLS::batch_tablet_freeze(const int64_t trace_id, ret = OB_NOT_INIT; LOG_WARN("ls is not inited", K(ret)); } else if (OB_UNLIKELY(is_offline())) { - ret = OB_MINOR_FREEZE_NOT_ALLOW; + ret = OB_LS_OFFLINE; LOG_WARN("offline ls not allowed freeze", K(ret), K_(ls_meta)); } else if (OB_FAIL(ls_freezer_.batch_tablet_freeze(trace_id, tablet_ids, &result))) { LOG_WARN("batch tablet freeze failed", K(ret)); @@ -2168,7 +2243,6 @@ int ObLS::disable_replay_without_lock() return ret; } - int ObLS::try_update_upper_trans_version_and_gc_sstable( compaction::ObCompactionScheduleIterator &iter) { diff --git a/src/storage/ls/ob_ls.h b/src/storage/ls/ob_ls.h index 7557bee19..c41b16d45 100644 --- a/src/storage/ls/ob_ls.h +++ b/src/storage/ls/ob_ls.h @@ -15,7 +15,6 @@ #include "lib/utility/ob_print_utils.h" #include "common/ob_member_list.h" -#include "share/ob_rpc_struct.h" #include "share/ob_delegate.h" #include "share/ob_tenant_info_proxy.h" #include "lib/worker.h" @@ -869,7 +868,16 @@ public: // tablet_freeze_with_rewrite_meta // @param [in] abs_timeout_ts, wait until timeout if lock conflict int tablet_freeze_with_rewrite_meta(const ObTabletID &tablet_id, + ObFuture *result = nullptr, const int64_t abs_timeout_ts = INT64_MAX); + int tablet_freeze_task_for_direct_load(const ObTabletID &tablet_id, + const uint64_t epoch, + ObFuture *result = nullptr); + int sync_tablet_freeze_for_direct_load(const ObTabletID &tablet_id, + const int64_t max_retry_time = 3600LL * 1000LL * 1000LL /*1 hour*/); + void async_tablet_freeze_for_direct_load(const ObTabletID &tablet_id); + + DELEGATE_WITH_RET(ls_freezer_, wait_freeze_finished, int); // batch tablet freeze // @param [in] tablet_ids // @param [in] is_sync @@ -928,6 +936,7 @@ public: DELEGATE_WITH_RET(reserved_snapshot_mgr_, add_dependent_medium_tablet, int); DELEGATE_WITH_RET(reserved_snapshot_mgr_, del_dependent_medium_tablet, int); int set_ls_migration_gc(bool &allow_gc); + private: // StorageBaseUtil // table manager: create, remove and guard get. diff --git a/src/storage/ls/ob_ls_ddl_log_handler.h b/src/storage/ls/ob_ls_ddl_log_handler.h index d52256c49..4fb2908b1 100644 --- a/src/storage/ls/ob_ls_ddl_log_handler.h +++ b/src/storage/ls/ob_ls_ddl_log_handler.h @@ -92,6 +92,8 @@ public: int del_tablets(const common::ObIArray &tablet_ids); int get_tablets(common::ObIArray &tablet_ids); + ObDDLRedoLogReplayer &get_ddl_log_replayer() { return ddl_log_replayer_; } + private: int replay_ddl_redo_log_(const char *log_buf, const int64_t buf_size, int64_t pos, const share::SCN &scn); int replay_ddl_commit_log_(const char *log_buf, const int64_t buf_size, int64_t pos, const share::SCN &scn); diff --git a/src/storage/ls/ob_ls_tablet_service.cpp b/src/storage/ls/ob_ls_tablet_service.cpp index bbfd37539..b44cf5987 100644 --- a/src/storage/ls/ob_ls_tablet_service.cpp +++ b/src/storage/ls/ob_ls_tablet_service.cpp @@ -2331,6 +2331,7 @@ int ObLSTabletService::rollback_remove_tablet_without_lock( int ObLSTabletService::create_memtable( const common::ObTabletID &tablet_id, const int64_t schema_version, + const bool for_direct_load, const bool for_replay, const share::SCN clog_checkpoint_scn) { @@ -2370,7 +2371,7 @@ int ObLSTabletService::create_memtable( ret = OB_EAGAIN; LOG_WARN("tablet status not allow create new memtable", K(ret), K(is_committed), K(user_data)); } - if (FAILEDx(old_tablet.create_memtable(schema_version, clog_checkpoint_scn, for_replay))) { + if (FAILEDx(old_tablet.create_memtable(schema_version, clog_checkpoint_scn, for_direct_load, for_replay))) { if (OB_MINOR_FREEZE_NOT_ALLOW != ret) { LOG_WARN("fail to create memtable", K(ret), K(new_tablet_handle), K(schema_version), K(tablet_id)); } @@ -2382,6 +2383,7 @@ int ObLSTabletService::create_memtable( } } } + return ret; } diff --git a/src/storage/ls/ob_ls_tablet_service.h b/src/storage/ls/ob_ls_tablet_service.h index 38c64ca87..b8d66b50a 100644 --- a/src/storage/ls/ob_ls_tablet_service.h +++ b/src/storage/ls/ob_ls_tablet_service.h @@ -13,7 +13,6 @@ #ifndef OCEANBASE_STORAGE_OB_LS_TABLET_SERVICE #define OCEANBASE_STORAGE_OB_LS_TABLET_SERVICE -#include "storage/meta_mem/ob_tablet_handle.h" #include "common/ob_tablet_id.h" #include "lib/container/ob_array_serialization.h" #include "lib/container/ob_iarray.h" @@ -286,7 +285,8 @@ public: int create_memtable( const common::ObTabletID &tablet_id, const int64_t schema_version, - const bool for_replay = false, + const bool for_direct_load, + const bool for_replay, const share::SCN clog_checkpoint_scn = share::SCN::min_scn()); int get_read_tables( const common::ObTabletID tablet_id, diff --git a/src/storage/memtable/mvcc/ob_mvcc.h b/src/storage/memtable/mvcc/ob_mvcc.h index 1c35781f1..87c288b9f 100644 --- a/src/storage/memtable/mvcc/ob_mvcc.h +++ b/src/storage/memtable/mvcc/ob_mvcc.h @@ -17,11 +17,13 @@ namespace oceanbase { +namespace storage { +class ObIMemtable; +}; namespace memtable { class ObTransCallbackList; class ObITransCallbackIterator; -class ObIMemtable; enum class MutatorType; struct TxChecksum : public common::ObBatchChecksum { TxChecksum(): cnt_(0), scn_() {} @@ -56,9 +58,9 @@ public: virtual bool is_table_lock_callback() const { return false; } virtual int merge_memtable_key(transaction::ObMemtableKeyArray &memtable_key_arr) { UNUSED(memtable_key_arr); return common::OB_SUCCESS; } - virtual bool on_memtable(const ObIMemtable * const memtable) + virtual bool on_memtable(const storage::ObIMemtable * const memtable) { UNUSED(memtable); return false; } - virtual ObIMemtable* get_memtable() const { return nullptr; } + virtual storage::ObIMemtable* get_memtable() const { return nullptr; } virtual uint32_t get_freeze_clock() const { return 0; } virtual transaction::ObTxSEQ get_seq_no() const { return transaction::ObTxSEQ::INVL(); } virtual int del() { return remove(); } @@ -72,13 +74,13 @@ public: void after_append_cb(const bool is_replay); bool need_submit_log() const { return need_submit_log_; } virtual bool is_logging_blocked() const { return false; } - virtual bool on_frozen_memtable(ObIMemtable *&last_frozen_mt) const { return true; } - int log_submitted_cb(const share::SCN scn, ObIMemtable *&last_mt); + virtual bool on_frozen_memtable(storage::ObIMemtable *&last_frozen_mt) const { return true; } + int log_submitted_cb(const share::SCN scn, storage::ObIMemtable *&last_mt); int log_sync_fail_cb(const share::SCN scn); // interface should be implement by subclasses virtual int before_append(const bool is_replay) { return common::OB_SUCCESS; } virtual void after_append(const bool is_replay) {} - virtual int log_submitted(const share::SCN scn, ObIMemtable *&last_mt) + virtual int log_submitted(const share::SCN scn, storage::ObIMemtable *&last_mt) { UNUSED(scn); return common::OB_SUCCESS; } virtual int log_sync_fail(const share::SCN max_committed_scn) { return common::OB_SUCCESS; } diff --git a/src/storage/memtable/mvcc/ob_mvcc_engine.cpp b/src/storage/memtable/mvcc/ob_mvcc_engine.cpp index ad532284c..47d407fa4 100644 --- a/src/storage/memtable/mvcc/ob_mvcc_engine.cpp +++ b/src/storage/memtable/mvcc/ob_mvcc_engine.cpp @@ -260,7 +260,6 @@ int ObMvccEngine::create_kv( const bool is_insert, ObMemtableKey *stored_key, ObMvccRow *&value, - RowHeaderGetter &getter, bool &is_new_add) { int64_t loop_cnt = 0; @@ -285,8 +284,6 @@ int ObMvccEngine::create_kv( ret = OB_ERR_UNEXPECTED; TRANS_LOG(WARN, "get NULL value"); } - } else if (OB_FAIL(getter.get())) { - TRANS_LOG(WARN, "get row header error"); } else if (OB_FAIL(kv_builder_->dup_key(tmp_key, *engine_allocator_, key->get_rowkey()))) { diff --git a/src/storage/memtable/mvcc/ob_mvcc_engine.h b/src/storage/memtable/mvcc/ob_mvcc_engine.h index 07af9982b..1d87ef4ed 100644 --- a/src/storage/memtable/mvcc/ob_mvcc_engine.h +++ b/src/storage/memtable/mvcc/ob_mvcc_engine.h @@ -14,12 +14,8 @@ #define OCEANBASE_MEMTABLE_MVCC_OB_MVCC_ENGINE_ #include "share/ob_define.h" -#include "storage/memtable/mvcc/ob_mvcc_define.h" -#include "storage/memtable/mvcc/ob_multi_version_iterator.h" -#include "storage/memtable/mvcc/ob_mvcc_iterator.h" -#include "storage/memtable/mvcc/ob_query_engine.h" -#include "storage/memtable/ob_row_compactor.h" -#include "storage/memtable/ob_memtable_context.h" +#include "storage/memtable/ob_concurrent_control.h" +// #include "storage/memtable/ob_memtable_context.h" namespace oceanbase { @@ -34,11 +30,20 @@ namespace memtable struct ObRowData; class ObMemtableCtx; class ObMvccAccessCtx; -class RowHeaderGetter; class ObMemtableData; -class ObMemtableDataHeader; class ObMemtable; class ObMTKVBuilder; +class ObQueryEngine; +class ObMemtableKey; +class ObMvccRow; +class ObTxNodeArg; +class ObMvccWriteResult; +class ObMvccReplayResult; +class ObMvccValueIterator; +class ObMvccScanRange; +class ObMvccRowIterator; +class ObMvccTransNode; +class ObMultiVersionRowIterator; // class for concurrent control class ObMvccEngine @@ -60,7 +65,6 @@ public: const bool is_insert, ObMemtableKey *stored_key, ObMvccRow *&value, - RowHeaderGetter &getter, bool &is_new_add); // mvcc_write builds the ObMvccTransNode according to the arg and write diff --git a/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.h b/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.h index 584e06ad4..8f548595f 100644 --- a/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.h +++ b/src/storage/memtable/mvcc/ob_mvcc_trans_ctx.h @@ -34,11 +34,13 @@ namespace common { class ObTabletID; }; - +namespace storage +{ +class ObIMemtable; +}; namespace memtable { class ObMemtableCtxCbAllocator; -class ObIMemtable; class ObMemtable; class ObCallbackScope; typedef ObIArray ObCallbackScopeArray; @@ -506,9 +508,9 @@ public: column_cnt_ = column_cnt; is_non_unique_local_index_cb_ = is_non_unique_local_index_cb; } + bool on_memtable(const storage::ObIMemtable * const memtable) override; + storage::ObIMemtable *get_memtable() const override; bool is_non_unique_local_index_cb() const { return is_non_unique_local_index_cb_;} - bool on_memtable(const ObIMemtable * const memtable) override; - ObIMemtable *get_memtable() const override; virtual MutatorType get_mutator_type() const override; int get_redo(RedoDataNode &node); ObIMvccCtx &get_ctx() const { return ctx_; } @@ -527,7 +529,7 @@ public: int64_t to_string(char *buf, const int64_t buf_len) const; virtual int before_append(const bool is_replay) override; virtual void after_append(const bool is_replay) override; - virtual int log_submitted(const share::SCN scn, ObIMemtable *&last_mt) override; + virtual int log_submitted(const share::SCN scn, storage::ObIMemtable *&last_mt) override; int64_t get_data_size() { return data_size_; diff --git a/src/storage/memtable/mvcc/ob_query_engine.h b/src/storage/memtable/mvcc/ob_query_engine.h index a8ee29636..31bf54c75 100644 --- a/src/storage/memtable/mvcc/ob_query_engine.h +++ b/src/storage/memtable/mvcc/ob_query_engine.h @@ -17,7 +17,6 @@ #include "lib/oblog/ob_log_module.h" #include "lib/objectpool/ob_concurrency_objpool.h" #include "storage/memtable/mvcc/ob_keybtree.h" -#include "storage/memtable/mvcc/ob_mvcc_row.h" #include "storage/memtable/ob_memtable_key.h" #include "storage/memtable/ob_mt_hash.h" diff --git a/src/storage/memtable/ob_memtable.cpp b/src/storage/memtable/ob_memtable.cpp index 6f8223bd1..3400d8934 100644 --- a/src/storage/memtable/ob_memtable.cpp +++ b/src/storage/memtable/ob_memtable.cpp @@ -34,6 +34,7 @@ #include "storage/memtable/ob_lock_wait_mgr.h" #include "storage/memtable/ob_row_conflict_handler.h" #include "storage/memtable/ob_concurrent_control.h" +#include "storage/memtable/ob_row_compactor.h" #include "storage/compaction/ob_tablet_merge_task.h" #include "storage/compaction/ob_schedule_dag_func.h" #include "storage/compaction/ob_compaction_diagnose.h" @@ -102,48 +103,22 @@ ObGlobalMtAlloc &get_global_mt_alloc() // Public Functions ObMemtable::ObMemtable() - : ObIMemtable(), - ObFreezeCheckpoint(), - is_inited_(false), + : is_inited_(false), ls_handle_(), - freezer_(nullptr), - memtable_mgr_handle_(), - freeze_clock_(0), local_allocator_(*this), query_engine_(local_allocator_), mvcc_engine_(), - mt_stat_(), reported_dml_stat_(), - max_schema_version_(0), max_data_schema_version_(0), - pending_cb_cnt_(0), - unsubmitted_cnt_(0), - logging_blocked_(false), - logging_blocked_start_time(0), - unset_active_memtable_logging_blocked_(false), - resolved_active_memtable_left_boundary_(true), transfer_freeze_flag_(false), recommend_snapshot_version_(share::SCN::invalid_scn()), - freeze_scn_(SCN::max_scn()), - max_end_scn_(ObScnRange::MIN_SCN), - rec_scn_(SCN::max_scn()), - freeze_state_(ObMemtableFreezeState::INVALID), - timestamp_(0), - is_tablet_freeze_(false), - is_flushed_(false), - read_barrier_(false), - write_barrier_(false), - allow_freeze_(true), - write_ref_cnt_(0), + state_(ObMemtableState::INVALID), mode_(lib::Worker::CompatMode::INVALID), minor_merged_time_(0), contain_hotspot_row_(false), encrypt_meta_(nullptr), encrypt_meta_lock_(ObLatchIds::DEFAULT_SPIN_RWLOCK), - max_column_cnt_(0) -{ - migration_clog_checkpoint_scn_.set_min(); -} + max_column_cnt_(0) {} ObMemtable::~ObMemtable() { @@ -195,10 +170,11 @@ int ObMemtable::init(const ObITable::TableKey &table_key, } else { mode_ = MTL(lib::Worker::CompatMode); } - freeze_state_ = ObMemtableFreezeState::NOT_READY_FOR_FLUSH; - timestamp_ = ObTimeUtility::current_time(); - is_inited_ = true; + state_ = ObMemtableState::ACTIVE; + init_timestamp_ = ObTimeUtility::current_time(); contain_hotspot_row_ = false; + (void)set_freeze_state(TabletMemtableFreezeState::ACTIVE); + is_inited_ = true; TRANS_LOG(DEBUG, "memtable init success", K(*this)); } @@ -234,6 +210,7 @@ int ObMemtable::batch_remove_unused_callback_for_uncommited_txn( void ObMemtable::destroy() { + is_inited_ = false; ObTimeGuard time_guard("ObMemtable::destroy()", 100 * 1000); int ret = OB_SUCCESS; if (is_inited_) { @@ -245,44 +222,22 @@ void ObMemtable::destroy() STORAGE_LOG(INFO, "memtable destroyed", K(*this)); time_guard.click(); } - ObITable::reset(); - ObFreezeCheckpoint::reset(); mvcc_engine_.destroy(); time_guard.click(); query_engine_.destroy(); time_guard.click(); - time_guard.click(); local_allocator_.destroy(); time_guard.click(); ls_handle_.reset(); - freezer_ = nullptr; - memtable_mgr_handle_.reset(); - freeze_clock_ = 0; - max_schema_version_ = 0; max_data_schema_version_ = 0; max_column_cnt_ = 0; - mt_stat_.reset(); + state_ = ObMemtableState::INVALID; reported_dml_stat_.reset(); - freeze_state_ = ObMemtableFreezeState::INVALID; - unsubmitted_cnt_ = 0; - logging_blocked_ = false; - logging_blocked_start_time = 0; - unset_active_memtable_logging_blocked_ = false; - resolved_active_memtable_left_boundary_ = true; transfer_freeze_flag_ = false; recommend_snapshot_version_.reset(); - max_end_scn_ = ObScnRange::MIN_SCN; - migration_clog_checkpoint_scn_.set_min(); - rec_scn_ = SCN::max_scn(); - read_barrier_ = false; - is_tablet_freeze_ = false; - is_flushed_ = false; - allow_freeze_ = true; - is_inited_ = false; contain_hotspot_row_ = false; - snapshot_version_.set_max(); encrypt_meta_ = nullptr; - reset_trace_id(); + ObITabletMemtable::reset(); } int ObMemtable::safe_to_destroy(bool &is_safe) @@ -847,7 +802,7 @@ int ObMemtable::exist( *parameter_mtk.get_rowkey(), lock_state, key_.tablet_id_, - freezer_->get_ls_id(), + get_ls_id(), 0, 0 /* these two params get from mvcc_row, and for statistics, so we ignore them */, lock_state.trans_scn_); } @@ -979,7 +934,7 @@ int ObMemtable::get( *parameter_mtk.get_rowkey(), lock_state, key_.tablet_id_, - freezer_->get_ls_id(), + get_ls_id(), 0, 0 /* these two params get from mvcc_row, and for statistics, so we ignore them */, lock_state.trans_scn_); } @@ -1373,110 +1328,13 @@ int ObMemtable::lock_row_on_frozen_stores_( // skip if it is non-unique index for which the lock has been checked in primary table } else { ObRowState row_state; - ObStoreRowLockState tmp_lock_state; - const ObIArray *stores = nullptr; common::ObSEArray iter_tables; - ctx.table_iter_->resume(); - ObTransID my_tx_id = ctx.mvcc_acc_ctx_.get_tx_id(); - - while (OB_SUCC(ret)) { - ObITable *table_ptr = nullptr; - if (OB_FAIL(ctx.table_iter_->get_next(table_ptr))) { - if (OB_ITER_END != ret) { - TRANS_LOG(WARN, "failed to get next tables", K(ret)); - } else { - ret = OB_SUCCESS; - break; - } - } else if (OB_ISNULL(table_ptr)) { - ret = OB_ERR_UNEXPECTED; - TRANS_LOG(WARN, "table must not be null", K(ret), KPC(ctx.table_iter_)); - } else if (OB_FAIL(iter_tables.push_back(table_ptr))) { - TRANS_LOG(WARN, "rowkey_exists check::", K(ret), KPC(table_ptr)); - } - } // end while - if (OB_SUCC(ret)) { - // lock_is_decided means we have found either the lock that is locked by - // an active txn or the latest unlocked txn data. And after we have found - // either of the above situations, whether the row is locked is determined. - bool lock_is_decided = false; - stores = &iter_tables; - lock_state.reset(); - // ignore active memtable - for (int64_t i = stores->count() - 2; OB_SUCC(ret) && i >= 0; i--) { - tmp_lock_state.reset(); - if (NULL == stores->at(i)) { - ret = OB_ERR_UNEXPECTED; - TRANS_LOG(WARN, "ObIStore is null", K(ret), K(i)); - } else if (stores->at(i)->is_data_memtable()) { - ObMemtable *memtable = static_cast(stores->at(i)); - ObMvccEngine &mvcc_engine = memtable->get_mvcc_engine(); - //TODO(handora.qc): fix memtable check -// if (OB_UNLIKELY(memtable->is_active_memtable())) { -// ret = OB_ERR_UNEXPECTED; -// TRANS_LOG(ERROR, "lock row on frozen stores check an active memtable", K(ret), KPC(stores)); -// } else if (OB_FAIL(mvcc_engine.check_row_locked(ctx.mvcc_acc_ctx_, key, lock_state))) { -// TRANS_LOG(WARN, "mvcc engine check row lock fail", K(ret), K(lock_state)); -// } - - if (OB_FAIL(mvcc_engine.check_row_locked(ctx.mvcc_acc_ctx_, - key, - tmp_lock_state, - row_state))) { - TRANS_LOG(WARN, "mvcc engine check row lock fail", K(ret), K(lock_state), K(tmp_lock_state)); - } else { - TRANS_LOG(DEBUG, "check_row_locked meet memtable", K(ret), K(check_exist), K(*key), K(*memtable), - K(lock_state), K(tmp_lock_state), K(row_state)); - } - } else if (stores->at(i)->is_sstable()) { - blocksstable::ObDatumRowkeyHelper rowkey_converter; - blocksstable::ObDatumRowkey datum_rowkey; - ObITable *sstable = stores->at(i); - if (OB_FAIL(rowkey_converter.convert_datum_rowkey(key->get_rowkey()->get_rowkey(), datum_rowkey))) { - STORAGE_LOG(WARN, "Failed to convert datum rowkey", K(ret), KPC(key)); - } else if (OB_FAIL(static_cast(sstable)->check_row_locked(param, - datum_rowkey, - context, - tmp_lock_state, - row_state, - check_exist))) { - TRANS_LOG(WARN, "sstable check row lock fail", K(ret), K(datum_rowkey), K(*key), K(lock_state), - K(tmp_lock_state), K(row_state)); - } - TRANS_LOG(DEBUG, "check_row_locked meet sstable", K(ret), K(check_exist), K(*key), K(*sstable), - K(lock_state), K(tmp_lock_state), K(row_state)); - } else { - ret = OB_ERR_UNEXPECTED; - TRANS_LOG(ERROR, "unknown store type", K(ret), K(*stores), K(i)); - } - if (OB_SUCC(ret)) { - // 1. Check duplication. - if (check_exist) { - if (row_state.is_not_exist()) { - } else if (row_state.is_delete()) { - break; - } else { - ret = OB_ERR_PRIMARY_KEY_DUPLICATE; - } - } - // 2. Check write-write conflict. - if (OB_SUCC(ret) && !row_state.is_lock_decided()) { - lock_is_decided = tmp_lock_state.is_lock_decided(); - if (lock_is_decided) { - row_state.set_lock_decided(); - lock_state = tmp_lock_state; - if (tmp_lock_state.is_locked(my_tx_id)) { - ret = OB_TRY_LOCK_ROW_CONFLICT; - } else if (!check_exist) { - break; - } - } - } - } - } - } - - if (OB_SUCC(ret)) { + if (OB_FAIL(get_all_tables_(ctx, iter_tables))) { + TRANS_LOG(WARN, "get all tables from table iter failed", KR(ret)); + } else if (OB_FAIL(internal_lock_row_on_frozen_stores_( + check_exist, key, param, iter_tables, context, res, row_state))) { + TRANS_LOG(WARN, "internal lock row failed", KR(ret)); + } else { lock_state.trans_version_ = MAX(lock_state.trans_version_, row_state.get_max_trans_version()); if (OB_FAIL(lock_row_on_frozen_stores_on_success(lock_state.is_locked_, arg.data_->dml_flag_, lock_state.trans_version_, context, value, res))) { @@ -1489,6 +1347,125 @@ int ObMemtable::lock_row_on_frozen_stores_( return ret; } +int ObMemtable::get_all_tables_(ObStoreCtx &ctx, ObIArray &iter_tables) +{ + int ret = OB_SUCCESS; + ctx.table_iter_->resume(); + while (OB_SUCC(ret)) { + ObITable *table_ptr = nullptr; + if (OB_FAIL(ctx.table_iter_->get_next(table_ptr))) { + if (OB_ITER_END != ret) { + TRANS_LOG(WARN, "failed to get next tables", K(ret)); + } else { + ret = OB_SUCCESS; + break; + } + } else if (OB_ISNULL(table_ptr)) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "table must not be null", K(ret), KPC(ctx.table_iter_)); + } else if (OB_FAIL(iter_tables.push_back(table_ptr))) { + TRANS_LOG(WARN, "rowkey_exists check::", K(ret), KPC(table_ptr)); + } + } + return ret; +} + +int ObMemtable::internal_lock_row_on_frozen_stores_(const bool check_exist, + const ObMemtableKey *key, + const storage::ObTableIterParam ¶m, + const ObIArray &iter_tables, + storage::ObTableAccessContext &context, + ObMvccWriteResult &res, + ObRowState &row_state) + +{ + int ret = OB_SUCCESS; + + // lock_is_decided means we have found either the lock that is locked by + // an active txn or the latest unlocked txn data. And after we have found + // either of the above situations, whether the row is locked is determined. + bool lock_is_decided = false; + + ObStoreCtx &ctx = *(context.store_ctx_); + ObStoreRowLockState tmp_lock_state; + ObStoreRowLockState &lock_state = res.lock_state_; + lock_state.reset(); + // ignore active memtable + for (int64_t i = iter_tables.count() - 2; OB_SUCC(ret) && i >= 0; i--) { + tmp_lock_state.reset(); + if (NULL == iter_tables.at(i)) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "ObIStore is null", K(ret), K(i)); + } else if (iter_tables.at(i)->is_data_memtable()) { + ObMemtable *memtable = static_cast(iter_tables.at(i)); + ObMvccEngine &mvcc_engine = memtable->get_mvcc_engine(); + // FIXME(handora.qc): two active memtable in transfer + if (OB_FAIL(mvcc_engine.check_row_locked(ctx.mvcc_acc_ctx_, key, tmp_lock_state, row_state))) { + TRANS_LOG(WARN, "mvcc engine check row lock fail", K(ret), K(lock_state), K(tmp_lock_state)); + } + } else if (iter_tables.at(i)->is_sstable()) { + blocksstable::ObDatumRowkeyHelper rowkey_converter; + blocksstable::ObDatumRowkey datum_rowkey; + ObITable *sstable = iter_tables.at(i); + if (OB_FAIL(rowkey_converter.convert_datum_rowkey(key->get_rowkey()->get_rowkey(), datum_rowkey))) { + STORAGE_LOG(WARN, "Failed to convert datum rowkey", K(ret), KPC(key)); + } else if (OB_FAIL(static_cast(sstable)->check_row_locked( + param, datum_rowkey, context, tmp_lock_state, row_state, check_exist))) { + TRANS_LOG(WARN, + "sstable check row lock fail", + K(ret), + KPC(key), + K(check_exist), + K(datum_rowkey), + K(lock_state), + K(tmp_lock_state), + K(row_state)); + } + TRANS_LOG(DEBUG, + "sstable check row lock debug", + K(ret), + KPC(key), + KPC(sstable), + K(check_exist), + K(datum_rowkey), + K(lock_state), + K(tmp_lock_state), + K(row_state)); + } else if (iter_tables.at(i)->is_direct_load_memtable()) { + TRANS_LOG(DEBUG, "skip check direct load memtable", KPC(iter_tables.at(i))); + } else { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(ERROR, "unknown store type", K(ret), K(iter_tables), K(i)); + } + + if (OB_SUCC(ret)) { + // 1. Check duplication. + if (check_exist) { + if (row_state.is_not_exist()) { + } else if (row_state.is_delete()) { + break; + } else { + ret = OB_ERR_PRIMARY_KEY_DUPLICATE; + } + } + // 2. Check write-write conflict. + if (OB_SUCC(ret) && !row_state.is_lock_decided()) { + lock_is_decided = tmp_lock_state.is_lock_decided(); + if (lock_is_decided) { + row_state.set_lock_decided(); + lock_state = tmp_lock_state; + if (tmp_lock_state.is_locked(ctx.mvcc_acc_ctx_.get_tx_id())) { + ret = OB_TRY_LOCK_ROW_CONFLICT; + } else if (!check_exist) { + break; + } + } + } + } + } + return ret; +} + int ObMemtable::lock_row_on_frozen_stores_on_success( const bool row_locked, const blocksstable::ObDmlFlag writer_dml_flag, @@ -1625,24 +1602,9 @@ int ObMemtable::lock_rows_on_frozen_stores_( // so there is no need to check transaction conflict again. } else { common::ObSEArray iter_tables; - ctx.table_iter_->resume(); - while (OB_SUCC(ret)) { - ObITable *table_ptr = nullptr; - if (OB_FAIL(ctx.table_iter_->get_next(table_ptr))) { - if (OB_ITER_END != ret) { - TRANS_LOG(WARN, "Failed to get next table", K(ret)); - } else { - ret = OB_SUCCESS; - break; - } - } else if (OB_ISNULL(table_ptr)) { - ret = OB_ERR_UNEXPECTED; - TRANS_LOG(WARN, "Table must not be null", K(ret), KPC(ctx.table_iter_)); - } else if (OB_FAIL(iter_tables.push_back(table_ptr))) { - TRANS_LOG(WARN, "Failed to push back table", K(ret)); - } - } - if (OB_SUCC(ret)) { + if (OB_FAIL(get_all_tables_(ctx, iter_tables))) { + TRANS_LOG(WARN, "get all tables from table iter failed", KR(ret)); + } else { share::SCN max_trans_version = SCN::min_scn(); if (OB_FAIL(internal_lock_rows_on_frozen_stores_(check_exist, iter_tables, param, context, max_trans_version, rows_info))) { @@ -1687,7 +1649,7 @@ int ObMemtable::internal_lock_rows_on_frozen_stores_( int ret = OB_SUCCESS; for (int64_t i = iter_tables.count() - 2; OB_SUCC(ret) && i >= 0; i--) { ObITable *i_table = iter_tables.at(i); - if (i_table->is_memtable()) { + if (i_table->is_data_memtable()) { ObMemtable *memtable = static_cast(i_table); if (OB_FAIL(memtable->check_rows_locked(check_exist, param, context, rows_info))) { TRANS_LOG(WARN, "Failed to check rows locked and duplication in memtable", K(ret), K(i), @@ -1711,6 +1673,8 @@ int ObMemtable::internal_lock_rows_on_frozen_stores_( TRANS_LOG(WARN, "Failed to check rows locked for sstable", K(ret), K(i), K(iter_tables)); } } + } else if (iter_tables.at(i)->is_direct_load_memtable()) { + TRANS_LOG(DEBUG, "skip check direct load memtable", KPC(iter_tables.at(i))); } else { ret = OB_ERR_UNEXPECTED; TRANS_LOG(ERROR, "Unknown store type", K(ret), K(iter_tables), K(i)); @@ -1726,32 +1690,6 @@ int ObMemtable::internal_lock_rows_on_frozen_stores_( //////////////////////////////////////////////////////////////////////////////////////////////////// // no allocator here for it, so we desirialize and save the struct info -int ObMemtable::set_freezer(ObFreezer *handler) -{ - int ret = OB_SUCCESS; - - if (OB_ISNULL(handler)) { - ret = OB_INVALID_ARGUMENT; - TRANS_LOG(WARN, "freeze handler is null", K(ret)); - } else { - freezer_ = handler; - } - - return ret; -} - -int ObMemtable::get_ls_id(share::ObLSID &ls_id) -{ - int ret = OB_SUCCESS; - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else { - ls_id = ls_handle_.get_ls()->get_ls_id(); - } - return ret; -} - int64_t ObMemtable::get_size() const { return local_allocator_.get_size(); @@ -1822,131 +1760,6 @@ int64_t ObMemtable::get_btree_alloc_memory() const return query_engine_.btree_alloc_memory(); } -int ObMemtable::inc_unsubmitted_cnt() -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - int64_t unsubmitted_cnt = inc_unsubmitted_cnt_(); - TRANS_LOG(DEBUG, "inc_unsubmitted_cnt", K(ls_id), KPC(this), K(lbt())); - - if (ATOMIC_LOAD(&unset_active_memtable_logging_blocked_)) { - TRANS_LOG(WARN, "cannot inc unsubmitted_cnt", K(unsubmitted_cnt), K(ls_id), KPC(this)); - } - - return ret; -} - -int ObMemtable::dec_unsubmitted_cnt() -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - - // fix issue 47021079 - // To avoid the following case where logging_block cannot be unset: - // ----------------------------------------------------- - // dec_write_ref() dec_unsubmitted_cnt() - // ----------------------------------------------------- - // is_frozen is_frozen - // get write_ref_cnt 1 - // dec write_ref to 0 - // get unsubmitted_cnt 1 - // dec unsubmitted_cnt to 0 - // ----------------------------------------------------- - int64_t old_unsubmitted_cnt = dec_unsubmitted_cnt_(); - - // must maintain the order of getting variables to avoid concurrency problems - // is_frozen_memtable() can affect wirte_ref_cnt - // write_ref_cnt can affect unsubmitted_cnt - bool is_frozen = is_frozen_memtable(); - int64_t write_ref_cnt = get_write_ref(); - int64_t new_unsubmitted_cnt = get_unsubmitted_cnt(); - TRANS_LOG(DEBUG, "dec_unsubmitted_cnt", K(ls_id), KPC(this), K(lbt())); - - if (OB_UNLIKELY(old_unsubmitted_cnt < 0)) { - TRANS_LOG(ERROR, "unsubmitted_cnt not match", K(ret), K(ls_id), KPC(this)); - } else if (is_frozen && - 0 == write_ref_cnt && - 0 == new_unsubmitted_cnt) { - (void)unset_logging_blocked_for_active_memtable(); - TRANS_LOG(INFO, "memtable log submitted", K(ret), K(ls_id), KPC(this)); - } - - return ret; -} - -int64_t ObMemtable::dec_write_ref() -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - - // fix issue 47021079 - // To avoid the following case where logging_block cannot be unset: - // ----------------------------------------------------- - // dec_write_ref() dec_unsubmitted_cnt() - // ----------------------------------------------------- - // is_frozen is_frozen - // get write_ref_cnt 1 - // dec write_ref to 0 - // get unsubmitted_cnt 1 - // dec unsubmitted_cnt to 0 - // ----------------------------------------------------- - int64_t old_write_ref_cnt = dec_write_ref_(); - - // must maintain the order of getting variables to avoid concurrency problems - // is_frozen_memtable() can affect wirte_ref_cnt - // write_ref_cnt can affect unsubmitted_cnt - bool is_frozen = is_frozen_memtable(); - int64_t new_write_ref_cnt = get_write_ref(); - int64_t unsubmitted_cnt = get_unsubmitted_cnt(); - if (is_frozen && - 0 == new_write_ref_cnt && - 0 == unsubmitted_cnt) { - (void)unset_logging_blocked_for_active_memtable(); - share::SCN right_boundary; - if (OB_FAIL(get_ls_current_right_boundary(right_boundary))) { - TRANS_LOG(WARN, "get ls right bound fail", K(ret), K(ls_id), KPC(this)); - } else if (right_boundary >= get_max_end_scn()) { - resolve_right_boundary(); - if (OB_LIKELY(!get_resolved_active_memtable_left_boundary())) { - resolve_left_boundary_for_active_memtable(); - } - } - } - - return old_write_ref_cnt; -} - -void ObMemtable::unset_logging_blocked_for_active_memtable() -{ - int ret = OB_SUCCESS; - storage::ObTabletMemtableMgr *memtable_mgr = get_memtable_mgr_(); - - if (OB_NOT_NULL(memtable_mgr)) { - do { - if (OB_FAIL(memtable_mgr->unset_logging_blocked_for_active_memtable(this))) { - TRANS_LOG(ERROR, "fail to unset logging blocked for active memtable", K(ret), K(ls_id_), KPC(this)); - ob_usleep(100); - } - } while (OB_FAIL(ret)); - } -} - -void ObMemtable::resolve_left_boundary_for_active_memtable() -{ - int ret = OB_SUCCESS; - storage::ObTabletMemtableMgr *memtable_mgr = get_memtable_mgr_(); - const SCN new_start_scn = MAX(get_end_scn(), get_migration_clog_checkpoint_scn()); - - if (OB_NOT_NULL(memtable_mgr)) { - do { - if (OB_FAIL(memtable_mgr->resolve_left_boundary_for_active_memtable(this, new_start_scn, get_snapshot_version_scn()))) { - TRANS_LOG(ERROR, "fail to set start log ts for active memtable", K(ret), K(ls_id_), KPC(this)); - ob_usleep(100); - } - } while (OB_FAIL(ret)); - } -} - void ObMemtable::set_allow_freeze(const bool allow_freeze) { int ret = OB_SUCCESS; @@ -1969,54 +1782,12 @@ void ObMemtable::set_allow_freeze(const bool allow_freeze) } } -int64_t ObMemtable::inc_write_ref_() -{ - return ATOMIC_AAF(&write_ref_cnt_, 1); -} - -int64_t ObMemtable::dec_write_ref_() -{ - return ATOMIC_SAF(&write_ref_cnt_, 1); -} - -int64_t ObMemtable::inc_unsubmitted_cnt_() -{ - return ATOMIC_AAF(&unsubmitted_cnt_, 1); -} - -int64_t ObMemtable::dec_unsubmitted_cnt_() -{ - return ATOMIC_SAF(&unsubmitted_cnt_, 1); -} - -bool ObMemtable::can_be_minor_merged() -{ - return is_in_prepare_list_of_data_checkpoint(); -} - int ObMemtable::get_frozen_schema_version(int64_t &schema_version) const { UNUSED(schema_version); return OB_NOT_SUPPORTED; } -int ObMemtable::set_migration_clog_checkpoint_scn(const SCN &clog_checkpoint_scn) -{ - int ret = OB_SUCCESS; - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else if (clog_checkpoint_scn <= ObScnRange::MIN_SCN) { - ret = OB_SCN_OUT_OF_BOUND; - TRANS_LOG(WARN, "invalid clog_checkpoint_ts", K(ret)); - } else { - (void)migration_clog_checkpoint_scn_.atomic_store(clog_checkpoint_scn); - } - - return ret; -} - int ObMemtable::set_snapshot_version(const SCN snapshot_version) { int ret = OB_SUCCESS; @@ -2034,193 +1805,6 @@ int ObMemtable::set_snapshot_version(const SCN snapshot_version) return ret; } -int ObMemtable::set_rec_scn(SCN rec_scn) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else if (rec_scn.is_max()) { - ret = OB_INVALID_ARGUMENT; - TRANS_LOG(WARN, "invalid args", K(ret), K(rec_scn)); - } else if (rec_scn <= get_start_scn()) { - ret = OB_SCN_OUT_OF_BOUND; - TRANS_LOG(ERROR, "cannot set freeze log ts smaller to start log ts", K(ret), K(rec_scn), K(ls_id), KPC(this)); - } else { - SCN old_rec_scn; - SCN new_rec_scn = get_rec_scn(); - while ((old_rec_scn = new_rec_scn) > rec_scn) { - if ((new_rec_scn = rec_scn_.atomic_vcas(old_rec_scn, rec_scn)) - == old_rec_scn) { - new_rec_scn = rec_scn; - } - } - } - - return ret; -} - -int ObMemtable::set_start_scn(const SCN start_scn) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else if (ObScnRange::MAX_SCN == start_scn) { - ret = OB_INVALID_ARGUMENT; - TRANS_LOG(WARN, "invalid args", K(ret), K(start_scn)); - } else if (start_scn >= get_end_scn() - || (max_end_scn_ != SCN::min_scn() && start_scn >= max_end_scn_) - || start_scn >= rec_scn_) { - ret = OB_SCN_OUT_OF_BOUND; - TRANS_LOG(ERROR, "cannot set start ts now", K(ret), K(start_scn), K(ls_id), KPC(this)); - } else { - key_.scn_range_.start_scn_ = start_scn; - } - - return ret; -} - -int ObMemtable::set_end_scn(const SCN freeze_scn) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else if (ObScnRange::MAX_SCN == freeze_scn) { - ret = OB_INVALID_ARGUMENT; - TRANS_LOG(WARN, "invalid args", K(ret), K(freeze_scn)); - } else if (freeze_scn < get_start_scn()) { - ret = OB_SCN_OUT_OF_BOUND; - TRANS_LOG(ERROR, "cannot set freeze log ts smaller to start log ts", - K(ret), K(freeze_scn), K(ls_id), KPC(this)); - } else { - SCN old_end_scn; - SCN new_end_scn = get_end_scn(); - while ((old_end_scn = new_end_scn) < freeze_scn - || new_end_scn == ObScnRange::MAX_SCN) { - if ((new_end_scn = - key_.scn_range_.end_scn_.atomic_vcas(old_end_scn, freeze_scn)) - == old_end_scn) { - new_end_scn = freeze_scn; - } - } - freeze_scn_ = freeze_scn; - } - - return ret; -} - -int ObMemtable::set_max_end_scn(const SCN scn, bool allow_backoff) -{ - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else if (ObScnRange::MAX_SCN == scn) { - ret = OB_INVALID_ARGUMENT; - TRANS_LOG(WARN, "invalid args", K(ret), K(scn)); - } else if (scn <= get_start_scn() || scn > get_end_scn()) { - ret = OB_SCN_OUT_OF_BOUND; - TRANS_LOG(WARN, "cannot set max end log ts smaller to start log ts", - K(ret), K(scn), K(ls_id), KPC(this)); - } else if (allow_backoff) { - TRANS_LOG(INFO, "set max_end_scn force", K(scn), K(max_end_scn_.atomic_get()), K(key_), KPC(this)); - if (scn != max_end_scn_.atomic_get()) { - max_end_scn_.dec_update(scn); - } - } else { - SCN old_max_end_scn; - SCN new_max_end_scn = get_max_end_scn(); - while ((old_max_end_scn = new_max_end_scn) < scn) { - if ((new_max_end_scn = - max_end_scn_.atomic_vcas(old_max_end_scn, scn)) - == old_max_end_scn) { - new_max_end_scn = scn; - } - } - } - - return ret; -} - -// the difference from set_max_end_scn is not to check memtable range -int ObMemtable::set_max_end_scn_to_inc_start_scn() -{ - int ret = OB_SUCCESS; - const share::SCN scn = share::SCN::scn_inc(get_start_scn()); - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - TRANS_LOG(WARN, "not inited", K(ret)); - } else { - SCN old_max_end_scn; - SCN new_max_end_scn = get_max_end_scn(); - while ((old_max_end_scn = new_max_end_scn) < scn) { - if ((new_max_end_scn = - max_end_scn_.atomic_vcas(old_max_end_scn, scn)) - == old_max_end_scn) { - new_max_end_scn = scn; - } - } - } - - return ret; -} - -bool ObMemtable::rec_scn_is_stable() -{ - int ret = OB_SUCCESS; - bool rec_scn_is_stable = false; - if (SCN::max_scn() == rec_scn_) { - rec_scn_is_stable = (is_frozen_memtable() && write_ref_cnt_ == 0 && unsubmitted_cnt_ == 0); - } else { - SCN max_consequent_callbacked_scn; - if (OB_FAIL(freezer_->get_max_consequent_callbacked_scn(max_consequent_callbacked_scn))) { - STORAGE_LOG(WARN, "get_max_consequent_callbacked_scn failed", K(ret), K(freezer_->get_ls_id())); - } else { - rec_scn_is_stable = (max_consequent_callbacked_scn >= rec_scn_); - } - - if (!rec_scn_is_stable && - (mt_stat_.frozen_time_ != 0 && - ObTimeUtility::current_time() - mt_stat_.frozen_time_ > 10 * 1000 * 1000L)) { - STORAGE_LOG(WARN, "memtable rec_scn not stable for long time", - K(freezer_->get_ls_id()), K(*this), K(mt_stat_.frozen_time_), - K(max_consequent_callbacked_scn)); - - int tmp_ret = OB_SUCCESS; - if (OB_TMP_FAIL(ADD_SUSPECT_INFO(MINI_MERGE, ObDiagnoseTabletType::TYPE_MINI_MERGE, - freezer_->get_ls_id(), get_tablet_id(), - ObSuspectInfoType::SUSPECT_REC_SCN_NOT_STABLE, - rec_scn_.get_val_for_tx(), max_consequent_callbacked_scn.get_val_for_tx()))) { - STORAGE_LOG(WARN, "failed to add suspect info", K(tmp_ret)); - } - } - } - return rec_scn_is_stable; -} - -int ObMemtable::get_ls_current_right_boundary(SCN ¤t_right_boundary) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(freezer_)) { - ret = OB_ENTRY_NOT_EXIST; - TRANS_LOG(WARN, "freezer should not be null", K(ret)); - } else if (OB_FAIL(freezer_->get_max_consequent_callbacked_scn(current_right_boundary))) { - TRANS_LOG(WARN, "fail to get min_unreplay_scn", K(ret), K(current_right_boundary)); - } - - return ret; -} bool ObMemtable::ready_for_flush() { @@ -2248,7 +1832,7 @@ bool ObMemtable::ready_for_flush_() int ret = OB_SUCCESS; SCN current_right_boundary = ObScnRange::MIN_SCN; - share::ObLSID ls_id = freezer_->get_ls_id(); + share::ObLSID ls_id = get_ls_id(); if (bool_ret) { if (OB_FAIL(resolve_snapshot_version_())) { TRANS_LOG(WARN, "fail to resolve snapshot version", K(ret), KPC(this), K(ls_id)); @@ -2256,31 +1840,31 @@ bool ObMemtable::ready_for_flush_() TRANS_LOG(WARN, "fail to resolve max_end_scn", K(ret), KPC(this), K(ls_id)); } else { TRANS_LOG(INFO, "[resolve_right_boundary] ready_for_flush_", K(ls_id), KPC(this)); - if (OB_FAIL(get_ls_current_right_boundary(current_right_boundary))) { + if (OB_FAIL(get_ls_current_right_boundary_(current_right_boundary))) { TRANS_LOG(WARN, "fail to get current right boundary", K(ret)); } if ((bool_ret = (current_right_boundary >= get_max_end_scn()))) { resolve_right_boundary(); if (!get_resolved_active_memtable_left_boundary()) { - resolve_left_boundary_for_active_memtable(); + resolve_left_boundary_for_active_memtable_(); } bool_ret = (is_empty() || get_resolved_active_memtable_left_boundary()); } if (bool_ret) { - freeze_state_ = ObMemtableFreezeState::READY_FOR_FLUSH; + set_freeze_state(TabletMemtableFreezeState::READY_FOR_FLUSH); if (0 == mt_stat_.ready_for_flush_time_) { mt_stat_.ready_for_flush_time_ = ObTimeUtility::current_time(); - } freezer_->get_stat().remove_memtable_info(get_tablet_id()); + } } - TRANS_LOG(INFO, "ready for flush", K(bool_ret), K(ret), K(current_right_boundary), K(ls_id), K(*this)); + TRANS_LOG(INFO, "ready for flush", K(bool_ret), K(ret), K(current_right_boundary), K(ls_id), KPC(this)); } } else if (is_frozen && get_logging_blocked()) { // ensure unset all frozen memtables'logging_block ObTableHandleV2 handle; ObMemtable *first_frozen_memtable = nullptr; - storage::ObTabletMemtableMgr *memtable_mgr = get_memtable_mgr_(); + ObTabletMemtableMgr *memtable_mgr = get_memtable_mgr(); if (OB_ISNULL(memtable_mgr)) { } else if (OB_FAIL(memtable_mgr->get_first_frozen_memtable(handle))) { TRANS_LOG(WARN, "fail to get first_frozen_memtable", K(ret)); @@ -2297,7 +1881,7 @@ bool ObMemtable::ready_for_flush_() ObTimeUtility::current_time() - mt_stat_.frozen_time_ > 10 * 1000 * 1000L)) { if (ObTimeUtility::current_time() - mt_stat_.last_print_time_ > 10 * 1000) { STORAGE_LOG(WARN, "memtable not ready for flush for long time", - K(freezer_->get_ls_id()), K(*this), K(mt_stat_.frozen_time_), + K(get_ls_id()), K(*this), K(mt_stat_.frozen_time_), K(current_right_boundary)); mt_stat_.last_print_time_ = ObTimeUtility::current_time(); } @@ -2324,15 +1908,15 @@ bool ObMemtable::ready_for_flush_() void ObMemtable::print_ready_for_flush() { int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); + share::ObLSID ls_id = get_ls_id(); const common::ObTabletID tablet_id = key_.tablet_id_; bool frozen_memtable_flag = is_frozen_memtable(); int64_t write_ref = get_write_ref(); SCN end_scn = get_end_scn(); SCN current_right_boundary; uint32_t logstream_freeze_clock = freezer_->get_freeze_clock(); - uint32_t memtable_freeze_clock = freeze_clock_; - if (OB_FAIL(get_ls_current_right_boundary(current_right_boundary))) { + uint32_t memtable_freeze_clock = get_freeze_clock(); + if (OB_FAIL(get_ls_current_right_boundary_(current_right_boundary))) { TRANS_LOG(WARN, "fail to get current right boundary", K(ret)); } bool bool_ret = frozen_memtable_flag && @@ -2464,79 +2048,6 @@ int ObMemtable::resolve_max_end_scn_() return ret; } -// implement NOTE: -// call this function must ensure all TxNodes on memtable has been -// logged and the log's either synced successfully or synced failed. -// because otherwise the max_end_scn is not correct and which may be larger than -// the max value of valid TxNode(s)'s log_scn, which cause an incorrect right -// boundary value, and an incorrect left boundary value of next active memtable -// -// when TxNode's log synced failed, Txn's function will process to adjust the -// max_end_scn of this memtable, finally, the memtable will has a correct right -// boundary value, keep the safety: -// future data's log_scn > max_end_scn of this memtable -int ObMemtable::resolve_right_boundary() -{ - SCN max_end_scn = get_max_end_scn(); - SCN end_scn = max_end_scn; - SCN start_scn = get_start_scn(); - int ret = OB_SUCCESS; - - if (ObScnRange::MIN_SCN == max_end_scn) { - end_scn = start_scn; - (void)freezer_->inc_empty_memtable_cnt(); - } - if (OB_FAIL(set_end_scn(end_scn))) { - TRANS_LOG(ERROR, "fail to set end_scn", K(ret)); - } - - return ret; -} - -int ObMemtable::resolve_right_boundary_for_migration() -{ - bool bool_ret = false; - int ret = OB_SUCCESS; - share::ObLSID ls_id = freezer_->get_ls_id(); - int64_t start_time = ObTimeUtility::current_time(); - - do { - bool_ret = is_frozen_memtable() && 0 == get_write_ref(); - if (bool_ret) { - if (OB_FAIL(resolve_snapshot_version_())) { - TRANS_LOG(WARN, "fail to resolve snapshot version", K(ret), KPC(this), K(ls_id)); - } else if (OB_FAIL(resolve_max_end_scn_())) { - TRANS_LOG(WARN, "fail to resolve max_end_scn", K(ret), KPC(this), K(ls_id)); - } else { - resolve_right_boundary(); - TRANS_LOG(INFO, "resolve_right_boundary_for_migration", K(ls_id), KPC(this)); - } - } else { - const int64_t cost_time = ObTimeUtility::current_time() - start_time; - if (cost_time > 5 * 1000 * 1000) { - if (TC_REACH_TIME_INTERVAL(5 * 1000 * 1000)) { - TRANS_LOG(WARN, "cannot resolve_right_boundary_for_migration", K(ret), KPC(this), K(ls_id)); - } - } - ob_usleep(100); - } - } while (!bool_ret); - - return ret; -} - -void ObMemtable::resolve_left_boundary(SCN end_scn) -{ - set_start_scn(end_scn); -} - -void ObMemtable::set_freeze_state(const int64_t state) -{ - if (state >= ObMemtableFreezeState::NOT_READY_FOR_FLUSH && - state <= ObMemtableFreezeState::RELEASED) { - freeze_state_ = state; - } -} DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(UpdateScheduleDagTime, update_schedule_dag_time) int ObMemtable::flush(share::ObLSID ls_id) @@ -2545,7 +2056,7 @@ int ObMemtable::flush(share::ObLSID ls_id) int tmp_ret = OB_SUCCESS; int64_t cur_time = ObTimeUtility::current_time(); - if (is_flushed_) { + if (get_is_flushed()) { ret = OB_NO_NEED_UPDATE; } else { ObTabletMergeDagParam param; @@ -2596,30 +2107,6 @@ void ObMemtable::fill_compaction_param_( compaction_param.estimate_phy_size_ = mt_stat_.row_size_; } -bool ObMemtable::is_active_memtable() const -{ - return !is_frozen_memtable(); -} - -bool ObMemtable::is_frozen_memtable() const -{ - // Note (yanyuan.cxf) log_frozen_memstore_info() will use this func after local_allocator_ init - // Now freezer_ and ls_ will not be released before memtable - const uint32_t logstream_freeze_clock = OB_NOT_NULL(freezer_) ? freezer_->get_freeze_clock() : 0; - const uint32_t memtable_freeze_clock = get_freeze_clock(); - if (!allow_freeze() && logstream_freeze_clock > memtable_freeze_clock) { - ATOMIC_STORE(&freeze_clock_, logstream_freeze_clock); - TRANS_LOG(INFO, "inc freeze_clock because the memtable cannot be freezed", K(memtable_freeze_clock), K(logstream_freeze_clock), KPC(this)); - } - const bool bool_ret = logstream_freeze_clock > get_freeze_clock() || is_tablet_freeze_; - - if (bool_ret && 0 == mt_stat_.frozen_time_) { - mt_stat_.frozen_time_ = ObTimeUtility::current_time(); - } - - return bool_ret; -} - int ObMemtable::estimate_phy_size(const ObStoreRowkey* start_key, const ObStoreRowkey* end_key, int64_t& total_bytes, int64_t& total_rows) { int ret = OB_SUCCESS; @@ -2856,19 +2343,6 @@ int ObMemtable::dump2text(const char *fname) return ret; } -void ObMemtable::set_max_schema_version(const int64_t schema_version) -{ - if (INT64_MAX == schema_version) { - TRANS_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "invalid schema version", K(schema_version), KPC(this)); - } else { - inc_update(&max_schema_version_, schema_version); - } -} - -int64_t ObMemtable::get_max_schema_version() const -{ - return ATOMIC_LOAD(&max_schema_version_); -} void ObMemtable::set_max_data_schema_version(const int64_t schema_version) { @@ -2966,12 +2440,6 @@ int64_t ObMemtable::get_upper_trans_version() const return INT64_MAX; } -int ObMemtable::get_active_table_ids(common::ObIArray &table_ids) -{ - int ret = OB_NOT_SUPPORTED; - return ret; -} - #ifdef OB_BUILD_TDE_SECURITY int ObMemtable::save_encrypt_meta(const uint64_t table_id, const share::ObEncryptMeta *encrypt_meta) { @@ -3026,34 +2494,6 @@ bool ObMemtable::need_for_save(const share::ObEncryptMeta *encrypt_meta) } #endif -int RowHeaderGetter::get() -{ - int ret = OB_ENTRY_NOT_EXIST; - //const ObIArray *stores = ctx_.tables_; - // FIXME. xiaoshi -// if (NULL != stores) { - // ignore active memtable - /* - for (int64_t i = stores->count() - 2; OB_ENTRY_NOT_EXIST == ret && i >= 0; i--) { - ObITable *store = stores->at(i); - if (OB_FAIL(store->get_row_header(ctx_, table_id_, rowkey_, columns_, - modify_count_, acc_checksum_))) { - if (OB_ENTRY_NOT_EXIST != ret) { - TRANS_LOG(WARN, "get row heade error", K(ret), K(i), KP(stores->at(i))); - } - } - } - */ -// } - if (OB_ENTRY_NOT_EXIST == ret) { - modify_count_ = 0; - acc_checksum_ = 0; - // rewrite ret - ret = OB_SUCCESS; - } - return ret; -} - int ObMemtable::multi_set_( const storage::ObTableIterParam ¶m, const common::ObIArray &columns, @@ -3201,7 +2641,7 @@ int ObMemtable::set_( ctx.mvcc_acc_ctx_.tx_id_, /*trans id*/ &mtd, /*memtable_data*/ NULL == old_row ? NULL : &old_row_data, - timestamp_, /*memstore_version*/ + init_timestamp_, /*memstore_version*/ ctx.mvcc_acc_ctx_.tx_scn_, /*seq_no*/ new_row.row_val_.count_ /*column_cnt*/); if (OB_FAIL(mvcc_write_(param, @@ -3285,7 +2725,7 @@ int ObMemtable::lock_( ObTxNodeArg arg(acc_ctx.tx_id_, /*trans id*/ &mtd, /*memtable_data*/ NULL, /*old_data*/ - timestamp_, /*memstore_version*/ + init_timestamp_, /*memstore_version*/ acc_ctx.tx_scn_, /*seq_no*/ rowkey.get_obj_cnt()); /*column_cnt*/ if (acc_ctx.write_flag_.is_check_row_locked()) { @@ -3316,7 +2756,6 @@ int ObMemtable::mvcc_replay_(storage::ObStoreCtx &ctx, int ret = OB_SUCCESS; ObMemtableKey stored_key; ObMvccRow *value = NULL; - RowHeaderGetter getter; bool is_new_add = false; ObMemtableCtx *mem_ctx = ctx.mvcc_acc_ctx_.get_mem_ctx(); ObMvccReplayResult res; @@ -3326,7 +2765,6 @@ int ObMemtable::mvcc_replay_(storage::ObStoreCtx &ctx, false, // is_insert &stored_key, value, - getter, is_new_add))) { TRANS_LOG(WARN, "prepare kv before lock fail", K(ret)); } else if (FALSE_IT(timeguard.click("mvcc_engine_.create_kv"))) { @@ -3363,7 +2801,6 @@ int ObMemtable::mvcc_write_( int ret = OB_SUCCESS; bool is_new_add = false; ObMemtableKey stored_key; - RowHeaderGetter getter; ObMvccRow *value = NULL; ObMvccWriteResult res; ObStoreCtx &ctx = *(context.store_ctx_); @@ -3376,7 +2813,6 @@ int ObMemtable::mvcc_write_( blocksstable::ObDmlFlag::DF_INSERT == arg.data_->dml_flag_, &stored_key, value, - getter, is_new_add))) { TRANS_LOG(WARN, "create kv failed", K(ret), K(arg), K(*key)); } else if (OB_FAIL(mvcc_engine_.mvcc_write(ctx, @@ -3542,15 +2978,82 @@ int ObMemtable::get_tx_table_guard(ObTxTableGuard &tx_table_guard) return ret; } -int ObMemtable::set_memtable_mgr_(storage::ObTabletMemtableMgr *mgr) +bool ObMemtable::rec_scn_is_stable() { - ObTabletMemtableMgrPool *pool = MTL(ObTabletMemtableMgrPool*); - return memtable_mgr_handle_.set_memtable_mgr(mgr, pool); + int ret = OB_SUCCESS; + bool rec_scn_is_stable = false; + if (SCN::max_scn() == get_rec_scn()) { + rec_scn_is_stable = (is_frozen_memtable() && get_write_ref() == 0 && get_unsubmitted_cnt() == 0); + } else { + SCN max_consequent_callbacked_scn; + if (OB_FAIL(freezer_->get_max_consequent_callbacked_scn(max_consequent_callbacked_scn))) { + STORAGE_LOG(WARN, "get_max_consequent_callbacked_scn failed", K(ret), K(get_ls_id())); + } else { + rec_scn_is_stable = (max_consequent_callbacked_scn >= get_rec_scn()); + } + + if (!rec_scn_is_stable && + (mt_stat_.frozen_time_ != 0 && + ObTimeUtility::current_time() - mt_stat_.frozen_time_ > 10 * 1000 * 1000L)) { + STORAGE_LOG(WARN, "memtable rec_scn not stable for long time", + K(get_ls_id()), K(*this), K(mt_stat_.frozen_time_), + K(max_consequent_callbacked_scn)); + + int tmp_ret = OB_SUCCESS; + if (OB_TMP_FAIL(ADD_SUSPECT_INFO(compaction::ObMergeType::MINI_MERGE, + ObDiagnoseTabletType::TYPE_MINI_MERGE, + get_ls_id(), + get_tablet_id(), + ObSuspectInfoType::SUSPECT_REC_SCN_NOT_STABLE, + get_rec_scn().get_val_for_tx(), + max_consequent_callbacked_scn.get_val_for_tx()))) { + STORAGE_LOG(WARN, "failed to add suspect info", K(tmp_ret)); + } + } + } + return rec_scn_is_stable; } -storage::ObTabletMemtableMgr *ObMemtable::get_memtable_mgr_() +int64_t ObMemtable::dec_write_ref() { - return static_cast(memtable_mgr_handle_.get_memtable_mgr()); + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + + // fix issue 47021079 + // To avoid the following case where logging_block cannot be unset: + // ----------------------------------------------------- + // dec_write_ref() dec_unsubmitted_cnt() + // ----------------------------------------------------- + // is_frozen is_frozen + // get write_ref_cnt 1 + // dec write_ref to 0 + // get unsubmitted_cnt 1 + // dec unsubmitted_cnt to 0 + // ----------------------------------------------------- + int64_t old_write_ref_cnt = dec_write_ref_(); + + // must maintain the order of getting variables to avoid concurrency problems + // is_frozen_memtable() can affect wirte_ref_cnt + // write_ref_cnt can affect unsubmitted_cnt + bool is_frozen = is_frozen_memtable(); + int64_t new_write_ref_cnt = get_write_ref(); + int64_t unsubmitted_cnt = get_unsubmitted_cnt(); + if (is_frozen && + 0 == new_write_ref_cnt && + 0 == unsubmitted_cnt) { + (void)unset_logging_blocked_for_active_memtable_(); + share::SCN right_boundary; + if (OB_FAIL(get_ls_current_right_boundary_(right_boundary))) { + TRANS_LOG(WARN, "get ls right bound fail", K(ret), K(ls_id), KPC(this)); + } else if (right_boundary >= get_max_end_scn()) { + resolve_right_boundary(); + if (OB_LIKELY(!get_resolved_active_memtable_left_boundary())) { + resolve_left_boundary_for_active_memtable_(); + } + } + } + + return old_write_ref_cnt; } int ObMemtable::try_report_dml_stat_(const int64_t table_id) @@ -3593,11 +3096,34 @@ int ObMemtable::finish_freeze() if (OB_FAIL(ObFreezeCheckpoint::finish_freeze())) { TRANS_LOG(WARN, "fail to finish_freeze", KR(ret)); } else { - report_memtable_diagnose_info(UpdateFreezeInfo(*this)); + report_memtable_diagnose_info(TabletMemtableUpdateFreezeInfo(*this)); } return ret; } +bool ObMemtable::is_frozen_memtable() +{ + // Note (yanyuan.cxf) log_frozen_memstore_info() will use this func after local_allocator_ init + // Now freezer_ and ls_ will not be released before memtable + const uint32_t logstream_freeze_clock = OB_NOT_NULL(freezer_) ? freezer_->get_freeze_clock() : 0; + const uint32_t memtable_freeze_clock = get_freeze_clock(); + if (!allow_freeze() && logstream_freeze_clock > memtable_freeze_clock) { + ATOMIC_STORE(&freeze_clock_, logstream_freeze_clock); + TRANS_LOG(INFO, + "inc freeze_clock because the memtable cannot be freezed", + K(memtable_freeze_clock), + K(logstream_freeze_clock), + KPC(this)); + } + const bool bool_ret = logstream_freeze_clock > get_freeze_clock() || is_tablet_freeze_; + + if (bool_ret && 0 == get_frozen_time()) { + set_frozen_time(ObClockGenerator::getClock()); + } + + return bool_ret; +} + int ObMemtable::report_residual_dml_stat_() { int ret = OB_SUCCESS; diff --git a/src/storage/memtable/ob_memtable.h b/src/storage/memtable/ob_memtable.h index 20da97e77..1805260f1 100644 --- a/src/storage/memtable/ob_memtable.h +++ b/src/storage/memtable/ob_memtable.h @@ -12,38 +12,28 @@ #ifndef OCEANBASE_MEMTABLE_OB_MEMTABLE_ #define OCEANBASE_MEMTABLE_OB_MEMTABLE_ -#include "share/allocator/ob_memstore_allocator.h" +#include "share/allocator/ob_memstore_allocator.h" #include "share/ob_tenant_mgr.h" #include "share/ob_cluster_version.h" #include "lib/literals/ob_literals.h" #include "lib/worker.h" -#include "storage/memtable/ob_memtable_interface.h" -#include "storage/memtable/mvcc/ob_query_engine.h" -#include "storage/memtable/mvcc/ob_mvcc_engine.h" -#include "storage/memtable/ob_memtable_data.h" -#include "storage/memtable/ob_memtable_key.h" -#include "storage/memtable/ob_row_compactor.h" -#include "storage/memtable/ob_multi_source_data.h" + +#include "storage/ob_i_tablet_memtable.h" #include "storage/ob_i_memtable_mgr.h" -#include "storage/checkpoint/ob_freeze_checkpoint.h" -#include "storage/compaction/ob_medium_compaction_mgr.h" -#include "storage/tx_storage/ob_ls_handle.h" //ObLSHandle +#include "storage/memtable/mvcc/ob_mvcc_engine.h" +#include "storage/memtable/mvcc/ob_query_engine.h" #include "storage/blocksstable/ob_sstable.h" #include "storage/checkpoint/ob_checkpoint_diagnose.h" namespace oceanbase { -namespace common -{ -class ObVersion; -class ObTabletID; -} namespace storage { class ObTabletMemtableMgr; class ObFreezer; class ObStoreRowIterator; +class ObRowState; } namespace compaction { @@ -51,40 +41,7 @@ class ObTabletMergeDagParam; } namespace memtable { -class ObMemtableScanIterator; -class ObMemtableGetIterator; - - -/* - * Attention! When tx is rollback, insert/update/delete row count and size will not reduced accordingly - */ -struct ObMtStat -{ - ObMtStat() { reset(); } - ~ObMtStat() = default; - void reset() { memset(this, 0, sizeof(*this));} - TO_STRING_KV(K_(insert_row_count), - K_(update_row_count), - K_(delete_row_count), - K_(empty_mvcc_row_count), - K_(frozen_time), - K_(ready_for_flush_time), - K_(create_flush_dag_time), - K_(release_time), - K_(last_print_time), - K_(row_size)); - int64_t insert_row_count_; - int64_t update_row_count_; - int64_t delete_row_count_; - int64_t empty_mvcc_row_count_; - int64_t frozen_time_; - int64_t ready_for_flush_time_; - int64_t create_flush_dag_time_; - int64_t release_time_; - int64_t push_table_into_gc_queue_time_; - int64_t last_print_time_; - int64_t row_size_; -}; +class ObMemtableMutatorIterator; // report the dml stat to ObOptStatMonitorManager struct ObReportedDmlStat @@ -187,32 +144,6 @@ private: DISALLOW_COPY_AND_ASSIGN(ObMTKVBuilder); }; -class ObMemtableState -{ -public: - static const int64_t INVALID = -1; - static const int64_t ACTIVE = 0; - static const int64_t MAJOR_FROZEN = 1; - static const int64_t MINOR_FROZEN = 2; - static const int64_t MAJOR_MERGING = 3; - static const int64_t MINOR_MERGING = 4; -public: - bool is_valid(const int64_t state) { return state >= ACTIVE && state <= MINOR_MERGING; } -}; - -class ObMemtableFreezeState -{ -public: - static const int64_t INVALID = -1; - static const int64_t NOT_READY_FOR_FLUSH = 0; - static const int64_t READY_FOR_FLUSH = 1; - static const int64_t FLUSHED = 2; - static const int64_t RELEASED = 3; -}; - -class ObMemtableMutatorIterator; -class ObEncryptRowBuf; - enum class MemtableRefOp { NONE = 0, @@ -220,35 +151,17 @@ enum class MemtableRefOp DEC_REF }; -class ObMemtable : public ObIMemtable, public storage::checkpoint::ObFreezeCheckpoint +class ObMemtable : public ObITabletMemtable { public: using ObMvccRowAndWriteResults = common::ObSEArray; typedef share::ObMemstoreAllocator::AllocHandle ObSingleMemstoreAllocator; -#define DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(function, update_function) \ -struct function \ -{ \ -public: \ - function() {} \ - function(const function&) = delete; \ - function& operator=(const function&) = delete; \ - void operator()(const checkpoint::ObCheckpointDiagnoseParam& param) const \ - { \ - checkpoint::ObCheckpointDiagnoseMgr *cdm = MTL(checkpoint::ObCheckpointDiagnoseMgr*); \ - if (OB_NOT_NULL(cdm)) { \ - cdm->update_function(param); \ - } \ - } \ -}; -DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(UpdateStartGCTimeForMemtable, update_start_gc_time_for_memtable) -DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(AddCheckpointDiagnoseInfoForMemtable, add_diagnose_info) - -struct UpdateFreezeInfo +struct TabletMemtableUpdateFreezeInfo { public: - UpdateFreezeInfo(ObMemtable &memtable) : memtable_(memtable) {} - UpdateFreezeInfo& operator=(const UpdateFreezeInfo&) = delete; + TabletMemtableUpdateFreezeInfo(ObMemtable &memtable) : memtable_(memtable) {} + TabletMemtableUpdateFreezeInfo& operator=(const TabletMemtableUpdateFreezeInfo&) = delete; void operator()(const checkpoint::ObCheckpointDiagnoseParam& param) const { checkpoint::ObCheckpointDiagnoseMgr *cdm = MTL(checkpoint::ObCheckpointDiagnoseMgr*); @@ -292,18 +205,28 @@ private: public: ObMemtable(); virtual ~ObMemtable(); -public: - int init(const ObITable::TableKey &table_key, - ObLSHandle &ls_handle, - storage::ObFreezer *freezer, - storage::ObTabletMemtableMgr *memtable_mgr, - const int64_t schema_version, - const uint32_t freeze_clock); - virtual void destroy(); - virtual int safe_to_destroy(bool &is_safe); - OB_INLINE void reset() { destroy(); } -public: + virtual void destroy(); + +public: // derived from ObFreezeCheckpoint + virtual bool rec_scn_is_stable() override; + virtual bool ready_for_flush() override; + +public: // derived from ObITabletMemtable + virtual int init(const ObITable::TableKey &table_key, + ObLSHandle &ls_handle, + storage::ObFreezer *freezer, + storage::ObTabletMemtableMgr *memtable_mgr, + const int64_t schema_version, + const uint32_t freeze_clock) override; + virtual void print_ready_for_flush() override; + virtual void set_allow_freeze(const bool allow_freeze) override; + virtual int set_frozen() override { local_allocator_.set_frozen(); return OB_SUCCESS; } + virtual bool is_inited() const override { return is_inited_; } + virtual int64_t dec_write_ref() override; + virtual bool is_frozen_memtable() override; + +public: // derived from ObITable // ==================== Memtable Operation Interface ================== // set is used to insert/update the row @@ -434,27 +357,14 @@ public: storage::ObStoreCtx &ctx, const share::SCN &scn, ObMemtableMutatorIterator *mmi); - virtual int replay_schema_version_change_log( - const int64_t schema_version); + virtual int replay_schema_version_change_log(const int64_t schema_version); + virtual int safe_to_destroy(bool &is_safe); - // // TODO: ==================== Memtable Other Interface ================== - int set_freezer(storage::ObFreezer *handler); - storage::ObFreezer *get_freezer() { return freezer_; } - int get_ls_id(share::ObLSID &ls_id); - ObLSHandle &get_ls_handle() { return ls_handle_; } - int set_memtable_mgr_(storage::ObTabletMemtableMgr *mgr); - storage::ObTabletMemtableMgr *get_memtable_mgr_(); - void set_freeze_clock(const uint32_t freeze_clock) { ATOMIC_STORE(&freeze_clock_, freeze_clock); } - uint32_t get_freeze_clock() const { return ATOMIC_LOAD(&freeze_clock_); } - int set_emergency(const bool emergency); - ObMtStat& get_mt_stat() { return mt_stat_; } - const ObMtStat& get_mt_stat() const { return mt_stat_; } +public: int64_t get_size() const; int64_t get_occupied_size() const; int64_t get_physical_row_cnt() const { return query_engine_.btree_size(); } inline bool not_empty() const { return INT64_MAX != get_protection_clock(); }; - void set_max_schema_version(const int64_t schema_version); - virtual int64_t get_max_schema_version() const override; void set_max_data_schema_version(const int64_t schema_version); int64_t get_max_data_schema_version() const; void set_max_column_cnt(const int64_t column_cnt); @@ -470,33 +380,14 @@ public: int64_t get_hash_alloc_memory() const; int64_t get_btree_item_count() const; int64_t get_btree_alloc_memory() const; - virtual bool can_be_minor_merged() override; + virtual int get_frozen_schema_version(int64_t &schema_version) const override; - virtual bool is_frozen_memtable() const override; - virtual bool is_active_memtable() const override; virtual bool is_inner_tablet() const { return key_.tablet_id_.is_inner_tablet(); } - ObTabletID get_tablet_id() const { return key_.tablet_id_; } int set_snapshot_version(const share::SCN snapshot_version); - int64_t get_freeze_state() const { return freeze_state_; } + int64_t get_memtable_state() const { return state_; } int64_t get_protection_clock() const { return local_allocator_.get_protection_clock(); } int64_t get_retire_clock() const { return local_allocator_.get_retire_clock(); } - int get_ls_current_right_boundary(share::SCN ¤t_right_boundary); - inline bool& get_read_barrier() { return read_barrier_; } - inline void set_write_barrier() { write_barrier_ = true; } - inline void unset_write_barrier() { write_barrier_ = false; } - inline void set_read_barrier() { read_barrier_ = true; } - virtual int64_t inc_write_ref() override { return inc_write_ref_(); } - virtual int64_t dec_write_ref() override; - virtual int64_t get_write_ref() const override { return ATOMIC_LOAD(&write_ref_cnt_); } - inline void set_is_tablet_freeze() { is_tablet_freeze_ = true; } - inline bool get_is_tablet_freeze() { return is_tablet_freeze_; } - inline void set_is_flushed() { is_flushed_ = true; } - inline bool get_is_flushed() { return is_flushed_; } - inline void unset_active_memtable_logging_blocked() { ATOMIC_STORE(&unset_active_memtable_logging_blocked_, true); } - inline void set_resolved_active_memtable_left_boundary(bool flag) { ATOMIC_STORE(&resolved_active_memtable_left_boundary_, flag); } - inline bool get_resolved_active_memtable_left_boundary() { return ATOMIC_LOAD(&resolved_active_memtable_left_boundary_); } - void set_freeze_state(const int64_t state); void set_minor_merged(); int64_t get_minor_merged_time() const { return minor_merged_time_; } common::ObIAllocator &get_allocator() {return local_allocator_;} @@ -513,63 +404,24 @@ public: ObQueryEngine &get_query_engine() { return query_engine_; } ObMvccEngine &get_mvcc_engine() { return mvcc_engine_; } const ObMvccEngine &get_mvcc_engine() const { return mvcc_engine_; } - OB_INLINE bool is_inited() const { return is_inited_;} void pre_batch_destroy_keybtree(); static int batch_remove_unused_callback_for_uncommited_txn( const share::ObLSID ls_id, const memtable::ObMemtableSet *memtable_set); /* freeze */ - virtual int set_frozen() override { local_allocator_.set_frozen(); return OB_SUCCESS; } - virtual bool rec_scn_is_stable() override; - virtual bool ready_for_flush() override; - void print_ready_for_flush(); virtual int flush(share::ObLSID ls_id) override; - share::SCN get_rec_scn() { return rec_scn_.atomic_get(); } - virtual bool is_frozen_checkpoint() const override { return is_frozen_memtable();} - virtual bool is_active_checkpoint() const override { return is_active_memtable();} - virtual OB_INLINE share::SCN get_end_scn() const - { - return key_.scn_range_.end_scn_; - } - virtual OB_INLINE share::SCN get_start_scn() const - { - return key_.scn_range_.start_scn_; - } bool is_empty() const override { - return get_end_scn() == get_start_scn() && + return ObITable::get_end_scn() == ObITable::get_start_scn() && share::ObScnRange::MIN_SCN == get_max_end_scn(); } - int resolve_right_boundary(); - void resolve_left_boundary(share::SCN end_scn); void fill_compaction_param_( const int64_t current_time, compaction::ObTabletMergeDagParam ¶m); int resolve_snapshot_version_(); int resolve_max_end_scn_(); - share::SCN get_max_end_scn() const { return max_end_scn_.atomic_get(); } - int set_rec_scn(share::SCN rec_scn); - int set_start_scn(const share::SCN start_ts); - int set_end_scn(const share::SCN freeze_ts); - int set_max_end_scn(const share::SCN scn, bool allow_backoff = false); - int set_max_end_scn_to_inc_start_scn(); - inline int set_logging_blocked() - { - logging_blocked_start_time = common::ObTimeUtility::current_time(); - ATOMIC_STORE(&logging_blocked_, true); - return OB_SUCCESS; - } - inline void unset_logging_blocked() - { - if (get_logging_blocked()) { - ATOMIC_STORE(&logging_blocked_, false); - int64_t cost_time = common::ObTimeUtility::current_time() - logging_blocked_start_time; - TRANS_LOG(INFO, "the cost time of logging blocked: ", K(cost_time), K(this), K(key_.tablet_id_)); - } - } - inline bool get_logging_blocked() { return ATOMIC_LOAD(&logging_blocked_); } // User should take response of the recommend scn. All version smaller than // recommend scn should belong to the tables before the memtable and the // memtable. And under exception case, user need guarantee all new data is @@ -580,23 +432,10 @@ public: ATOMIC_STORE(&transfer_freeze_flag_, true); } inline bool is_transfer_freeze() const { return ATOMIC_LOAD(&transfer_freeze_flag_); } - int64_t get_unsubmitted_cnt() const { return ATOMIC_LOAD(&unsubmitted_cnt_); } - int inc_unsubmitted_cnt(); - int dec_unsubmitted_cnt(); virtual uint32_t get_freeze_flag() override; - virtual OB_INLINE int64_t get_timestamp() const override { return timestamp_; } - void inc_timestamp(const int64_t timestamp) { timestamp_ = MAX(timestamp_, timestamp + 1); } - int get_active_table_ids(common::ObIArray &table_ids); blocksstable::ObDatumRange &m_get_real_range(blocksstable::ObDatumRange &real_range, const blocksstable::ObDatumRange &range, const bool is_reverse) const; int get_tx_table_guard(storage::ObTxTableGuard &tx_table_guard); - int set_migration_clog_checkpoint_scn(const share::SCN &clog_checkpoint_scn); - share::SCN get_migration_clog_checkpoint_scn() { return migration_clog_checkpoint_scn_.atomic_get(); } - int resolve_right_boundary_for_migration(); - void unset_logging_blocked_for_active_memtable(); - void resolve_left_boundary_for_active_memtable(); - void set_allow_freeze(const bool allow_freeze); - inline bool allow_freeze() const { return ATOMIC_LOAD(&allow_freeze_); } #ifdef OB_BUILD_TDE_SECURITY /*clog encryption related*/ @@ -613,52 +452,26 @@ public: int64_t &count); int dump2text(const char *fname); // TODO(handora.qc) ready_for_flush interface adjustment - bool is_can_flush() { return ObMemtableFreezeState::READY_FOR_FLUSH == freeze_state_ && share::SCN::max_scn() != get_end_scn(); } + virtual int finish_freeze(); - virtual int64_t dec_ref() - { - int64_t ref_cnt = ObITable::dec_ref(); - if (0 == ref_cnt) { - report_memtable_diagnose_info(UpdateStartGCTimeForMemtable()); - } - return ref_cnt; - } - - template - void report_memtable_diagnose_info(const OP &op) - { - int ret = OB_SUCCESS; - // logstream freeze - if (!get_is_tablet_freeze()) { - share::ObLSID ls_id; - if (OB_FAIL(get_ls_id(ls_id))) { - TRANS_LOG(WARN, "failed to get ls id", KPC(this)); - } else { - checkpoint::ObCheckpointDiagnoseParam param(ls_id.id(), get_freeze_clock(), get_tablet_id(), (void*)this); - op(param); - } - } - // batch tablet freeze - else if (checkpoint::INVALID_TRACE_ID != get_trace_id()) { - checkpoint::ObCheckpointDiagnoseParam param(trace_id_, get_tablet_id(), (void*)this); - op(param); - } - } - - INHERIT_TO_STRING_KV("ObITable", ObITable, KP(this), K_(timestamp), - K_(freeze_clock), K_(max_schema_version), K_(max_data_schema_version), K_(max_column_cnt), - K_(write_ref_cnt), K_(local_allocator), K_(unsubmitted_cnt), - K_(logging_blocked), K_(unset_active_memtable_logging_blocked), K_(resolved_active_memtable_left_boundary), - K_(contain_hotspot_row), K_(max_end_scn), K_(rec_scn), K_(snapshot_version), K_(migration_clog_checkpoint_scn), - K_(is_tablet_freeze), K_(contain_hotspot_row), - K_(read_barrier), K_(is_flushed), K_(freeze_state), K_(allow_freeze), - K_(mt_stat_.frozen_time), K_(mt_stat_.ready_for_flush_time), - K_(mt_stat_.create_flush_dag_time), K_(mt_stat_.release_time), - K_(mt_stat_.push_table_into_gc_queue_time), - K_(mt_stat_.last_print_time), K_(ls_id), K_(transfer_freeze_flag), K_(recommend_snapshot_version)); + INHERIT_TO_STRING_KV("ObITabletMemtable", + ObITabletMemtable, + KP(this), + K_(state), + K_(max_data_schema_version), + K_(max_column_cnt), + K_(local_allocator), + K_(contain_hotspot_row), + K_(snapshot_version), + K_(contain_hotspot_row), + K_(ls_id), + K_(transfer_freeze_flag), + K_(recommend_snapshot_version)); private: static const int64_t OB_EMPTY_MEMSTORE_MAX_SIZE = 10L << 20; // 10MB + + int get_all_tables_(ObStoreCtx &ctx, ObIArray &iter_tables); int mvcc_write_( const storage::ObTableIterParam ¶m, storage::ObTableAccessContext &context, @@ -704,6 +517,14 @@ private: ObMvccRowAndWriteResults &mvcc_rows, ObRowsInfo &rows_info); + int internal_lock_row_on_frozen_stores_(const bool check_exist, + const ObMemtableKey *key, + const storage::ObTableIterParam ¶m, + const ObIArray &iter_tables, + storage::ObTableAccessContext &context, + ObMvccWriteResult &res, + ObRowState &row_state); + int internal_lock_rows_on_frozen_stores_( const bool check_exist, const ObIArray &iter_tables, @@ -753,10 +574,6 @@ private: const int64_t last_compact_cnt, const int64_t total_trans_node_count); bool ready_for_flush_(); - int64_t inc_write_ref_(); - int64_t dec_write_ref_(); - int64_t inc_unsubmitted_cnt_(); - int64_t dec_unsubmitted_cnt_(); int64_t try_split_range_for_sample_(const ObStoreRowkey &start_key, const ObStoreRowkey &end_key, const int64_t range_count, @@ -769,41 +586,19 @@ private: DISALLOW_COPY_AND_ASSIGN(ObMemtable); bool is_inited_; storage::ObLSHandle ls_handle_; - storage::ObFreezer *freezer_; - storage::ObMemtableMgrHandle memtable_mgr_handle_; - mutable uint32_t freeze_clock_; ObSingleMemstoreAllocator local_allocator_; ObMTKVBuilder kv_builder_; ObQueryEngine query_engine_; ObMvccEngine mvcc_engine_; - mutable ObMtStat mt_stat_; mutable ObReportedDmlStat reported_dml_stat_; - int64_t max_schema_version_; // to record the max schema version of memtable & schema_change_clog int64_t max_data_schema_version_; // to record the max schema version of write data - int64_t pending_cb_cnt_; // number of transactions have to sync log - int64_t unsubmitted_cnt_; // number of trans node to be submitted logs - bool logging_blocked_; // flag whether the memtable can submit log, cannot submit if true - int64_t logging_blocked_start_time; // record the start time of logging blocked - bool unset_active_memtable_logging_blocked_; - bool resolved_active_memtable_left_boundary_; // TODO(handora.qc): remove it as soon as possible // only used for decide special right boundary of memtable bool transfer_freeze_flag_; // only used for decide special snapshot version of memtable share::SCN recommend_snapshot_version_; - share::SCN freeze_scn_; - share::SCN max_end_scn_; - share::SCN rec_scn_; - int64_t freeze_state_; - int64_t timestamp_; - share::SCN migration_clog_checkpoint_scn_; - bool is_tablet_freeze_; - bool is_flushed_; - bool read_barrier_ CACHE_ALIGNED; - bool write_barrier_; - bool allow_freeze_; - int64_t write_ref_cnt_ CACHE_ALIGNED; + int64_t state_; lib::Worker::CompatMode mode_; int64_t minor_merged_time_; bool contain_hotspot_row_; @@ -812,19 +607,7 @@ private: int64_t max_column_cnt_; // record max column count of row }; -class RowHeaderGetter -{ -public: - RowHeaderGetter() : modify_count_(0), acc_checksum_(0) {} - ~RowHeaderGetter() {} - uint32_t get_modify_count() const { return modify_count_; } - uint32_t get_acc_checksum() const { return acc_checksum_; } - int get(); -private: - uint32_t modify_count_; - uint32_t acc_checksum_; -}; -} -} +} // namespace memtable +} // namespace oceanbase #endif //OCEANBASE_MEMTABLE_OB_MEMTABLE_ diff --git a/src/storage/memtable/ob_memtable_interface.cpp b/src/storage/memtable/ob_memtable_interface.cpp index f0a395604..f3e285052 100644 --- a/src/storage/memtable/ob_memtable_interface.cpp +++ b/src/storage/memtable/ob_memtable_interface.cpp @@ -10,60 +10,20 @@ * See the Mulan PubL v2 for more details. */ -#include "lib/allocator/ob_pcounter.h" - -#include "storage/memtable/ob_memtable_context.h" -#include "storage/memtable/ob_memtable.h" +#include "ob_memtable_interface.h" namespace oceanbase { -using namespace common; -namespace memtable +using namespace share; +namespace storage { -//////////////////////////////////////////////////////////////////////////////////////////////////// - -int64_t ObMemtableFactory::alloc_count_ = 0; -int64_t ObMemtableFactory::free_count_ = 0; - -ObMemtableFactory::ObMemtableFactory() -{ +int ObIMemtable::get_ls_id(ObLSID &ls_id) { + int ret = OB_SUCCESS; + ls_id = get_ls_id(); + return ret; } +ObLSID ObIMemtable::get_ls_id() const { return ls_id_; } -ObMemtableFactory::~ObMemtableFactory() -{ -} - -ObMemtable *ObMemtableFactory::alloc(const uint64_t tenant_id) -{ - ObMemAttr memattr(tenant_id, ObModIds::OB_MEMTABLE_OBJECT, ObCtxIds::MEMSTORE_CTX_ID); - ObMemtable *mt = NULL; - void *mt_buffer = ob_malloc(sizeof(ObMemtable), memattr); - if (NULL == mt_buffer) { - TRANS_LOG_RET(WARN, OB_ALLOCATE_MEMORY_FAILED, "alloc memory for memtable fail"); - } else if (NULL == (mt = new(mt_buffer) ObMemtable())) { - TRANS_LOG_RET(WARN, OB_ERR_UNEXPECTED, "construct object of memtable fail"); - ob_free(mt_buffer); - mt_buffer = NULL; - } else { - PC_ADD(MT, 1); - (void)ATOMIC_AAF(&alloc_count_, 1); - } - TRANS_LOG(INFO, "alloc memtable", KP(mt), K_(alloc_count), K_(free_count)); - return mt; -} - -void ObMemtableFactory::free(ObMemtable *mt) -{ - if (NULL != mt) { - mt->~ObMemtable(); - ob_free(mt); - (void)ATOMIC_AAF(&free_count_, 1); - TRANS_LOG(INFO, "free memtable", KP(mt), K_(alloc_count), K_(free_count)); - mt = NULL; - PC_ADD(MT, -1); - } -} - -} -} +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/memtable/ob_memtable_interface.h b/src/storage/memtable/ob_memtable_interface.h index 1beb7b840..655779794 100644 --- a/src/storage/memtable/ob_memtable_interface.h +++ b/src/storage/memtable/ob_memtable_interface.h @@ -31,25 +31,12 @@ namespace common { class ObVersion; } -namespace storage -{ -class ObIPartitionGroup; -} -namespace transaction -{ -class ObTransID; -} + namespace memtable { class ObTxFillRedoCtx; -class ObRedoLogSubmitHelper; class ObMemtableCtxCbAllocator; -// Interfaces of Memtable -//////////////////////////////////////////////////////////////////////////////////////////////////// - -class ObIMemtable; -class ObIMultiSourceDataUnit; class ObIMemtableCtx : public ObIMvccCtx { public: @@ -87,57 +74,11 @@ public: common::ActiveResource resource_link_; }; -//////////////////////////////////////////////////////////////////////////////////////////////////// +} // namespace memtable -struct ObMergePriorityInfo -{ - ObMergePriorityInfo() - : tenant_id_(0), - last_freeze_timestamp_(0), - handle_id_(0), - emergency_(false), - protection_clock_(0), - partition_(nullptr) {} - void set_low_priority() - { - tenant_id_ = INT64_MAX; - } - bool is_low_priority() - { - return INT64_MAX == tenant_id_; - } - bool compare(const ObMergePriorityInfo &other) const - { - int64_t cmp = 0; - if (emergency_ != other.emergency_) { - if (emergency_) { - cmp = -1; - } - } else if (tenant_id_ != other.tenant_id_ - && std::min(tenant_id_, other.tenant_id_) < 1000) { - // sys tenant has higher priority - cmp = tenant_id_ - other.tenant_id_; - } else if (last_freeze_timestamp_ != other.last_freeze_timestamp_) { - cmp = last_freeze_timestamp_ - other.last_freeze_timestamp_; - } else if (handle_id_ != other.handle_id_){ - cmp = handle_id_ - other.handle_id_; - } else { - cmp = protection_clock_ - other.protection_clock_; - } - return cmp < 0; - } - TO_STRING_KV(K_(tenant_id), K_(last_freeze_timestamp), K_(handle_id), K_(emergency), - K_(protection_clock), KP_(partition)); - int64_t tenant_id_; - int64_t last_freeze_timestamp_; - int64_t handle_id_; - bool emergency_; - int64_t protection_clock_; - storage::ObIPartitionGroup *partition_; -}; +namespace storage { -class ObIMemtable: public storage::ObITable -{ +class ObIMemtable : public storage::ObITable { public: ObIMemtable() : ls_id_(), @@ -145,55 +86,67 @@ public: trace_id_(checkpoint::INVALID_TRACE_ID) {} virtual ~ObIMemtable() {} - virtual share::ObLSID &get_ls_id() { return ls_id_;} + void reset() + { + ObITable::reset(); + ls_id_.reset(); + snapshot_version_.set_max(); + reset_trace_id(); + } + int get_ls_id(share::ObLSID &ls_id); + share::ObLSID get_ls_id() const; virtual ObTabletID get_tablet_id() const = 0; - virtual int get( - const storage::ObTableIterParam ¶m, - storage::ObTableAccessContext &context, - const blocksstable::ObDatumRowkey &rowkey, - blocksstable::ObDatumRow &row) = 0; + virtual int get(const storage::ObTableIterParam ¶m, + storage::ObTableAccessContext &context, + const blocksstable::ObDatumRowkey &rowkey, + blocksstable::ObDatumRow &row) = 0; virtual int64_t get_frozen_trans_version() { return 0; } virtual int major_freeze(const common::ObVersion &version) - { UNUSED(version); return common::OB_SUCCESS; } + { + UNUSED(version); + return common::OB_SUCCESS; + } virtual int minor_freeze(const common::ObVersion &version) - { UNUSED(version); return common::OB_SUCCESS; } + { + UNUSED(version); + return common::OB_SUCCESS; + } virtual void inc_pending_lob_count() {} virtual void dec_pending_lob_count() {} virtual int on_memtable_flushed() { return common::OB_SUCCESS; } virtual bool can_be_minor_merged() { return false; } - void set_snapshot_version(const share::SCN snapshot_version) { snapshot_version_ = snapshot_version; } + void set_snapshot_version(const share::SCN snapshot_version) { snapshot_version_ = snapshot_version; } virtual int64_t get_snapshot_version() const override { return snapshot_version_.get_val_for_tx(); } virtual share::SCN get_snapshot_version_scn() const { return snapshot_version_; } - virtual int64_t get_upper_trans_version() const override - { return OB_NOT_SUPPORTED; } - virtual int64_t get_max_merged_trans_version() const override - { return OB_NOT_SUPPORTED; } + virtual int64_t get_upper_trans_version() const override { return OB_NOT_SUPPORTED; } + virtual int64_t get_max_merged_trans_version() const override { return OB_NOT_SUPPORTED; } - virtual int64_t get_serialize_size() const override - { return OB_NOT_SUPPORTED; } + virtual int64_t get_serialize_size() const override { return OB_NOT_SUPPORTED; } - virtual int serialize(char *buf, const int64_t buf_len, int64_t &pos) const override - { return OB_NOT_SUPPORTED; } + virtual int serialize(char *buf, const int64_t buf_len, int64_t &pos) const override { return OB_NOT_SUPPORTED; } - virtual int deserialize(const char *buf, const int64_t data_len, int64_t &pos) override - { return OB_NOT_SUPPORTED; } + virtual int deserialize(const char *buf, const int64_t data_len, int64_t &pos) override { return OB_NOT_SUPPORTED; } - virtual bool can_be_minor_merged() const { return false; } virtual int64_t inc_write_ref() { return OB_INVALID_COUNT; } virtual int64_t dec_write_ref() { return OB_INVALID_COUNT; } virtual int64_t get_write_ref() const { return OB_INVALID_COUNT; } virtual uint32_t get_freeze_flag() { return 0; } - virtual bool get_is_tablet_freeze() { return false; } - virtual int64_t get_max_schema_version() const { return 0; } + virtual bool is_tablet_freeze() { return false; } virtual int64_t get_occupied_size() const { return 0; } - virtual int estimate_phy_size(const ObStoreRowkey* start_key, const ObStoreRowkey* end_key, int64_t& total_bytes, int64_t& total_rows) + virtual int estimate_phy_size(const ObStoreRowkey *start_key, + const ObStoreRowkey *end_key, + int64_t &total_bytes, + int64_t &total_rows) { UNUSEDx(start_key, end_key); total_bytes = 0; total_rows = 0; return OB_SUCCESS; } - virtual int get_split_ranges(const ObStoreRowkey* start_key, const ObStoreRowkey* end_key, const int64_t part_cnt, common::ObIArray &range_array) + virtual int get_split_ranges(const ObStoreRowkey *start_key, + const ObStoreRowkey *end_key, + const int64_t part_cnt, + common::ObIArray &range_array) { UNUSEDx(start_key, end_key); int ret = OB_SUCCESS; @@ -209,10 +162,8 @@ public: } return ret; } - virtual bool is_empty() const override - { - return false; - } + + virtual bool is_empty() const override { return false; } virtual int64_t dec_ref() { @@ -242,26 +193,9 @@ protected: // a round tablet freeze identifier for checkpoint diagnose int64_t trace_id_; }; +} // namespace storage -//////////////////////////////////////////////////////////////////////////////////////////////////// - -class ObMemtableFactory -{ -public: - ObMemtableFactory(); - ~ObMemtableFactory(); -public: - static ObMemtable *alloc(const uint64_t tenant_id); - static void free(ObMemtable *mt); -private: - DISALLOW_COPY_AND_ASSIGN(ObMemtableFactory); -private: - static int64_t alloc_count_; - static int64_t free_count_; -}; - -} -} +} // namespace oceanbase #endif //OCEANBASE_MEMTABLE_OB_MEMTABLE_INTERFACE_ diff --git a/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp b/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp index fa5c68c56..0e9b146ce 100644 --- a/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp +++ b/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp @@ -278,6 +278,7 @@ void ObTenantMetaMemMgr::init_pool_arr() pool_arr_[static_cast(ObITable::TableType::TX_DATA_MEMTABLE)] = &tx_data_memtable_pool_; pool_arr_[static_cast(ObITable::TableType::TX_CTX_MEMTABLE)] = &tx_ctx_memtable_pool_; pool_arr_[static_cast(ObITable::TableType::LOCK_MEMTABLE)] = &lock_memtable_pool_; + pool_arr_[static_cast(ObITable::TableType::DIRECT_LOAD_MEMTABLE)] = &ddl_kv_pool_; } int ObTenantMetaMemMgr::start() @@ -429,7 +430,7 @@ int ObTenantMetaMemMgr::push_table_into_gc_queue(ObITable *table, const ObITable } else { if (ObITable::TableType::DATA_MEMTABLE == table_type) { ObMemtable *memtable = static_cast(table); - memtable::ObMtStat& mt_stat = memtable->get_mt_stat(); + ObMtStat& mt_stat = memtable->get_mt_stat(); if (0 == mt_stat.push_table_into_gc_queue_time_) { mt_stat.push_table_into_gc_queue_time_ = ObTimeUtility::current_time(); if (0 != mt_stat.release_time_ @@ -616,8 +617,7 @@ void ObTenantMetaMemMgr::batch_gc_memtable_() for (common::hash::ObHashSet::iterator set_iter = memtable_set->begin(); set_iter != memtable_set->end(); ++set_iter) { - if (OB_TMP_FAIL(push_table_into_gc_queue((ObITable *)(set_iter->first), - ObITable::TableType::DATA_MEMTABLE))) { + if (OB_TMP_FAIL(push_table_into_gc_queue((ObITable *)(set_iter->first), ObITable::TableType::DATA_MEMTABLE))) { LOG_ERROR("push table into gc queue failed, maybe there will be leak", K(tmp_ret), KPC(memtable_set)); } @@ -1051,7 +1051,31 @@ void ObTenantMetaMemMgr::release_ddl_kv(ObDDLKV *ddl_kv) } } -int ObTenantMetaMemMgr::acquire_memtable(ObTableHandleV2 &handle) +int ObTenantMetaMemMgr::acquire_direct_load_memtable(ObTableHandleV2 &handle) +{ + int ret = OB_SUCCESS; + ObDDLKV *ddl_kv = nullptr; + handle.reset(); + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + STORAGE_LOG(WARN, "ObTenantMetaMemMgr hasn't been initialized", K(ret)); + } else if (OB_FAIL(ddl_kv_pool_.acquire(ddl_kv))) { + STORAGE_LOG(WARN, "fail to acquire ddl kv object", K(ret)); + } else { + handle.set_table(ddl_kv, this, ObITable::TableType::DIRECT_LOAD_MEMTABLE); + ddl_kv = nullptr; + } + + if (OB_FAIL(ret)) { + handle.reset(); + if (OB_NOT_NULL(ddl_kv)) { + release_ddl_kv(ddl_kv); + } + } + return ret; + +} +int ObTenantMetaMemMgr::acquire_data_memtable(ObTableHandleV2 &handle) { int ret = OB_SUCCESS; ObMemtable *memtable = nullptr; @@ -1063,7 +1087,7 @@ int ObTenantMetaMemMgr::acquire_memtable(ObTableHandleV2 &handle) } else if (OB_FAIL(memtable_pool_.acquire(memtable))) { LOG_WARN("fail to acquire memtable object", K(ret)); } else { - handle.set_table(memtable, this, ObITable::TableType::DATA_MEMTABLE); + handle.set_table(memtable, this, ObITable::TableType::DATA_MEMTABLE); memtable = nullptr; } @@ -1086,7 +1110,7 @@ int ObTenantMetaMemMgr::acquire_tx_data_memtable(ObTableHandleV2 &handle) } else if (OB_FAIL(tx_data_memtable_pool_.acquire(tx_data_memtable))) { LOG_WARN("fail to acquire tx data memtable object", K(ret)); } else { - handle.set_table(tx_data_memtable, this, ObITable::TableType::TX_DATA_MEMTABLE); + handle.set_table(tx_data_memtable, this, ObITable::TableType::TX_DATA_MEMTABLE); tx_data_memtable = nullptr; } @@ -1110,7 +1134,7 @@ int ObTenantMetaMemMgr::acquire_tx_ctx_memtable(ObTableHandleV2 &handle) } else if (OB_FAIL(tx_ctx_memtable_pool_.acquire(tx_ctx_memtable))) { LOG_WARN("fail to acquire tx ctx memtable object", K(ret)); } else { - handle.set_table(tx_ctx_memtable, this, ObITable::TableType::TX_CTX_MEMTABLE); + handle.set_table(tx_ctx_memtable, this, ObITable::TableType::TX_CTX_MEMTABLE); tx_ctx_memtable = nullptr; } diff --git a/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h b/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h index b228291f0..2d620f426 100644 --- a/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h +++ b/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h @@ -207,13 +207,12 @@ public: // ddl kv interface int acquire_ddl_kv(ObDDLKVHandle &handle); - void release_ddl_kv(ObDDLKV *ddl_kv); - - // memtable interfaces - int acquire_memtable(ObTableHandleV2 &handle); + int acquire_direct_load_memtable(ObTableHandleV2 &handle); + int acquire_data_memtable(ObTableHandleV2 &handle); int acquire_tx_data_memtable(ObTableHandleV2 &handle); int acquire_tx_ctx_memtable(ObTableHandleV2 &handle); int acquire_lock_memtable(ObTableHandleV2 &handle); + void release_ddl_kv(ObDDLKV *ddl_kv); // tablet create and acquire interfaces // - create_xx_tablet() is used for the first time to construct a tablet object and create a diff --git a/src/storage/ob_direct_load_table_guard.cpp b/src/storage/ob_direct_load_table_guard.cpp new file mode 100644 index 000000000..49ae5d8d0 --- /dev/null +++ b/src/storage/ob_direct_load_table_guard.cpp @@ -0,0 +1,245 @@ +/** + * 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. + */ + +#include "ob_direct_load_table_guard.h" + +#include "storage/ob_protected_memtable_mgr_handle.h" +#include "storage/tablet/ob_tablet.h" +#include "storage/tx_storage/ob_ls_service.h" +#include "storage/ddl/ob_tablet_ddl_kv.h" + +namespace oceanbase { +using namespace share; + +namespace storage { + +ObDirectLoadTableGuard::ObDirectLoadTableGuard(ObTablet &tablet, const share::SCN &scn, const bool for_replay) + : has_acquired_memtable_(false), + is_write_filtered_(false), + for_replay_(for_replay), + ddl_redo_scn_(scn), + table_handle_(), + construct_timestamp_(0) +{ + ls_id_ = tablet.get_tablet_meta().ls_id_; + tablet_id_ = tablet.get_tablet_meta().tablet_id_; + construct_timestamp_ = ObClockGenerator::getClock(); +} + +void ObDirectLoadTableGuard::reset() +{ + const int64_t MAX_HOLD_GUARD_TIME = 1LL * 1000LL * 1000LL; // one second + const int64_t reset_time = ObClockGenerator::getClock(); + bool need_print_debug_log = false; + if (reset_time - construct_timestamp_ > MAX_HOLD_GUARD_TIME) { + need_print_debug_log = true; + STORAGE_LOG_RET(ERROR, + OB_ERR_TOO_MUCH_TIME, + "hold ObDirectLoadTableGuard for too long", + KTIME(reset_time), + KTIME(construct_timestamp_)); + } + + int ret = OB_SUCCESS; + ObITabletMemtable *memtable = nullptr; + if (table_handle_.is_valid()) { + if (OB_FAIL(table_handle_.get_tablet_memtable(memtable))) { + STORAGE_LOG(ERROR, "unexpected fail when get tablet memtable", KPC(this), K(table_handle_)); + } else { + if (need_print_debug_log) { + STORAGE_LOG(INFO, "Print Debug Info", KPC(memtable), KPC(this)); + } + memtable->dec_write_ref(); + } + } +} + +int ObDirectLoadTableGuard::prepare_memtable(ObDDLKV *&res_memtable) +{ + int ret = OB_SUCCESS; + res_memtable = nullptr; + bool tried_freeze = false; + const int64_t INC_MACRO_BLOCK_COUNT_FREEZE_TRIGGER = + 10 * 10L * 1024L * 1024L * 1024L / OB_SERVER_BLOCK_MGR.get_macro_block_size(); + const int64_t INC_MACRO_BLOCK_MEMORY_FREEZE_TRIGGER = 50 * 1024 * 1024; // 50M; + + do { + ObDDLKV *ddl_kv = nullptr; + if (OB_FAIL(acquire_memtable_once_())) { + STORAGE_LOG(WARN, "acquire direct load memtable failed", KR(ret), KPC(this)); + } else if (is_write_filtered_) { + // TODO : @gengli.wzy change this log to debug level + STORAGE_LOG(INFO, "filtered one ddl redo write", KPC(this)); + } else if (FALSE_IT(ddl_kv = static_cast(table_handle_.get_table()))) { + } else if (!tried_freeze && (ddl_kv->get_macro_block_cnt() >= INC_MACRO_BLOCK_COUNT_FREEZE_TRIGGER || + ddl_kv->get_memory_used() >= INC_MACRO_BLOCK_MEMORY_FREEZE_TRIGGER)) { + reset(); // ATTENTION!!! : must reset guard, or freeze cannot finish + tried_freeze = true; // only try independent freeze once + ret = OB_EAGAIN; // to execute loop again + + int tmp_ret = OB_SUCCESS; + if (OB_TMP_FAIL(ddl_kv->freeze())) { + // tmp_ret = OB_ENTRY_EXIST; means this ddl kv has been freezed by other thread + } else { + (void)async_freeze_(); + STORAGE_LOG(INFO, "trigger inc ddlkv freeze", K(ddl_kv->get_macro_block_cnt()), K(ddl_kv->get_memory_used())); + } + } else { + res_memtable = ddl_kv; + has_acquired_memtable_ = true; + } + } while (OB_EAGAIN == ret); + + return ret; +} + +int ObDirectLoadTableGuard::acquire_memtable_once_() +{ + int ret = OB_SUCCESS; + ObLSHandle ls_handle; + + if (has_acquired_memtable_) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "direct load table guard cannot be inited twice", KR(ret), KPC(this)); + } else if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id_, ls_handle, ObLSGetMod::STORAGE_MOD))) { + STORAGE_LOG(WARN, "failed to get log stream", K(ret), KPC(this)); + } else if (OB_UNLIKELY(!ls_handle.is_valid())) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "unexpected error, invalid ls handle", K(ret), K(ls_handle), KPC(this)); + } else { + const int64_t start_time = ObClockGenerator::getClock(); + bool need_create_new_memtable = false; + do { + if (need_create_new_memtable) { + need_create_new_memtable = false; + if (OB_FAIL(do_create_memtable_(ls_handle))) { + STORAGE_LOG(WARN, "create direct load memtable failed", KR(ret), KPC(this)); + } else if (is_write_filtered_) { + break; + } + } + + if (OB_FAIL(ret)) { + const int64_t MAX_RETRY_CREATE_MEMTABLE_TIME = 1LL * 1000LL * 1000LL; + if ((OB_ALLOCATE_MEMORY_FAILED == ret || OB_MINOR_FREEZE_NOT_ALLOW == ret) && + (ObClockGenerator::getClock() - start_time < MAX_RETRY_CREATE_MEMTABLE_TIME)) { + ret = OB_SUCCESS; + need_create_new_memtable = true; + } + } else if (OB_FAIL(try_get_direct_load_memtable_for_write(ls_handle, need_create_new_memtable))) { + STORAGE_LOG(WARN, "get direct load memtable for write failed", KR(ret), K(start_time)); + } + } while (OB_SUCC(ret) && need_create_new_memtable); + } + + return ret; +} + +int ObDirectLoadTableGuard::do_create_memtable_(ObLSHandle &ls_handle) +{ + int ret = OB_SUCCESS; + ObTabletHandle tablet_handle; + SCN clog_checkpoint_scn; + + if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->get_tablet( + tablet_id_, tablet_handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { + STORAGE_LOG(WARN, "fail to get tablet", K(ret), KPC(this)); + } else if (FALSE_IT(clog_checkpoint_scn = tablet_handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_)) { + } else if (ddl_redo_scn_ <= clog_checkpoint_scn) { + is_write_filtered_ = true; + ret = OB_SUCCESS; + } else if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->create_memtable( + tablet_id_, 0 /* schema version */, true /* for_direct_load */, for_replay_, clog_checkpoint_scn))) { + STORAGE_LOG(WARN, "fail to create a boundary memtable", K(ret), KPC(this)); + } + return ret; +} + +int ObDirectLoadTableGuard::try_get_direct_load_memtable_for_write(ObLSHandle &ls_handle, + bool &need_create_new_memtable) +{ + int ret = OB_SUCCESS;; + ObTabletHandle tablet_handle; + ObSEArray local_table_handles; + ObProtectedMemtableMgrHandle *protected_handle = nullptr; + if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->get_tablet( + tablet_id_, tablet_handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { + STORAGE_LOG(WARN, "fail to get tablet", K(ret), KPC(this)); + } else if (OB_FAIL(tablet_handle.get_obj()->get_protected_memtable_mgr_handle(protected_handle))) { + STORAGE_LOG(WARN, "get memtable mgr failed", KR(ret), KPC(this), K(table_handle_)); + } else if (OB_FAIL(protected_handle->get_direct_load_memtables_for_write(local_table_handles))) { + STORAGE_LOG(WARN, "get direct load memtable for write failed", KR(ret), KPC(this)); + } else if (0 == local_table_handles.count()) { + need_create_new_memtable = true; + STORAGE_LOG(INFO, "need create new direct load memtable", K(ddl_redo_scn_)); + } else { + int64_t table_count = local_table_handles.count(); + ObITabletMemtable *head_memtable = static_cast(local_table_handles.at(0).get_table()); + ObITabletMemtable *tail_memtable = + static_cast(local_table_handles.at(table_count - 1).get_table()); + + if (head_memtable->get_start_scn() >= ddl_redo_scn_) { + is_write_filtered_ = true; + } else if (tail_memtable->get_end_scn() < ddl_redo_scn_) { + need_create_new_memtable = true; + STORAGE_LOG(INFO, "need create new direct load memtable", K(ddl_redo_scn_), KPC(tail_memtable)); + } else { + need_create_new_memtable = false; + for (int64_t i = 0; i < local_table_handles.count(); i++) { + ObITabletMemtable *direct_load_memtable = + static_cast(local_table_handles.at(i).get_table()); + const SCN start_scn = direct_load_memtable->get_scn_range().start_scn_; + const SCN end_scn = direct_load_memtable->get_scn_range().end_scn_; + if (start_scn < ddl_redo_scn_ && end_scn >= ddl_redo_scn_) { + table_handle_ = local_table_handles.at(i); + direct_load_memtable->inc_write_ref(); + break; + } + } + } + + (void)clear_write_ref(local_table_handles); + } + return ret; +} + +void ObDirectLoadTableGuard::clear_write_ref(ObIArray &table_handles) +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; i < table_handles.count(); i++) { + ObITabletMemtable *memtable = nullptr; + if (OB_FAIL(table_handles.at(i).get_tablet_memtable(memtable))) { + STORAGE_LOG(ERROR, "unexpected fail when get tablet memtable", KR(ret), KPC(this)); + } else { + memtable->dec_write_ref(); + } + } +} + +void ObDirectLoadTableGuard::async_freeze_() +{ + int ret = OB_SUCCESS; + ObLS *ls = nullptr; + ObLSHandle ls_handle; + if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id_, ls_handle, ObLSGetMod::DDL_MOD))) { + STORAGE_LOG(WARN, "failed to get ls", K(ret), "ls_id", ls_id_); + } else if (OB_ISNULL(ls = ls_handle.get_ls())) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "ls should not be null", K(ret), KPC(this)); + } else { + (void)ls->async_tablet_freeze_for_direct_load(tablet_id_); + } +} + + +} // namespace storage +} // namespace oceanbase \ No newline at end of file diff --git a/src/storage/ob_direct_load_table_guard.h b/src/storage/ob_direct_load_table_guard.h new file mode 100644 index 000000000..7513a3cd8 --- /dev/null +++ b/src/storage/ob_direct_load_table_guard.h @@ -0,0 +1,66 @@ +/** + * 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. + */ + +#pragma once + +#include "storage/ob_i_table.h" + +namespace oceanbase { + +namespace share{ +class SCN; +} + +namespace storage { +class ObTablet; +class ObDDLKV; + +class ObDirectLoadTableGuard { +public: + DISABLE_COPY_ASSIGN(ObDirectLoadTableGuard); + ObDirectLoadTableGuard(ObTablet &tablet, const share::SCN &scn, const bool for_replay); + ~ObDirectLoadTableGuard() { reset(); } + void reset(); + void clear_write_ref(ObIArray &table_handles); + int prepare_memtable(ObDDLKV *&res_memtable); + + bool is_write_filtered() { return is_write_filtered_; } + + TO_STRING_KV(KP(this), + K(has_acquired_memtable_), + K(is_write_filtered_), + K(for_replay_), + K(ls_id_), + K(tablet_id_), + K(ddl_redo_scn_), + K(table_handle_), + K(construct_timestamp_)); + +private: + void async_freeze_(); + int acquire_memtable_once_(); + int do_create_memtable_(ObLSHandle &ls_handle); + int try_get_direct_load_memtable_for_write(ObLSHandle &ls_handle, bool &need_create_new_memtable); + +private: + bool has_acquired_memtable_; + bool is_write_filtered_; + const bool for_replay_; + share::ObLSID ls_id_; + ObTabletID tablet_id_; + const share::SCN &ddl_redo_scn_; + ObTableHandleV2 table_handle_; + int64_t construct_timestamp_; +}; + +} // namespace storage +} // namespace oceanbase diff --git a/src/storage/ob_i_memtable_mgr.cpp b/src/storage/ob_i_memtable_mgr.cpp index 1b35ee65b..f5d7f0d5a 100644 --- a/src/storage/ob_i_memtable_mgr.cpp +++ b/src/storage/ob_i_memtable_mgr.cpp @@ -267,10 +267,10 @@ void ObIMemtableMgr::reset_tables() { if (OB_NOT_NULL(t3m_)) { for (int64_t pos = memtable_head_; pos < memtable_tail_; ++pos) { - memtable::ObIMemtable *memtable = tables_[get_memtable_idx(pos)]; + ObIMemtable *memtable = tables_[get_memtable_idx(pos)]; const int64_t ref_cnt = memtable->dec_ref(); if (0 == ref_cnt) { - t3m_->push_table_into_gc_queue(memtable, table_type_); + t3m_->push_table_into_gc_queue(memtable, memtable->get_table_type()); } } } @@ -278,7 +278,6 @@ void ObIMemtableMgr::reset_tables() memtable_head_ = 0; memtable_tail_ = 0; t3m_ = nullptr; - table_type_ = ObITable::TableType::MAX_TABLE_TYPE; } void ObIMemtableMgr::release_head_memtable() @@ -286,12 +285,12 @@ void ObIMemtableMgr::release_head_memtable() if (OB_ISNULL(t3m_)) { STORAGE_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "t3m is nullptr", KP_(t3m)); } else { - memtable::ObIMemtable *memtable = tables_[get_memtable_idx(memtable_head_)]; + ObIMemtable *memtable = tables_[get_memtable_idx(memtable_head_)]; tables_[get_memtable_idx(memtable_head_)] = nullptr; ++memtable_head_; const int64_t ref_cnt = memtable->dec_ref(); if (0 == ref_cnt) { - t3m_->push_table_into_gc_queue(memtable, table_type_); + t3m_->push_table_into_gc_queue(memtable, memtable->get_table_type()); } } } @@ -302,12 +301,12 @@ void ObIMemtableMgr::release_tail_memtable() if (OB_ISNULL(t3m_)) { STORAGE_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "t3m is nullptr", KP_(t3m)); } else { - memtable::ObIMemtable *memtable = tables_[get_memtable_idx(memtable_tail_ - 1)]; + ObIMemtable *memtable = tables_[get_memtable_idx(memtable_tail_ - 1)]; tables_[get_memtable_idx(memtable_tail_ - 1)] = nullptr; --memtable_tail_; const int64_t ref_cnt = memtable->dec_ref(); if (0 == ref_cnt) { - t3m_->push_table_into_gc_queue(memtable, table_type_); + t3m_->push_table_into_gc_queue(memtable, memtable->get_table_type()); } } } @@ -327,7 +326,6 @@ int64_t ObIMemtableMgr::to_string(char *buf, const int64_t buf_len) const K_(is_inited), K_(tablet_id), KP_(freezer), - K_(table_type), K_(memtable_head), K_(memtable_tail), KP_(t3m)); @@ -354,12 +352,13 @@ int64_t ObIMemtableMgr::to_string(char *buf, const int64_t buf_len) const int ObIMemtableMgr::add_memtable_(ObTableHandleV2 &memtable_handle) { int ret = OB_SUCCESS; - if (OB_UNLIKELY(nullptr == t3m_ || !ObITable::is_memtable(table_type_))) { + if (OB_UNLIKELY(nullptr == t3m_)) { ret = OB_NOT_INIT; - STORAGE_LOG(WARN, "Don't initialize memtable array", K(ret), KP(t3m_), K(table_type_)); + STORAGE_LOG(WARN, "Don't initialize memtable array", K(ret), KP(t3m_)); } else if (OB_UNLIKELY(!memtable_handle.is_valid())) { ret = OB_INVALID_ARGUMENT; STORAGE_LOG(WARN, "invalid argument", K(ret), K(memtable_handle)); + } else if (!ObITable::is_memtable(memtable_handle.get_table()->get_table_type())) { } else { const int64_t idx = get_memtable_idx(memtable_tail_); if (OB_FAIL(memtable_handle.get_memtable(tables_[idx]))) { @@ -374,7 +373,14 @@ int ObIMemtableMgr::add_memtable_(ObTableHandleV2 &memtable_handle) int ObIMemtableMgr::get_ith_memtable(const int64_t pos, ObTableHandleV2 &handle) const { - return handle.set_table(static_cast(tables_[get_memtable_idx(pos)]), t3m_, table_type_); + int ret = OB_SUCCESS; + ObITable *table = static_cast(tables_[get_memtable_idx(pos)]); + if (OB_NOT_NULL(table)) { + ret = handle.set_table(table, t3m_, table->get_table_type()); + } else { + ret = OB_ERR_NULL_VALUE; + } + return ret; } ObMemtableMgrHandle::ObMemtableMgrHandle() diff --git a/src/storage/ob_i_memtable_mgr.h b/src/storage/ob_i_memtable_mgr.h index 96b7fac90..5de698683 100644 --- a/src/storage/ob_i_memtable_mgr.h +++ b/src/storage/ob_i_memtable_mgr.h @@ -17,7 +17,7 @@ #include "lib/lock/ob_qsync_lock.h" #include "ob_tablet_id.h" #include "storage/ob_i_table.h" -#include "storage/memtable/ob_multi_source_data.h" +// #include "storage/memtable/ob_multi_source_data.h" namespace oceanbase { @@ -27,12 +27,12 @@ class ObLogHandler; } namespace memtable { -class ObIMemtable; class ObIMultiSourceDataUnit; } namespace storage { +class ObIMemtable; class ObFreezer; using ObTableHdlArray = common::ObIArray; @@ -191,6 +191,31 @@ private: DISALLOW_COPY_AND_ASSIGN(MemMgrWLockGuard); }; +struct CreateMemtableArg { + int64_t schema_version_; + share::SCN clog_checkpoint_scn_; + share::SCN new_clog_checkpoint_scn_; + bool for_replay_; + bool for_inc_direct_load_; + + CreateMemtableArg(const int64_t schema_version, + const share::SCN clog_checkpoint_scn, + const share::SCN new_clog_checkpoint_scn, + const bool for_replay, + const bool for_inc_direct_load) + : schema_version_(schema_version), + clog_checkpoint_scn_(clog_checkpoint_scn), + new_clog_checkpoint_scn_(new_clog_checkpoint_scn), + for_replay_(for_replay), + for_inc_direct_load_(for_inc_direct_load) {} + + TO_STRING_KV(K(schema_version_), + K(clog_checkpoint_scn_), + K(new_clog_checkpoint_scn_), + K(for_replay_), + K(for_inc_direct_load_)); +}; + class ObIMemtableMgr { public: @@ -199,7 +224,6 @@ public: ref_cnt_(0), tablet_id_(), freezer_(nullptr), - table_type_(ObITable::TableType::MAX_TABLE_TYPE), memtable_head_(0), memtable_tail_(0), t3m_(nullptr), @@ -224,17 +248,8 @@ public: ObFreezer *freezer, ObTenantMetaMemMgr *t3m); - virtual int create_memtable(const share::SCN clog_checkpoint_scn, - const int64_t schema_version, - const share::SCN newest_clog_checkpoint_scn, - const bool for_replay = false) - { - UNUSED(clog_checkpoint_scn); - UNUSED(schema_version); - UNUSED(newest_clog_checkpoint_scn); - UNUSED(for_replay); - return OB_NOT_SUPPORTED; - } + virtual void destroy() = 0; + virtual int create_memtable(const CreateMemtableArg &arg) = 0; virtual int get_active_memtable(ObTableHandleV2 &handle) const; @@ -242,9 +257,7 @@ public: virtual int get_all_memtables(ObTableHdlArray &handle); - virtual void destroy() = 0; - - virtual int get_boundary_memtable(ObTableHandleV2 &handle) { return OB_SUCCESS; } + virtual int get_boundary_memtable(ObTableHandleV2 &handle) { return OB_NOT_SUPPORTED; } virtual int get_memtable_for_replay(share::SCN replay_scn, ObTableHandleV2 &handle) { @@ -291,11 +304,12 @@ public: virtual int reset_storage_recorder() { return common::OB_SUCCESS; } virtual int set_frozen_for_all_memtables() { return common::OB_SUCCESS; } virtual int set_is_tablet_freeze_for_active_memtable(ObTableHandleV2 &handle, const int64_t trace_id = checkpoint::INVALID_TRACE_ID) { return OB_NOT_SUPPORTED; } - virtual int get_last_frozen_memtable(ObTableHandleV2 &handle) const { return OB_NOT_SUPPORTED; } + virtual int get_last_frozen_memtable(ObTableHandleV2 &handle) { return OB_NOT_SUPPORTED; } + virtual int get_direct_load_memtables_for_write(ObTableHdlArray &handles) { return OB_NOT_SUPPORTED; } DECLARE_VIRTUAL_TO_STRING; protected: static int64_t get_memtable_idx(const int64_t pos) { return pos & (MAX_MEMSTORE_CNT - 1); } - virtual int release_head_memtable_(memtable::ObIMemtable *memtable, const bool force = false) = 0; + virtual int release_head_memtable_(ObIMemtable *memtable, const bool force = false) = 0; int add_memtable_(ObTableHandleV2 &memtable); int get_ith_memtable(const int64_t pos, ObTableHandleV2 &handle) const; int64_t get_memtable_count_() const { return memtable_tail_ - memtable_head_; } @@ -315,11 +329,10 @@ protected: common::ObTabletID tablet_id_; // FIXME : whether freeze_handler on base class or not ? ObFreezer *freezer_; - ObITable::TableType table_type_; int64_t memtable_head_; int64_t memtable_tail_; ObTenantMetaMemMgr *t3m_; - memtable::ObIMemtable *tables_[MAX_MEMSTORE_CNT]; + ObIMemtable *tables_[MAX_MEMSTORE_CNT]; mutable MemtableMgrLock lock_; }; diff --git a/src/storage/ob_i_partition_component_factory.h b/src/storage/ob_i_partition_component_factory.h deleted file mode 100644 index b598a263c..000000000 --- a/src/storage/ob_i_partition_component_factory.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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_I_PARTITION_COMPONENT_FACTORY_ -#define OCEANBASE_STORAGE_OB_I_PARTITION_COMPONENT_FACTORY_ - -namespace oceanbase -{ -namespace transaction -{ -class ObTransService; -} -namespace memtable -{ -class ObIMemtable; -} -namespace storage -{ -class ObIPartitionGroup; -class ObMinorFreeze; -class ObIPSFreezeCb; -class ObSSStore; -class ObITable; -class ObReplayStatus; -class ObLS; - - -class ObIPartitionComponentFactory -{ -public: - // for log stream - virtual ObLS *get_ls(const uint64_t tenant_id) = 0; - -public: - virtual ~ObIPartitionComponentFactory() {} - virtual transaction::ObTransService *get_trans_service() = 0; - - virtual void free(ObIPartitionGroup *partition) = 0; - virtual void free(transaction::ObTransService *txs) = 0; - - -}; - -} // namespace storage -} // namespace oceanbase -#endif // OCEANBASE_STORAGE_OB_I_PARTITION_COMPONENT_FACTORY_ diff --git a/src/storage/ob_i_table.cpp b/src/storage/ob_i_table.cpp index b46fd61b5..ee3366306 100644 --- a/src/storage/ob_i_table.cpp +++ b/src/storage/ob_i_table.cpp @@ -21,6 +21,7 @@ #include "storage/tx_table/ob_tx_ctx_memtable.h" #include "storage/tx_table/ob_tx_data_memtable.h" #include "share/scheduler/ob_tenant_dag_scheduler.h" +#include "storage/ddl/ob_tablet_ddl_kv.h" using namespace oceanbase; using namespace oceanbase::blocksstable; @@ -54,7 +55,7 @@ const char* ObITable::table_type_name_[] = "TX_DATA_MEMTABLE", "TX_CTX_MEMTABLE", "LOCK_MEMTABLE", - "", + "DIRECT_LOAD_MEMTABLE", "", "", "", @@ -279,7 +280,7 @@ int ObTableHandleV2::get_sstable(const blocksstable::ObSSTable *&sstable) const return ret; } -int ObTableHandleV2::get_memtable(memtable::ObIMemtable *&memtable) +int ObTableHandleV2::get_memtable(ObIMemtable *&memtable) { int ret = OB_SUCCESS; memtable = nullptr; @@ -291,12 +292,12 @@ int ObTableHandleV2::get_memtable(memtable::ObIMemtable *&memtable) ret = OB_ENTRY_NOT_EXIST; STORAGE_LOG(WARN, "not memtable", K(ret), K(table_->get_key())); } else { - memtable = static_cast(table_); + memtable = static_cast(table_); } return ret; } -int ObTableHandleV2::get_memtable(const memtable::ObIMemtable *&memtable) const +int ObTableHandleV2::get_memtable(const ObIMemtable *&memtable) const { int ret = OB_SUCCESS; memtable = nullptr; @@ -308,7 +309,39 @@ int ObTableHandleV2::get_memtable(const memtable::ObIMemtable *&memtable) const ret = OB_ENTRY_NOT_EXIST; STORAGE_LOG(WARN, "not memtable", K(ret), K(table_->get_key())); } else { - memtable = static_cast(table_); + memtable = static_cast(table_); + } + return ret; +} + +int ObTableHandleV2::get_tablet_memtable(ObITabletMemtable *&memtable) +{ + int ret = OB_SUCCESS; + memtable = NULL; + if (OB_ISNULL(table_)) { + ret = OB_NOT_INIT; + STORAGE_LOG(WARN, "not inited", K(ret)); + } else if (!table_->is_tablet_memtable()) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "not tablet memtable", K(ret), K(table_->get_key())); + } else { + memtable = static_cast(table_); + } + return ret; +} + +int ObTableHandleV2::get_tablet_memtable(const ObITabletMemtable *&memtable) const +{ + int ret = OB_SUCCESS; + memtable = NULL; + if (OB_ISNULL(table_)) { + ret = OB_NOT_INIT; + STORAGE_LOG(WARN, "not inited", K(ret)); + } else if (!table_->is_tablet_memtable()) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "not data memtable", K(ret), K(table_->get_key())); + } else { + memtable = static_cast(table_); } return ret; } @@ -449,6 +482,40 @@ int ObTableHandleV2::get_lock_memtable(const ObLockMemtable *&memtable) const return ret; } +int ObTableHandleV2::get_direct_load_memtable(ObDDLKV *&memtable) +{ + int ret = OB_SUCCESS; + memtable = nullptr; + + if (OB_ISNULL(table_)) { + ret = OB_NOT_INIT; + STORAGE_LOG(WARN, "not inited", K(ret)); + } else if (!table_->is_direct_load_memtable()) { + ret = OB_ENTRY_NOT_EXIST; + STORAGE_LOG(WARN, "not direct load memtable", K(ret), K(table_->get_key())); + } else { + memtable = static_cast(table_); + } + return ret; +} + +int ObTableHandleV2::get_direct_load_memtable(const ObDDLKV *&memtable) const +{ + int ret = OB_SUCCESS; + memtable = nullptr; + + if (OB_ISNULL(table_)) { + ret = OB_NOT_INIT; + STORAGE_LOG(WARN, "not inited", K(ret)); + } else if (!table_->is_direct_load_memtable()) { + ret = OB_ENTRY_NOT_EXIST; + STORAGE_LOG(WARN, "not direct load memtable", K(ret), K(table_->get_key())); + } else { + memtable = static_cast(table_); + } + return ret; +} + ObTableHandleV2::ObTableHandleV2(const ObTableHandleV2 &other) : table_(nullptr), t3m_(nullptr), @@ -741,13 +808,13 @@ int ObTablesHandleArray::get_tables(common::ObIArray &tables) const return ret; } -int ObTablesHandleArray::get_first_memtable(memtable::ObIMemtable *&memtable) const +int ObTablesHandleArray::get_first_memtable(ObIMemtable *&memtable) const { int ret = OB_SUCCESS; memtable = nullptr; for (int64_t i = 0; OB_SUCC(ret) && i < handles_array_.count(); ++i) { if (handles_array_.at(i).get_table()->is_memtable()) { - memtable = static_cast(handles_array_.at(i).table_); + memtable = static_cast(handles_array_.at(i).table_); break; } } diff --git a/src/storage/ob_i_table.h b/src/storage/ob_i_table.h index f10bc4f76..4759be232 100644 --- a/src/storage/ob_i_table.h +++ b/src/storage/ob_i_table.h @@ -34,7 +34,6 @@ namespace oceanbase namespace memtable { class ObMemtable; -class ObIMemtable; } namespace transaction @@ -59,9 +58,12 @@ struct ObScnRange; namespace storage { +class ObIMemtable; +class ObITabletMemtable; class ObTxDataMemtable; class ObTxCtxMemtable; class ObLSMemberMemtable; +class ObDDLKV; class ObTenantMetaMemMgr; struct ObTableIterParam; struct ObTableAccessParam; @@ -83,6 +85,8 @@ public: TX_DATA_MEMTABLE = 1, TX_CTX_MEMTABLE = 2, LOCK_MEMTABLE = 3, + DIRECT_LOAD_MEMTABLE = 4, + MAX_MEMTABLE_TYPE, // < add new memtable here // < sstable start from here @@ -148,8 +152,8 @@ public: OB_INLINE bool is_column_store_sstable() const { return is_co_sstable() || is_cg_sstable(); } OB_INLINE const common::ObTabletID &get_tablet_id() const { return tablet_id_; } - OB_INLINE share::SCN get_start_scn() const { return scn_range_.start_scn_; } - OB_INLINE share::SCN get_end_scn() const { return scn_range_.end_scn_; } + share::SCN get_start_scn() const { return scn_range_.start_scn_; } + share::SCN get_end_scn() const { return scn_range_.end_scn_; } OB_INLINE int64_t get_snapshot_version() const { return version_range_.snapshot_version_; @@ -186,6 +190,7 @@ public: void set_scn_range(share::ObScnRange scn_range) { key_.scn_range_ = scn_range; } void set_table_type(ObITable::TableType table_type) { key_.table_type_ = table_type; } void set_snapshot_version(int64_t version) { key_.version_range_.snapshot_version_ = version; } + ObITable::TableType get_table_type() { return key_.table_type_; } virtual int exist( ObStoreCtx &ctx, @@ -260,12 +265,14 @@ public: virtual bool is_multi_version_table() const { return is_multi_version_table(key_.table_type_); } virtual bool is_memtable() const { return is_memtable(key_.table_type_); } virtual bool is_resident_memtable() const { return is_resident_memtable(key_.table_type_); } + virtual bool is_tablet_memtable() const { return is_tablet_memtable(key_.table_type_); } + virtual bool is_direct_load_memtable() const { return is_direct_load_memtable(key_.table_type_); } virtual bool is_data_memtable() const { return is_data_memtable(key_.table_type_); } virtual bool is_tx_data_memtable() const { return is_tx_data_memtable(key_.table_type_); } virtual bool is_tx_ctx_memtable() const { return is_tx_ctx_memtable(key_.table_type_); } virtual bool is_lock_memtable() const { return is_lock_memtable(key_.table_type_); } - virtual bool is_frozen_memtable() const { return false; } - virtual bool is_active_memtable() const { return false; } + virtual bool is_frozen_memtable() { return false; } + virtual bool is_active_memtable() { return false; } OB_INLINE bool is_table_with_scn_range() const { return is_table_with_scn_range(key_.table_type_); } virtual OB_INLINE int64_t get_timestamp() const { return 0; } virtual bool is_ddl_sstable() const { return is_ddl_sstable(key_.table_type_); } @@ -356,17 +363,23 @@ public: static bool is_memtable(const TableType table_type) { - // TODO: yanyuan.cxf maybe we need > and < - return (ObITable::TableType::TX_DATA_MEMTABLE == table_type - || ObITable::TableType::TX_CTX_MEMTABLE == table_type - || ObITable::TableType::DATA_MEMTABLE == table_type - || ObITable::TableType::LOCK_MEMTABLE == table_type); + return ObITable::TableType::DATA_MEMTABLE <= table_type && + ObITable::TableType::MAX_MEMTABLE_TYPE > table_type; } static bool is_resident_memtable(const TableType table_type) { return (ObITable::TableType::TX_CTX_MEMTABLE == table_type || ObITable::TableType::LOCK_MEMTABLE == table_type); } + static bool is_tablet_memtable(const TableType table_type) + { + return (ObITable::TableType::DATA_MEMTABLE == table_type || + ObITable::TableType::DIRECT_LOAD_MEMTABLE == table_type); + } + static bool is_direct_load_memtable(const TableType table_type) + { + return ObITable::TableType::DIRECT_LOAD_MEMTABLE == table_type; + } static bool is_data_memtable(const TableType table_type) { return ObITable::TableType::DATA_MEMTABLE == table_type; @@ -466,12 +479,15 @@ public: OB_INLINE ObITable *get_table() { return table_; } OB_INLINE const ObITable *get_table() const { return table_; } + OB_INLINE ObTenantMetaMemMgr *get_t3m() { return t3m_; } OB_INLINE common::ObIAllocator *get_allocator() { return allocator_; } int get_sstable(blocksstable::ObSSTable *&sstable); int get_sstable(const blocksstable::ObSSTable *&sstable) const; - int get_memtable(memtable::ObIMemtable *&memtable); - int get_memtable(const memtable::ObIMemtable *&memtable) const; + int get_memtable(ObIMemtable *&memtable); + int get_memtable(const ObIMemtable *&memtable) const; + int get_tablet_memtable(ObITabletMemtable *&memtable); + int get_tablet_memtable(const ObITabletMemtable *&memtable) const; int get_data_memtable(memtable::ObMemtable *&memtable); int get_data_memtable(const memtable::ObMemtable *&memtable) const; int get_tx_data_memtable(ObTxDataMemtable *&memtable); @@ -480,6 +496,8 @@ public: int get_tx_ctx_memtable(const ObTxCtxMemtable *&memtable) const; int get_lock_memtable(transaction::tablelock::ObLockMemtable *&memtable); int get_lock_memtable(const transaction::tablelock::ObLockMemtable *&memtable) const; + int get_direct_load_memtable(ObDDLKV *&memtable); + int get_direct_load_memtable(const ObDDLKV *&memtable) const; ObTableHandleV2(const ObTableHandleV2 &other); ObTableHandleV2 &operator= (const ObTableHandleV2 &other); @@ -526,7 +544,7 @@ public: int add_table(const ObTableHandleV2 &handle); int assign(const ObTablesHandleArray &other); int get_tables(common::ObIArray &tables) const; - int get_first_memtable(memtable::ObIMemtable *&memtable) const; + int get_first_memtable(ObIMemtable *&memtable) const; int get_all_minor_sstables(common::ObIArray &tables) const; int check_continues(const share::ObScnRange *scn_range) const; DECLARE_TO_STRING; @@ -542,7 +560,7 @@ private: OB_INLINE bool ObITable::is_table_type_valid(const TableType &type) { - return (type >= ObITable::DATA_MEMTABLE && type <= ObITable::LOCK_MEMTABLE) + return (type >= ObITable::DATA_MEMTABLE && type < ObITable::MAX_MEMTABLE_TYPE) || (type >= ObITable::MAJOR_SSTABLE && type < ObITable::MAX_TABLE_TYPE); } diff --git a/src/storage/ob_i_tablet_memtable.cpp b/src/storage/ob_i_tablet_memtable.cpp new file mode 100644 index 000000000..59b3aacca --- /dev/null +++ b/src/storage/ob_i_tablet_memtable.cpp @@ -0,0 +1,341 @@ +/** + * 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. + */ + +#define USING_LOG_PREFIX STORAGE + +#include "storage/ob_i_tablet_memtable.h" + +#include "storage/compaction/ob_compaction_diagnose.h" +#include "storage/ls/ob_freezer.h" +#include "storage/tablet/ob_tablet_memtable_mgr.h" + +namespace oceanbase { + +namespace storage { + + +int ObITabletMemtable::inc_unsubmitted_cnt() +{ + int ret = OB_SUCCESS; + const share::ObLSID ls_id = get_ls_id(); + int64_t unsubmitted_cnt = inc_unsubmitted_cnt_(); + TRANS_LOG(DEBUG, "inc_unsubmitted_cnt", K(ls_id), KPC(this), K(lbt())); + + if (ATOMIC_LOAD(&unset_active_memtable_logging_blocked_)) { + TRANS_LOG(WARN, "cannot inc unsubmitted_cnt", K(unsubmitted_cnt), K(ls_id), KPC(this)); + } + + return ret; +} + +int ObITabletMemtable::dec_unsubmitted_cnt() +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + + // fix issue 47021079 + // To avoid the following case where logging_block cannot be unset: + // ----------------------------------------------------- + // dec_write_ref() dec_unsubmitted_cnt() + // ----------------------------------------------------- + // is_frozen is_frozen + // get write_ref_cnt 1 + // dec write_ref to 0 + // get unsubmitted_cnt 1 + // dec unsubmitted_cnt to 0 + // ----------------------------------------------------- + int64_t old_unsubmitted_cnt = dec_unsubmitted_cnt_(); + + // must maintain the order of getting variables to avoid concurrency problems + // is_frozen_memtable() can affect wirte_ref_cnt + // write_ref_cnt can affect unsubmitted_cnt + bool is_frozen = is_frozen_memtable(); + int64_t write_ref_cnt = get_write_ref(); + int64_t new_unsubmitted_cnt = get_unsubmitted_cnt(); + TRANS_LOG(DEBUG, "dec_unsubmitted_cnt", K(ls_id), KPC(this), K(lbt())); + + if (OB_UNLIKELY(old_unsubmitted_cnt < 0)) { + TRANS_LOG(ERROR, "unsubmitted_cnt not match", K(ret), K(ls_id), KPC(this)); + } else if (is_frozen && + 0 == write_ref_cnt && + 0 == new_unsubmitted_cnt) { + (void)unset_logging_blocked_for_active_memtable_(); + TRANS_LOG(INFO, "memtable log submitted", K(ret), K(ls_id), KPC(this)); + } + + return ret; +} + + +void ObITabletMemtable::unset_logging_blocked_for_active_memtable_() +{ + int ret = OB_SUCCESS; + ObTabletMemtableMgr *memtable_mgr = get_memtable_mgr(); + + if (OB_NOT_NULL(memtable_mgr)) { + do { + if (OB_FAIL(memtable_mgr->unset_logging_blocked_for_active_memtable(this))) { + TRANS_LOG(ERROR, "fail to unset logging blocked for active memtable", K(ret), K(ls_id_), KPC(this)); + ob_usleep(100); + } + } while (OB_FAIL(ret)); + } +} + +void ObITabletMemtable::resolve_left_boundary_for_active_memtable_() +{ + int ret = OB_SUCCESS; + storage::ObTabletMemtableMgr *memtable_mgr = get_memtable_mgr(); + const SCN new_start_scn = MAX(get_end_scn(), get_migration_clog_checkpoint_scn()); + + if (OB_NOT_NULL(memtable_mgr)) { + do { + if (OB_FAIL(memtable_mgr->resolve_left_boundary_for_active_memtable(this, new_start_scn))) { + TRANS_LOG(ERROR, "fail to set start log ts for active memtable", K(ret), K(ls_id_), KPC(this)); + ob_usleep(100); + } + } while (OB_FAIL(ret)); + } +} + +int ObITabletMemtable::get_ls_current_right_boundary_(SCN ¤t_right_boundary) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(freezer_)) { + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(WARN, "freezer should not be null", K(ret)); + } else if (OB_FAIL(freezer_->get_max_consequent_callbacked_scn(current_right_boundary))) { + TRANS_LOG(WARN, "fail to get min_unreplay_scn", K(ret), K(current_right_boundary)); + } + + return ret; +} + +int ObITabletMemtable::set_memtable_mgr_(storage::ObTabletMemtableMgr *mgr) +{ + ObTabletMemtableMgrPool *pool = MTL(ObTabletMemtableMgrPool*); + return memtable_mgr_handle_.set_memtable_mgr(mgr, pool); +} + +ObTabletMemtableMgr *ObITabletMemtable::get_memtable_mgr() +{ + return static_cast(memtable_mgr_handle_.get_memtable_mgr()); +} + +int ObITabletMemtable::set_freezer(ObFreezer *handler) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(handler)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "freeze handler is null", K(ret)); + } else { + freezer_ = handler; + } + return ret; +} + +int ObITabletMemtable::set_migration_clog_checkpoint_scn(const SCN &clog_checkpoint_scn) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(!is_inited())) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "not inited", K(ret)); + } else if (clog_checkpoint_scn <= ObScnRange::MIN_SCN) { + ret = OB_SCN_OUT_OF_BOUND; + TRANS_LOG(WARN, "invalid clog_checkpoint_ts", K(ret)); + } else { + (void)migration_clog_checkpoint_scn_.atomic_store(clog_checkpoint_scn); + } + + return ret; +} + +int ObITabletMemtable::set_rec_scn(const SCN rec_scn) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + + if (OB_UNLIKELY(!is_inited())) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "not inited", K(ret)); + } else if (rec_scn.is_max()) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid args", K(ret), K(rec_scn)); + } else if (rec_scn <= get_start_scn()) { + ret = OB_SCN_OUT_OF_BOUND; + TRANS_LOG(ERROR, "cannot set freeze log ts smaller to start log ts", K(ret), K(rec_scn), K(ls_id), KPC(this)); + } else { + SCN old_rec_scn; + SCN new_rec_scn = get_rec_scn(); + while ((old_rec_scn = new_rec_scn) > rec_scn) { + if ((new_rec_scn = rec_scn_.atomic_vcas(old_rec_scn, rec_scn)) + == old_rec_scn) { + new_rec_scn = rec_scn; + } + } + } + return ret; +} + +int ObITabletMemtable::set_start_scn(const share::SCN start_scn) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + + if (OB_UNLIKELY(!is_inited())) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "not inited", K(ret)); + } else if (ObScnRange::MAX_SCN == start_scn) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid args", K(ret), K(start_scn)); + } else if (start_scn >= get_end_scn() + || (max_end_scn_ != SCN::min_scn() && start_scn >= max_end_scn_) + || start_scn >= rec_scn_) { + ret = OB_SCN_OUT_OF_BOUND; + TRANS_LOG(ERROR, "cannot set start ts now", K(ret), K(start_scn), K(ls_id), KPC(this)); + } else { + key_.scn_range_.start_scn_ = start_scn; + } + + return ret; +} + +int ObITabletMemtable::set_end_scn(const SCN freeze_scn) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + + if (OB_UNLIKELY(!is_inited())) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "not inited", K(ret)); + } else if (ObScnRange::MAX_SCN == freeze_scn) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid args", K(ret), K(freeze_scn)); + } else if (freeze_scn < get_start_scn()) { + ret = OB_SCN_OUT_OF_BOUND; + TRANS_LOG(ERROR, "cannot set freeze log ts smaller to start log ts", + K(ret), K(freeze_scn), K(ls_id), KPC(this)); + } else { + SCN old_end_scn; + SCN new_end_scn = get_end_scn(); + while ((old_end_scn = new_end_scn) < freeze_scn + || new_end_scn == ObScnRange::MAX_SCN) { + if ((new_end_scn = + key_.scn_range_.end_scn_.atomic_vcas(old_end_scn, freeze_scn)) + == old_end_scn) { + new_end_scn = freeze_scn; + } + } + freeze_scn_ = freeze_scn; + } + return ret; +} + +int ObITabletMemtable::set_max_end_scn(const SCN scn, bool allow_backoff) +{ + int ret = OB_SUCCESS; + share::ObLSID ls_id = get_ls_id(); + + if (OB_UNLIKELY(!is_inited())) { + ret = OB_NOT_INIT; + TRANS_LOG(WARN, "not inited", K(ret)); + } else if (ObScnRange::MAX_SCN == scn) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid args", K(ret), K(scn)); + } else if (scn <= get_start_scn() || scn > get_end_scn()) { + ret = OB_SCN_OUT_OF_BOUND; + TRANS_LOG(WARN, "cannot set max end log ts smaller to start log ts", + K(ret), K(scn), K(ls_id), KPC(this)); + } else if (allow_backoff) { + TRANS_LOG(INFO, "set max_end_scn force", K(scn), K(max_end_scn_.atomic_get()), K(key_), KPC(this)); + if (scn != max_end_scn_.atomic_get()) { + max_end_scn_.dec_update(scn); + } + } else { + SCN old_max_end_scn; + SCN new_max_end_scn = get_max_end_scn(); + while ((old_max_end_scn = new_max_end_scn) < scn) { + if ((new_max_end_scn = + max_end_scn_.atomic_vcas(old_max_end_scn, scn)) + == old_max_end_scn) { + new_max_end_scn = scn; + } + } + } + return ret; +} + + +// NOTE: +// CASE 1 : For Data Memtable +// call this function must ensure all TxNodes on memtable has been +// logged and the log's either synced successfully or synced failed. +// because otherwise the max_end_scn is not correct and which may be larger than +// the max value of valid TxNode(s)'s log_scn, which cause an incorrect right +// boundary value, and an incorrect left boundary value of next active memtable +// +// when TxNode's log synced failed, Txn's function will process to adjust the +// max_end_scn of this memtable, finally, the memtable will has a correct right +// boundary value, keep the safety: +// future data's log_scn > max_end_scn of this memtable +// +// CASE 2 : For Direct Load Memtable +// call this function after write_ref_cnt == 0 +// +int ObITabletMemtable::resolve_right_boundary() +{ + int ret = OB_SUCCESS; + SCN max_end_scn = get_max_end_scn(); + SCN end_scn = max_end_scn; + SCN father_start_scn = ObITable::get_start_scn(); + SCN ddl_start_scn = get_start_scn(); + + if (max_end_scn.is_min()) { + end_scn = father_start_scn; + (void)freezer_->inc_empty_memtable_cnt(); + } + + if (OB_FAIL(set_end_scn(end_scn))) { + TRANS_LOG(ERROR, "fail to set end_scn", K(ret)); + } + + return ret; +} + +void ObITabletMemtable::set_max_schema_version(const int64_t schema_version) +{ + if (INT64_MAX == schema_version) { + TRANS_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "invalid schema version", K(schema_version), KPC(this)); + } else { + inc_update(&max_schema_version_, schema_version); + } +} + +int64_t ObITabletMemtable::get_max_schema_version() const +{ + return ATOMIC_LOAD(&max_schema_version_); +} + +int64_t ObITabletMemtable::inc_unsubmitted_cnt_() { return ATOMIC_AAF(&unsubmitted_cnt_, 1); } +int64_t ObITabletMemtable::dec_unsubmitted_cnt_() { return ATOMIC_SAF(&unsubmitted_cnt_, 1); } +int64_t ObITabletMemtable::inc_write_ref_() { return ATOMIC_AAF(&write_ref_cnt_, 1); } +int64_t ObITabletMemtable::dec_write_ref_() { return ATOMIC_SAF(&write_ref_cnt_, 1); } + +bool ObITabletMemtable::can_be_minor_merged() +{ + return is_in_prepare_list_of_data_checkpoint(); +} + +} // namespace storage + +} // namespace oceanbase \ No newline at end of file diff --git a/src/storage/ob_i_tablet_memtable.h b/src/storage/ob_i_tablet_memtable.h new file mode 100644 index 000000000..3c1b15cdf --- /dev/null +++ b/src/storage/ob_i_tablet_memtable.h @@ -0,0 +1,380 @@ +/** + * 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_I_TABLET_MEMTABLE_H_ +#define OCEANBASE_STORAGE_OB_I_TABLET_MEMTABLE_H_ + +#include "lib/utility/ob_print_utils.h" + +#include "storage/ob_i_memtable_mgr.h" +#include "storage/memtable/ob_memtable_interface.h" +#include "storage/checkpoint/ob_freeze_checkpoint.h" + +namespace oceanbase { +namespace storage { + +class ObTabletMemtableMgr; + +/* + * Attention! When tx is rollback, insert/update/delete row count and size will not reduced accordingly + */ +struct ObMtStat { + ObMtStat() { reset(); } + ~ObMtStat() = default; + void reset() { memset(this, 0, sizeof(*this)); } + TO_STRING_KV(K_(insert_row_count), + K_(update_row_count), + K_(delete_row_count), + K_(empty_mvcc_row_count), + K_(frozen_time), + K_(ready_for_flush_time), + K_(create_flush_dag_time), + K_(release_time), + K_(last_print_time), + K_(row_size)); + int64_t insert_row_count_; + int64_t update_row_count_; + int64_t delete_row_count_; + int64_t empty_mvcc_row_count_; + int64_t frozen_time_; + int64_t ready_for_flush_time_; + int64_t create_flush_dag_time_; + int64_t release_time_; + int64_t push_table_into_gc_queue_time_; + int64_t last_print_time_; + int64_t row_size_; +}; + +class ObMemtableState { +public: + static const int64_t INVALID = -1; + static const int64_t ACTIVE = 0; + static const int64_t MAJOR_FROZEN = 1; + static const int64_t MINOR_FROZEN = 2; + static const int64_t MAJOR_MERGING = 3; + static const int64_t MINOR_MERGING = 4; + +public: + bool is_valid(const int64_t state) { return state >= ACTIVE && state <= MINOR_MERGING; } +}; + +enum TabletMemtableFreezeState : int64_t { + INVALID = 0, + ACTIVE = 1, + FREEZING = 2, + READY_FOR_FLUSH = 3, + FLUSHED = 4, + RELEASED = 5, + MAX_FREEZE_STATE +}; + +const static char *TABLET_MEMTABLE_FREEZE_STATE_TO_STR(const int64_t state) +{ + if (state >= TabletMemtableFreezeState::MAX_FREEZE_STATE) { + return ""; + } + STATIC_ASSERT(TabletMemtableFreezeState::INVALID == 0, "Invalid State Enum"); + STATIC_ASSERT(TabletMemtableFreezeState::ACTIVE == 1, "Invalid State Enum"); + STATIC_ASSERT(TabletMemtableFreezeState::FREEZING == 2, "Invalid State Enum"); + STATIC_ASSERT(TabletMemtableFreezeState::READY_FOR_FLUSH == 3, "Invalid State Enum"); + STATIC_ASSERT(TabletMemtableFreezeState::FLUSHED == 4, "Invalid State Enum"); + STATIC_ASSERT(TabletMemtableFreezeState::RELEASED == 5, "Invalid State Enum"); + const static char TABLET_MEMTABLE_FREEZE_STATE_TO_STR[6][20] = {"INVALID", "ACTIVE", "FREEZING", "READY_FOR_FLUSH", "FLUSHED", "RELEASED"}; + return TABLET_MEMTABLE_FREEZE_STATE_TO_STR[state]; +} + +class ObITabletMemtable : public ObIMemtable, public checkpoint::ObFreezeCheckpoint { +public: +#define DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(function, update_function) \ + struct function { \ + public: \ + function() {} \ + function(const function &) = delete; \ + function &operator=(const function &) = delete; \ + void operator()(const checkpoint::ObCheckpointDiagnoseParam ¶m) const \ + { \ + checkpoint::ObCheckpointDiagnoseMgr *cdm = MTL(checkpoint::ObCheckpointDiagnoseMgr *); \ + if (OB_NOT_NULL(cdm)) { \ + cdm->update_function(param); \ + } \ + } \ + }; + DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(UpdateStartGCTimeForMemtable, update_start_gc_time_for_memtable) + DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(AddCheckpointDiagnoseInfoForMemtable, + add_diagnose_info) + + template + void report_memtable_diagnose_info(const OP &op) + { + int ret = OB_SUCCESS; + // logstream freeze + if (!is_tablet_freeze()) { + share::ObLSID ls_id; + if (OB_FAIL(get_ls_id(ls_id))) { + TRANS_LOG(WARN, "failed to get ls id", KPC(this)); + } else { + checkpoint::ObCheckpointDiagnoseParam param(ls_id.id(), get_freeze_clock(), get_tablet_id(), (void *)this); + op(param); + } + } + // batch tablet freeze + else if (checkpoint::INVALID_TRACE_ID != get_trace_id()) { + checkpoint::ObCheckpointDiagnoseParam param(trace_id_, get_tablet_id(), (void *)this); + op(param); + } + } + +public: + ObITabletMemtable() + : allow_freeze_(true), + is_tablet_freeze_(false), + freeze_clock_(0), + init_timestamp_(0), + max_schema_version_(0), + freezer_(nullptr), + mt_stat_(), + freeze_scn_(), + max_end_scn_(), + rec_scn_(), + is_flushed_(false), + logging_blocked_(false), + resolved_active_memtable_left_boundary_(true), + unset_active_memtable_logging_blocked_(false), + read_barrier_(false), + unsubmitted_cnt_(0), + logging_blocked_start_time_(0), + write_ref_cnt_(0), + migration_clog_checkpoint_scn_(), + freeze_state_(TabletMemtableFreezeState::INVALID), + memtable_mgr_handle_() + { + max_end_scn_.set_min(); + rec_scn_.set_max(); + freeze_scn_.set_max(); + migration_clog_checkpoint_scn_.set_min(); + } + + void reset() + { + ObIMemtable::reset(); + ObFreezeCheckpoint::reset(); + allow_freeze_ = true; + is_flushed_ = false; + is_tablet_freeze_ = false; + logging_blocked_ = false; + resolved_active_memtable_left_boundary_ = true; + unset_active_memtable_logging_blocked_ = false; + read_barrier_ = false; + freeze_clock_ = 0; + freeze_state_ = TabletMemtableFreezeState::INVALID; + unsubmitted_cnt_ = 0; + logging_blocked_start_time_ = 0; + init_timestamp_ = 0; + max_schema_version_ = 0; + max_end_scn_.set_min(); + rec_scn_.set_max(); + freeze_scn_.set_max(); + migration_clog_checkpoint_scn_.set_min(); + freezer_ = nullptr; + memtable_mgr_handle_.reset(); + mt_stat_.reset(); + } + +public: + bool is_can_flush() + { + return TabletMemtableFreezeState::READY_FOR_FLUSH == freeze_state_ && share::SCN::max_scn() != get_end_scn(); + } + virtual bool can_be_minor_merged() override; + int inc_unsubmitted_cnt(); + int dec_unsubmitted_cnt(); + int set_freezer(ObFreezer *handler); + int set_rec_scn(const share::SCN rec_scn); + int set_migration_clog_checkpoint_scn(const share::SCN &clog_checkpoint_scn); + int resolve_left_boundary(share::SCN end_scn) { return set_start_scn(end_scn); } + int resolve_right_boundary(); + int set_start_scn(const share::SCN start_scn); + int set_end_scn(const share::SCN end_scn); + int set_max_end_scn(const share::SCN scn, bool allow_backoff = false); + + +public: // derived from ObITable + virtual bool is_active_memtable() override { return !is_frozen_memtable(); } + virtual int64_t get_timestamp() const override { return init_timestamp_; } + virtual int64_t dec_ref() + { + int64_t ref_cnt = ObITable::dec_ref(); + if (0 == ref_cnt) { + report_memtable_diagnose_info(UpdateStartGCTimeForMemtable()); + } + return ref_cnt; + } + +public: // derived from ObIMemtable + virtual int64_t inc_write_ref() override { return inc_write_ref_(); } + virtual int64_t dec_write_ref() override { return dec_write_ref_(); } + virtual int64_t get_write_ref() const override { return ATOMIC_LOAD(&write_ref_cnt_); } + +public: // derived from ObFreezeCheckpoint + ObTabletID get_tablet_id() const { return key_.tablet_id_; } + virtual bool is_active_checkpoint() override { return is_active_memtable(); } + virtual bool is_frozen_checkpoint() override { return is_frozen_memtable(); } + +public: + // *************** pure virtual functions ***************** + virtual bool is_inited() const = 0; + virtual int init(const ObITable::TableKey &table_key, + ObLSHandle &ls_handle, + ObFreezer *freezer, + ObTabletMemtableMgr *memtable_mgr, + const int64_t schema_version, + const uint32_t freeze_clock) = 0; + virtual void print_ready_for_flush() = 0; + virtual void set_allow_freeze(const bool allow_freeze) = 0; + virtual int set_frozen() = 0; + // *************** pure virtual functions ***************** + +public: + // *************** setter ***************** + void set_max_schema_version(const int64_t schema_version); + void set_is_tablet_freeze() { is_tablet_freeze_ = true; } + void set_freeze_clock(const uint32_t freeze_clock) { ATOMIC_STORE(&freeze_clock_, freeze_clock); } + void set_is_flushed() { is_flushed_ = true; } + void set_read_barrier() { read_barrier_ = true; } + void reset_mt_stat() { mt_stat_.reset(); } + void unset_active_memtable_logging_blocked() { ATOMIC_STORE(&unset_active_memtable_logging_blocked_, true); } + void set_frozen_time(const int64_t timestamp) const { mt_stat_.frozen_time_ = timestamp; } + void set_last_print_time(const int64_t timestamp) const { mt_stat_.last_print_time_ = timestamp; } + void set_ready_for_flush_time(const int64_t timestamp) { mt_stat_.ready_for_flush_time_= timestamp; } + void set_create_flush_dag_time(const int64_t timestamp) { mt_stat_.create_flush_dag_time_ = timestamp; } + void set_release_time(const int64_t timestamp) { mt_stat_.release_time_ = timestamp; } + void set_push_table_into_gc_queue_time(const int64_t timestamp) { mt_stat_.push_table_into_gc_queue_time_ = timestamp; } + void set_resolved_active_memtable_left_boundary(bool flag) + { + ATOMIC_STORE(&resolved_active_memtable_left_boundary_, flag); + } + void set_freeze_state(const TabletMemtableFreezeState state) + { + if (state >= TabletMemtableFreezeState::ACTIVE && state <= TabletMemtableFreezeState::RELEASED) { + freeze_state_ = state; + } + } + void set_logging_blocked() + { + logging_blocked_start_time_ = ObClockGenerator::getClock(); + ATOMIC_STORE(&logging_blocked_, true); + } + void unset_logging_blocked() + { + if (get_logging_blocked()) { + ATOMIC_STORE(&logging_blocked_, false); + int64_t cost_time = ObClockGenerator::getClock() - logging_blocked_start_time_; + TRANS_LOG(INFO, "the cost time of logging blocked: ", K(cost_time), K(this), K(key_.tablet_id_)); + } + } + // *************** setter ***************** + +public: + // *************** getter ***************** + bool get_is_flushed() { return is_flushed_; } + bool is_tablet_freeze() { return is_tablet_freeze_; } + bool &get_read_barrier() { return read_barrier_; } + bool allow_freeze() const { return ATOMIC_LOAD(&allow_freeze_); } + bool get_logging_blocked() { return ATOMIC_LOAD(&logging_blocked_); } + bool get_resolved_active_memtable_left_boundary() { return ATOMIC_LOAD(&resolved_active_memtable_left_boundary_); } + uint32_t get_freeze_clock() const { return ATOMIC_LOAD(&freeze_clock_); } + int64_t get_unsubmitted_cnt() const { return ATOMIC_LOAD(&unsubmitted_cnt_); } + int64_t get_max_schema_version() const ; + int64_t get_frozen_time() const { return mt_stat_.frozen_time_; } + int64_t get_last_print_time() const { return mt_stat_.last_print_time_; } + TabletMemtableFreezeState get_freeze_state() const { return freeze_state_; } + ObFreezer *get_freezer() { return freezer_; } + ObMtStat &get_mt_stat() { return mt_stat_; } + const ObMtStat &get_mt_stat() const { return mt_stat_; } + share::SCN get_max_end_scn() const { return max_end_scn_.atomic_get(); } + share::SCN get_rec_scn() { return rec_scn_.atomic_get(); } + share::SCN get_migration_clog_checkpoint_scn() { return migration_clog_checkpoint_scn_.atomic_get(); } + ObTabletMemtableMgr *get_memtable_mgr(); + // *************** getter ***************** + + INHERIT_TO_STRING_KV("ObITable", + ObITable, + K(ls_id_), + K(allow_freeze_), + K(is_flushed_), + K(is_tablet_freeze_), + K(logging_blocked_), + K(resolved_active_memtable_left_boundary_), + K(unset_active_memtable_logging_blocked_), + K(read_barrier_), + K(freeze_clock_), + K(freeze_state_), + K(unsubmitted_cnt_), + K(init_timestamp_), + K(max_schema_version_), + K(write_ref_cnt_), + K(max_end_scn_), + K(rec_scn_), + K(freeze_scn_), + K(migration_clog_checkpoint_scn_), + KP(freezer_), + K(memtable_mgr_handle_), + K(mt_stat_.frozen_time_), + K(mt_stat_.ready_for_flush_time_), + K(mt_stat_.create_flush_dag_time_), + K(mt_stat_.release_time_), + K(mt_stat_.push_table_into_gc_queue_time_), + K(mt_stat_.last_print_time_)) + +protected: + void resolve_left_boundary_for_active_memtable_(); + int get_ls_current_right_boundary_(share::SCN ¤t_right_boundary); + int set_memtable_mgr_(ObTabletMemtableMgr *mgr); + int64_t inc_unsubmitted_cnt_(); + int64_t dec_unsubmitted_cnt_(); + int64_t inc_write_ref_(); + int64_t dec_write_ref_(); + void unset_logging_blocked_for_active_memtable_(); + +protected: + bool allow_freeze_; + bool is_tablet_freeze_; + mutable uint32_t freeze_clock_; + int64_t init_timestamp_; + int64_t max_schema_version_; // to record the max schema version of memtable & schema_change_clog + ObFreezer *freezer_; + mutable ObMtStat mt_stat_; + share::SCN freeze_scn_; + share::SCN max_end_scn_; + share::SCN rec_scn_; + +private: + bool is_flushed_; + bool logging_blocked_; // flag whether the memtable can submit log, cannot submit if true + bool resolved_active_memtable_left_boundary_; + bool unset_active_memtable_logging_blocked_; + bool read_barrier_ CACHE_ALIGNED; + int64_t unsubmitted_cnt_; + int64_t logging_blocked_start_time_; // record the start time of logging blocked + int64_t write_ref_cnt_ CACHE_ALIGNED; + share::SCN migration_clog_checkpoint_scn_; + TabletMemtableFreezeState freeze_state_; + ObMemtableMgrHandle memtable_mgr_handle_; +}; + + + + +} // namespace storage +} // namespace oceanbase + +#endif \ No newline at end of file diff --git a/src/storage/ob_partition_component_factory.cpp b/src/storage/ob_partition_component_factory.cpp deleted file mode 100644 index c4e151f26..000000000 --- a/src/storage/ob_partition_component_factory.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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. - */ - -#include "storage/ob_partition_component_factory.h" -#include "storage/memtable/ob_memtable.h" -#include "share/allocator/ob_tenant_mutil_allocator.h" -#include "lib/allocator/ob_pcounter.h" -#include "ls/ob_ls.h" -#include "storage/tx/ob_trans_service.h" - -namespace oceanbase -{ -using namespace oceanbase::common; -using namespace oceanbase::transaction; -using namespace oceanbase::memtable; -namespace storage -{ - -static const char *MEMORY_LABEL_COMPONENT_FACTORY = "PartitionComponentFactory"; - -ObMemtable *ObPartitionComponentFactory::get_memtable(const uint64_t tenant_id) -{ - ObMemtable* obj = ObMemtableFactory::alloc(tenant_id); - if (NULL != obj) { - PC_ADD(MT, 1); - } - return obj; -} - -ObTransService *ObPartitionComponentFactory::get_trans_service() -{ - return OB_NEW(ObTransService, MEMORY_LABEL_COMPONENT_FACTORY); -} - - -ObLS *ObPartitionComponentFactory::get_ls(const uint64_t tenant_id) -{ - ObMemAttr memattr(tenant_id, ObModIds::OB_PARTITION, ObCtxIds::STORAGE_LONG_TERM_META_CTX_ID); - ObLS *obj = OB_NEW_ALIGN32(ObLS, memattr); - if (!OB_ISNULL(obj)) { - PC_ADD(PT, 1); - } - return obj; -} - -void ObPartitionComponentFactory::free(ObIPartitionGroup *partition) -{ - UNUSEDx(partition); -} - -void ObPartitionComponentFactory::free(memtable::ObMemtable *memtable) -{ - if (NULL != memtable) { - PC_ADD(MT, -1); - ObMemtableFactory::free(memtable); - memtable = NULL; - } -} - -void ObPartitionComponentFactory::free(ObTransService *txs) -{ - OB_DELETE(ObTransService, MEMORY_LABEL_COMPONENT_FACTORY, txs); - txs = NULL; -} - -} // namespace storage -} // namespace oceanbase diff --git a/src/storage/ob_partition_component_factory.h b/src/storage/ob_partition_component_factory.h deleted file mode 100644 index c01f66546..000000000 --- a/src/storage/ob_partition_component_factory.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * 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_COMPONENT_FACTORY_ -#define OCEANBASE_STORAGE_OB_PARTITION_COMPONENT_FACTORY_ - -#include "lib/allocator/ob_malloc.h" -#include "lib/objectpool/ob_concurrency_objpool.h" -#include "storage/ob_i_partition_component_factory.h" -#include "storage/memtable/ob_memtable_interface.h" - -namespace oceanbase -{ -namespace storage -{ -class ObSSStore; -class ObLS; - -class ObPartitionComponentFactory: public ObIPartitionComponentFactory -{ -public: - // for log stream - virtual ObLS *get_ls(const uint64_t tenant_id); -public: - ObPartitionComponentFactory() {} - virtual ~ObPartitionComponentFactory() {} - - virtual memtable::ObMemtable *get_memtable(const uint64_t tenant_id); - virtual transaction::ObTransService *get_trans_service(); - - virtual void free(ObIPartitionGroup *partition); - virtual void free(memtable::ObMemtable *memtable); - virtual void free(transaction::ObTransService *txs); - - -protected: - template - void component_free(IT *component) - { - if (OB_LIKELY(NULL != component)) { - op_free(component); - component = NULL; - } - } -}; - -} // namespace storage -} // namespace oceanbase -#endif // OCEANBASE_STORAGE_OB_PARTITION_COMPONENT_FACTORY_ diff --git a/src/storage/ob_protected_memtable_mgr_handle.h b/src/storage/ob_protected_memtable_mgr_handle.h index 7f91b5bcd..b1a95dc44 100644 --- a/src/storage/ob_protected_memtable_mgr_handle.h +++ b/src/storage/ob_protected_memtable_mgr_handle.h @@ -37,18 +37,15 @@ } \ } while (OB_SUCC(ret)); -#define DELEGATE_FOR_MEMTABLE_MGR_WITH_CREATE(function) \ -template \ -int function(const ObTabletMeta &tablet_meta, \ - Args &&...args) \ -{ \ - int ret = OB_SUCCESS; \ - PROCESS_FOR_MEMTABLE_MGR( \ - { \ - ret = memtable_mgr_handle_.get_memtable_mgr()->function(std::forward(args)...); \ - }) \ - return ret; \ -} +#define DELEGATE_FOR_MEMTABLE_MGR_WITH_CREATE(function) \ + template \ + int function(const ObTabletMeta &tablet_meta, Args &&...args) \ + { \ + int ret = OB_SUCCESS; \ + PROCESS_FOR_MEMTABLE_MGR( \ + { ret = memtable_mgr_handle_.get_memtable_mgr()->function(std::forward(args)...); }) \ + return ret; \ + } #define DELEGATE_FOR_MEMTABLE_MGR(function, ignore_not_exist_error) \ template \ @@ -95,18 +92,9 @@ int process(const ObTabletMeta &tablet_meta, \ namespace oceanbase { -namespace logservice -{ -class ObLogHandler; -} -namespace memtable -{ -class ObIMemtable; -} namespace storage { - class ObProtectedMemtableMgrHandle { public: @@ -165,6 +153,7 @@ public: DELEGATE_FOR_MEMTABLE_MGR(set_is_tablet_freeze_for_active_memtable, false); DELEGATE_FOR_MEMTABLE_MGR(get_last_frozen_memtable, false); DELEGATE_FOR_MEMTABLE_MGR(get_memtable_for_replay, false); + DELEGATE_FOR_MEMTABLE_MGR(get_direct_load_memtables_for_write, true); DELEGATE_FOR_MEMTABLE_MGR_WITH_CREATE(create_memtable); diff --git a/src/storage/ob_storage_table_guard.cpp b/src/storage/ob_storage_table_guard.cpp index 1a5f1d502..32e94daee 100644 --- a/src/storage/ob_storage_table_guard.cpp +++ b/src/storage/ob_storage_table_guard.cpp @@ -27,9 +27,11 @@ namespace oceanbase { +using namespace share; +using namespace memtable; + namespace storage { -using namespace share; ObStorageTableGuard::ObStorageTableGuard( ObTablet *tablet, ObStoreCtx &store_ctx, @@ -128,64 +130,87 @@ int ObStorageTableGuard::refresh_and_protect_table(ObRelativeTable &relative_tab int ObStorageTableGuard::refresh_and_protect_memtable() { + const int64_t DEFAULT_REFRESH_WARN_INTERVAL = 10LL * 1000LL; // 10 ms + const int64_t FIND_DIRECT_LOAD_MT_WARN_INTERVAL = 10LL * 1000LL * 1000LL; // 10 seconds + int ret = OB_SUCCESS; - memtable::ObIMemtable *memtable = nullptr; + // need_retry is set to false in two situation : + // case 1 : find a memtable and inc_write_ref success + // case 2 : no need replay + bool need_retry = true; ObTableHandleV2 handle; - const share::ObLSID &ls_id = tablet_->get_tablet_meta().ls_id_; - const common::ObTabletID &tablet_id = tablet_->get_tablet_meta().tablet_id_; - SCN clog_checkpoint_scn; - bool bool_ret = true; - bool for_replace_tablet_meta = false; - const int64_t start = ObTimeUtility::current_time(); + ObITabletMemtable *tablet_memtable = nullptr; + const ObLSID &ls_id = tablet_->get_tablet_meta().ls_id_; + const ObTabletID &tablet_id = tablet_->get_tablet_meta().tablet_id_; + const int64_t start_time = ObClockGenerator::getClock(); + int64_t warn_interval = DEFAULT_REFRESH_WARN_INTERVAL; + do { if (OB_FAIL(tablet_->get_boundary_memtable(handle))) { // if there is no memtable, create a new one if (OB_ENTRY_NOT_EXIST == ret) { - LOG_DEBUG("there is no boundary memtable", K(ret), K(ls_id), K(tablet_id)); - ObLSHandle ls_handle; - ObTabletHandle tmp_handle; - if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD))) { - LOG_WARN("failed to get log stream", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_UNLIKELY(!ls_handle.is_valid())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected error, invalid ls handle", K(ret), K(ls_handle), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->get_tablet(tablet_id, - tmp_handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { - LOG_WARN("fail to get tablet", K(ret), K(ls_id), K(tablet_id)); - } else if (FALSE_IT(clog_checkpoint_scn = tmp_handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_)) { - } else if (replay_scn_ > clog_checkpoint_scn) { - // TODO: get the newest schema_version from tablet - if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->create_memtable( - tablet_id, 0/*schema version*/, for_replay_, clog_checkpoint_scn))) { - LOG_WARN("fail to create a boundary memtable", K(ret), K(ls_id), K(tablet_id)); - } - } else { // replay_log_scn_ <= clog_checkpoint_scn - // no need to create a boundary memtable - ret = OB_SUCCESS; - break; - } - } else { // OB_ENTRY_NOT_EXIST != ret + ret = create_data_memtable_(ls_id, tablet_id, need_retry); + } else { // OB_ENTRY_NOT_EXIST != ret LOG_WARN("fail to get boundary memtable", K(ret), K(ls_id), K(tablet_id)); } - } else if (OB_FAIL(handle.get_memtable(memtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { LOG_WARN("fail to get memtable from ObTableHandle", K(ret), K(ls_id), K(tablet_id)); - } else if (OB_FAIL(check_freeze_to_inc_write_ref(memtable, bool_ret, for_replace_tablet_meta))) { + } else if (tablet_memtable->is_direct_load_memtable()) { + // set warn interval to 1 second because freeze direct load memtable is an async task + warn_interval = FIND_DIRECT_LOAD_MT_WARN_INTERVAL; + ret = create_data_memtable_(ls_id, tablet_id, need_retry); + } else if (OB_FAIL(check_freeze_to_inc_write_ref(static_cast(tablet_memtable), need_retry))) { if (OB_EAGAIN == ret) { } else if (OB_MINOR_FREEZE_NOT_ALLOW != ret) { - LOG_WARN("fail to check_freeze", K(ret), K(tablet_id), K(bool_ret), KPC(memtable)); - } - } else { - // do nothing - } - const int64_t cost_time = ObTimeUtility::current_time() - start; - if (cost_time > 10 * 1000) { - if (TC_REACH_TIME_INTERVAL(10 * 1000)) { - TRANS_LOG_RET(WARN, OB_ERR_TOO_MUCH_TIME, "refresh replay table too much times", K(ret), - K(ls_id), K(tablet_id), K(cost_time)); + LOG_WARN("fail to check_freeze", K(ret), K(tablet_id), K(need_retry), KPC(tablet_memtable)); } } - } while ((OB_SUCC(ret) || OB_ENTRY_NOT_EXIST == ret || OB_EAGAIN == ret) && bool_ret); + const int64_t cost_time = ObClockGenerator::getClock() - start_time; + if (cost_time > warn_interval) { + if (TC_REACH_TIME_INTERVAL(warn_interval)) { + TRANS_LOG_RET(WARN, + OB_ERR_TOO_MUCH_TIME, + "refresh replay table too much times", + K(ret), + K(ls_id), + K(tablet_id), + K(cost_time)); + } + } + } while ((OB_SUCC(ret) || OB_ENTRY_NOT_EXIST == ret || OB_EAGAIN == ret) && need_retry); + + return ret; +} + +int ObStorageTableGuard::create_data_memtable_(const share::ObLSID &ls_id, + const common::ObTabletID &tablet_id, + bool &need_retry) +{ + int ret = OB_SUCCESS; + LOG_DEBUG("there is no boundary memtable", K(ret), K(ls_id), K(tablet_id)); + ObLSHandle ls_handle; + ObTabletHandle tmp_handle; + SCN clog_checkpoint_scn; + if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD))) { + LOG_WARN("failed to get log stream", K(ret), K(ls_id), K(tablet_id)); + } else if (OB_UNLIKELY(!ls_handle.is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error, invalid ls handle", K(ret), K(ls_handle), K(ls_id), K(tablet_id)); + } else if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->get_tablet( + tablet_id, tmp_handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { + LOG_WARN("fail to get tablet", K(ret), K(ls_id), K(tablet_id)); + } else if (FALSE_IT(clog_checkpoint_scn = tmp_handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_)) { + } else if (replay_scn_ > clog_checkpoint_scn) { + // TODO: get the newest schema_version from tablet + if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->create_memtable( + tablet_id, 0 /* schema version */, false /* for_direct_load */, for_replay_, clog_checkpoint_scn))) { + LOG_WARN("fail to create a boundary memtable", K(ret), K(ls_id), K(tablet_id)); + } + } else { + // replay_log_scn_ <= clog_checkpoint_scn. no need to create a boundary memtable + need_retry = false; + } return ret; } @@ -200,26 +225,26 @@ void ObStorageTableGuard::reset() void ObStorageTableGuard::double_check_inc_write_ref( const uint32_t old_freeze_flag, const bool is_tablet_freeze, - memtable::ObIMemtable *memtable, - bool &bool_ret) + ObIMemtable *memtable, + bool &need_retry) { if (OB_ISNULL(memtable)) { LOG_WARN_RET(OB_ERR_UNEXPECTED, "memtable is null when inc write ref"); } else { memtable->inc_write_ref(); const uint32 new_freeze_flag = memtable->get_freeze_flag(); - const bool new_is_tablet_freeze = memtable->get_is_tablet_freeze(); + const bool new_is_tablet_freeze = memtable->is_tablet_freeze(); // do double-check to prevent concurrency problems if (old_freeze_flag != new_freeze_flag || is_tablet_freeze != new_is_tablet_freeze) { memtable->dec_write_ref(); } else { - bool_ret = false; + need_retry = false; memtable_ = memtable; } } } -int ObStorageTableGuard::get_memtable_for_replay(memtable::ObIMemtable *&memtable) +int ObStorageTableGuard::get_memtable_for_replay(ObIMemtable *&memtable) { int ret = OB_SUCCESS; const common::ObTabletID &tablet_id = tablet_->get_tablet_meta().tablet_id_; @@ -234,26 +259,25 @@ int ObStorageTableGuard::get_memtable_for_replay(memtable::ObIMemtable *&memtabl return ret; } -int ObStorageTableGuard::check_freeze_to_inc_write_ref(ObITable *table, bool &bool_ret, bool &for_replace_tablet_meta) +int ObStorageTableGuard::check_freeze_to_inc_write_ref(ObMemtable *memtable, bool &need_retry) { int ret = OB_SUCCESS; - bool_ret = true; + need_retry = true; const share::ObLSID &ls_id = tablet_->get_tablet_meta().ls_id_; const common::ObTabletID &tablet_id = tablet_->get_tablet_meta().tablet_id_; // need to make sure the memtable is a right boundary memtable - memtable::ObIMemtable *memtable = static_cast(table); - memtable::ObIMemtable *old_memtable = memtable; + ObMemtable *old_memtable = memtable; // get freeze_flag before memtable->is_active_memtable() to double-check // prevent that the memtable transforms from active to frozen before inc_write_ref uint32_t old_freeze_flag = 0; bool is_tablet_freeze = false; ObProtectedMemtableMgrHandle *protected_handle = NULL; - if (OB_ISNULL(table)) { - LOG_INFO("table is null, need to refresh", K(bool_ret), K(ls_id), K(tablet_id)); + if (OB_ISNULL(memtable)) { + LOG_INFO("table is null, need to refresh", K(need_retry), K(ls_id), K(tablet_id)); } else if (FALSE_IT(old_freeze_flag = memtable->get_freeze_flag())) { - } else if (FALSE_IT(is_tablet_freeze = memtable->get_is_tablet_freeze())) { - } else if (memtable->is_active_memtable() || for_replace_tablet_meta) { + } else if (FALSE_IT(is_tablet_freeze = memtable->is_tablet_freeze())) { + } else if (memtable->is_active_memtable()) { // the most recent memtable is active // no need to create a new memtable if (for_replay_ || for_multi_source_data_) { @@ -264,21 +288,21 @@ int ObStorageTableGuard::check_freeze_to_inc_write_ref(ObITable *table, bool &bo } else if (OB_FAIL(protected_handle->get_memtable_for_replay(replay_scn_, handle))) { if (OB_NO_NEED_UPDATE == ret) { // no need to replay the log - bool_ret = false; + need_retry = false; ret = OB_SUCCESS; } else { - LOG_WARN("fail to get memtable for replay", K(ret), K(bool_ret), K(ls_id), K(tablet_id)); + LOG_WARN("fail to get memtable for replay", K(ret), K(need_retry), K(ls_id), K(tablet_id)); } - } else if (OB_FAIL(handle.get_memtable(memtable))) { - LOG_WARN("fail to get memtable from ObTableHandle", K(ret), K(bool_ret), K(ls_id), K(tablet_id)); + } else if (OB_FAIL(handle.get_data_memtable(memtable))) { + LOG_WARN("fail to get memtable from ObTableHandle", K(ret), K(need_retry), K(ls_id), K(tablet_id)); } else { if (memtable != old_memtable) { - is_tablet_freeze = memtable->get_is_tablet_freeze(); + is_tablet_freeze = memtable->is_tablet_freeze(); } - double_check_inc_write_ref(old_freeze_flag, is_tablet_freeze, memtable, bool_ret); + double_check_inc_write_ref(old_freeze_flag, is_tablet_freeze, memtable, need_retry); } } else { - double_check_inc_write_ref(old_freeze_flag, is_tablet_freeze, memtable, bool_ret); + double_check_inc_write_ref(old_freeze_flag, is_tablet_freeze, memtable, need_retry); } } else { // the most recent memtable is frozen @@ -292,19 +316,18 @@ int ObStorageTableGuard::check_freeze_to_inc_write_ref(ObITable *table, bool &bo ObTabletHandle tmp_handle; ObLSHandle ls_handle; if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD))) { - LOG_WARN("failed to get log stream", K(ret), K(bool_ret), K(ls_id), K(tablet_id)); + LOG_WARN("failed to get log stream", K(ret), K(need_retry), K(ls_id), K(tablet_id)); } else if (OB_UNLIKELY(!ls_handle.is_valid())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected error, invalid ls handle", K(ret), K(bool_ret), K(ls_handle), K(ls_id), K(tablet_id)); + LOG_WARN("unexpected error, invalid ls handle", K(ret), K(need_retry), K(ls_handle), K(ls_id), K(tablet_id)); } else if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->get_tablet(tablet_id, tmp_handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK))) { LOG_WARN("fail to get tablet", K(ret), K(ls_id), K(tablet_id)); } else if (FALSE_IT(clog_checkpoint_scn = tmp_handle.get_obj()->get_tablet_meta().clog_checkpoint_scn_)) { - } else if (FALSE_IT(migration_clog_checkpoint_scn = static_cast(memtable)->get_migration_clog_checkpoint_scn())) { + } else if (FALSE_IT(migration_clog_checkpoint_scn = memtable->get_migration_clog_checkpoint_scn())) { } else if (for_replay_ && !migration_clog_checkpoint_scn.is_min()) { - static_cast(memtable)->resolve_right_boundary(); + memtable->resolve_right_boundary(); if (replay_scn_ <= clog_checkpoint_scn) { - for_replace_tablet_meta = true; need_create_memtable = false; } } @@ -312,13 +335,15 @@ int ObStorageTableGuard::check_freeze_to_inc_write_ref(ObITable *table, bool &bo // create a new memtable if no write in the old memtable if (OB_FAIL(ret)) { } else if (need_create_memtable) { - if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->create_memtable(tablet_id, - memtable->get_max_schema_version()/*schema version*/, - for_replay_, - clog_checkpoint_scn))) { + if (OB_FAIL(ls_handle.get_ls()->get_tablet_svr()->create_memtable( + tablet_id, + memtable->get_max_schema_version() /*schema version*/, + false /*for_direct_load*/, + for_replay_, + clog_checkpoint_scn))) { if (OB_EAGAIN == ret) { } else if (OB_MINOR_FREEZE_NOT_ALLOW != ret) { - LOG_WARN("fail to create new memtable for freeze", K(ret), K(bool_ret), K(ls_id), K(tablet_id)); + LOG_WARN("fail to create new memtable for freeze", K(ret), K(need_retry), K(ls_id), K(tablet_id)); } } } @@ -332,14 +357,13 @@ bool ObStorageTableGuard::need_to_refresh_table(ObTableStoreIterator &iter) { int ret = OB_SUCCESS; bool bool_ret = false; - bool for_replace_tablet_meta = false; int exit_flag = -1; ObITable *table = iter.get_last_memtable(); + ObMemtable *memtable = static_cast(table); bool need_create_memtable = false; - if (NULL == table || !table->is_memtable()) { + if (NULL == table || !table->is_data_memtable()) { need_create_memtable = true; } else { - memtable::ObIMemtable *memtable = static_cast(table); ObLSID ls_id = memtable->get_ls_id(); if (OB_UNLIKELY(!ls_id.is_valid())) { ret = OB_ERR_UNEXPECTED; @@ -357,7 +381,8 @@ bool ObStorageTableGuard::need_to_refresh_table(ObTableStoreIterator &iter) if (OB_FAIL(ret)) { } else if (need_create_memtable) { const common::ObTabletID &tablet_id = tablet_->get_tablet_meta().tablet_id_; - if (OB_FAIL(store_ctx_.ls_->get_tablet_svr()->create_memtable(tablet_id, 0/*schema version*/, for_replay_))) { + if (OB_FAIL(store_ctx_.ls_->get_tablet_svr()->create_memtable( + tablet_id, 0 /*schema version*/, false /*for_inc_direct_load*/, for_replay_))) { LOG_WARN("fail to create a boundary memtable", K(ret), K(tablet_id)); } bool_ret = true; @@ -367,7 +392,7 @@ bool ObStorageTableGuard::need_to_refresh_table(ObTableStoreIterator &iter) } else if (iter.check_store_expire()) { bool_ret = true; exit_flag = 1; - } else if (OB_FAIL(check_freeze_to_inc_write_ref(table, bool_ret, for_replace_tablet_meta))) { + } else if (OB_FAIL(check_freeze_to_inc_write_ref(memtable, bool_ret))) { bool_ret = true; exit_flag = 2; if (OB_MINOR_FREEZE_NOT_ALLOW != ret) { diff --git a/src/storage/ob_storage_table_guard.h b/src/storage/ob_storage_table_guard.h index 15ede4779..f5127eebc 100644 --- a/src/storage/ob_storage_table_guard.h +++ b/src/storage/ob_storage_table_guard.h @@ -22,18 +22,22 @@ namespace oceanbase namespace share { class ObThrottleInfoGuard; +class ObLSID; } -namespace memtable -{ -class ObIMemtable; +namespace common{ +class ObTabletID; +} + +namespace memtable { +class ObMemtable; } namespace storage { -class ObTablet; -class ObITable; struct ObStoreCtx; +class ObTablet; +class ObIMemtable; class ObRelativeTable; class ObTableStoreIterator; @@ -54,15 +58,27 @@ public: public: int refresh_and_protect_table(ObRelativeTable &relative_table); int refresh_and_protect_memtable(); - int get_memtable_for_replay(memtable::ObIMemtable *&memtable); + int get_memtable_for_replay(ObIMemtable *&memtable); + + TO_STRING_KV(KP(tablet_), + K(need_control_mem_), + K(for_replay_), + K(for_multi_source_data_), + K(replay_scn_), + KP(memtable_), + K(retry_count_), + K(last_ts_), + K(init_ts_)); + private: void reset(); void double_check_inc_write_ref( const uint32_t old_freeze_flag, const bool is_tablet_freeze, - memtable::ObIMemtable *memtable, + ObIMemtable *memtable, bool &bool_ret); - int check_freeze_to_inc_write_ref(ObITable *table, bool &bool_ret, bool &for_replace_tablet_meta); + int check_freeze_to_inc_write_ref(memtable::ObMemtable *table, bool &bool_ret); + int create_data_memtable_(const share::ObLSID &ls_id, const common::ObTabletID &tablet_id, bool &no_need_create); bool need_to_refresh_table(ObTableStoreIterator &iter); void check_if_need_log_(bool &need_log, bool &need_log_error); void throttle_if_needed_(); @@ -76,7 +92,7 @@ private: ObTablet *tablet_; ObStoreCtx &store_ctx_; bool need_control_mem_; - memtable::ObIMemtable *memtable_; + ObIMemtable *memtable_; int64_t retry_count_; int64_t last_ts_; // record write latency diff --git a/src/storage/tablelock/ob_lock_memtable.cpp b/src/storage/tablelock/ob_lock_memtable.cpp index 82a090788..bc966269c 100644 --- a/src/storage/tablelock/ob_lock_memtable.cpp +++ b/src/storage/tablelock/ob_lock_memtable.cpp @@ -898,12 +898,12 @@ bool ObLockMemtable::can_be_minor_merged() return bool_ret; } -bool ObLockMemtable::is_frozen_memtable() const +bool ObLockMemtable::is_frozen_memtable() { return ATOMIC_LOAD(&is_frozen_); } -bool ObLockMemtable::is_active_memtable() const +bool ObLockMemtable::is_active_memtable() { return !ATOMIC_LOAD(&is_frozen_); } diff --git a/src/storage/tablelock/ob_lock_memtable.h b/src/storage/tablelock/ob_lock_memtable.h index 2b13fa3cc..6f8738d45 100644 --- a/src/storage/tablelock/ob_lock_memtable.h +++ b/src/storage/tablelock/ob_lock_memtable.h @@ -41,7 +41,7 @@ namespace tablelock struct ObLockParam; class ObLockMemtable - : public memtable::ObIMemtable, + : public ObIMemtable, public storage::checkpoint::ObCommonCheckpoint { public: @@ -121,8 +121,8 @@ public: virtual bool can_be_minor_merged() override; int on_memtable_flushed() override; - bool is_frozen_memtable() const override; - bool is_active_memtable() const override; + bool is_frozen_memtable() override; + bool is_active_memtable() override; // =========== INHERITED FROM ObCommonCheckPoint ========== virtual share::SCN get_rec_scn(); diff --git a/src/storage/tablelock/ob_lock_memtable_mgr.cpp b/src/storage/tablelock/ob_lock_memtable_mgr.cpp index 49ba8e445..c92bb4383 100644 --- a/src/storage/tablelock/ob_lock_memtable_mgr.cpp +++ b/src/storage/tablelock/ob_lock_memtable_mgr.cpp @@ -83,23 +83,14 @@ int ObLockMemtableMgr::init( ls_id_ = ls_id; freezer_ = freezer; t3m_ = t3m; - table_type_ = ObITable::TableType::LOCK_MEMTABLE; is_inited_ = true; LOG_INFO("lock memtable mgr init successfully", K(ls_id), K(tablet_id), K(this)); } return ret; } -int ObLockMemtableMgr::create_memtable(const SCN clog_checkpoint_scn, - const int64_t schema_version, - const SCN newest_clog_checkpoint_scn, - const bool for_replay) +int ObLockMemtableMgr::create_memtable(const CreateMemtableArg &arg) { - UNUSED(clog_checkpoint_scn); - UNUSED(schema_version); - UNUSED(newest_clog_checkpoint_scn); - UNUSED(for_replay); - int ret = OB_SUCCESS; ObTableHandleV2 handle; ObITable::TableKey table_key; @@ -198,7 +189,7 @@ int ObLockMemtableMgr::unregister_from_common_checkpoint_(const ObLockMemtable * return ret; } -int ObLockMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable, +int ObLockMemtableMgr::release_head_memtable_(ObIMemtable *imemtable, const bool force) { int ret = OB_SUCCESS; diff --git a/src/storage/tablelock/ob_lock_memtable_mgr.h b/src/storage/tablelock/ob_lock_memtable_mgr.h index 68764e6b8..566c13ee3 100644 --- a/src/storage/tablelock/ob_lock_memtable_mgr.h +++ b/src/storage/tablelock/ob_lock_memtable_mgr.h @@ -29,11 +29,11 @@ class ObLSID; namespace memtable { -class ObIMemtable; } namespace storage { +class ObIMemtable; class ObFreezer; class ObTenantMetaMemMgr; } @@ -60,16 +60,13 @@ public: storage::ObTenantMetaMemMgr *t3m) override; virtual void destroy() override; - virtual int create_memtable(const share::SCN clog_checkpoint_scn, - const int64_t schema_version, - const share::SCN newest_clog_checkpoint_scn, - const bool for_replay = false) override; + virtual int create_memtable(const storage::CreateMemtableArg &arg) override; DECLARE_VIRTUAL_TO_STRING; private: const ObLockMemtable *get_memtable_(const int64_t pos) const; private: - virtual int release_head_memtable_(memtable::ObIMemtable *imemtable, + virtual int release_head_memtable_(storage::ObIMemtable *imemtable, const bool force = false) override; int unregister_from_common_checkpoint_(const ObLockMemtable *memtable); diff --git a/src/storage/tablelock/ob_lock_table.cpp b/src/storage/tablelock/ob_lock_table.cpp index 7faa69fd3..4b4458ab5 100644 --- a/src/storage/tablelock/ob_lock_table.cpp +++ b/src/storage/tablelock/ob_lock_table.cpp @@ -300,7 +300,8 @@ int ObLockTable::online() handle))) { LOG_WARN("get tablet failed", K(ret)); } else if (FALSE_IT(tablet = handle.get_obj())) { - } else if (OB_FAIL(ls_tablet_svr->create_memtable(LS_LOCK_TABLET, 0 /* schema_version */))) { + } else if (OB_FAIL(ls_tablet_svr->create_memtable( + LS_LOCK_TABLET, 0 /* schema_version */, false /* for_inc_direct_load */, false /*for_replay*/))) { LOG_WARN("failed to create memtable", K(ret)); } else if (OB_FAIL(tablet->fetch_table_store(table_store_wrapper))) { LOG_WARN("fail to fetch table store", K(ret)); @@ -394,7 +395,8 @@ int ObLockTable::load_lock() handle))) { LOG_WARN("get tablet failed", K(ret)); } else if (FALSE_IT(tablet = handle.get_obj())) { - } else if (OB_FAIL(ls_tablet_svr->create_memtable(LS_LOCK_TABLET, 0 /* schema_version */))) { + } else if (OB_FAIL(ls_tablet_svr->create_memtable( + LS_LOCK_TABLET, 0 /* schema_version */, false /* for_inc_direct_load */, false /*for_replay*/))) { LOG_WARN("failed to create memtable", K(ret)); } else if (OB_FAIL(tablet->fetch_table_store(table_store_wrapper))) { LOG_WARN("fail to fetch table store", K(ret)); diff --git a/src/storage/tablelock/ob_table_lock_callback.cpp b/src/storage/tablelock/ob_table_lock_callback.cpp index adfe639b5..6ca15e30f 100644 --- a/src/storage/tablelock/ob_table_lock_callback.cpp +++ b/src/storage/tablelock/ob_table_lock_callback.cpp @@ -30,12 +30,12 @@ namespace transaction namespace tablelock { -bool ObOBJLockCallback::on_memtable(const memtable::ObIMemtable * const memtable) +bool ObOBJLockCallback::on_memtable(const ObIMemtable * const memtable) { return memtable == memtable_; } -memtable::ObIMemtable* ObOBJLockCallback::get_memtable() const +ObIMemtable* ObOBJLockCallback::get_memtable() const { return memtable_; } diff --git a/src/storage/tablelock/ob_table_lock_callback.h b/src/storage/tablelock/ob_table_lock_callback.h index a77a1c7b2..f0e3af761 100644 --- a/src/storage/tablelock/ob_table_lock_callback.h +++ b/src/storage/tablelock/ob_table_lock_callback.h @@ -58,8 +58,8 @@ public: key_.encode(key); lock_op_ = lock_op; } - bool on_memtable(const memtable::ObIMemtable * const memtable) override; - memtable::ObIMemtable* get_memtable() const override; + bool on_memtable(const storage::ObIMemtable * const memtable) override; + storage::ObIMemtable* get_memtable() const override; virtual int del() override; transaction::ObTxSEQ get_seq_no() const override; bool is_table_lock_callback() const override { return true; } diff --git a/src/storage/tablet/ob_table_store_util.cpp b/src/storage/tablet/ob_table_store_util.cpp index 7bb437a1b..6921589a1 100644 --- a/src/storage/tablet/ob_table_store_util.cpp +++ b/src/storage/tablet/ob_table_store_util.cpp @@ -846,12 +846,12 @@ int ObMemtableArray::build(common::ObIArray &table_array, const int6 ObITable *table = nullptr; for (int64_t i = start_pos; OB_SUCC(ret) && i < table_array.count(); ++i) { - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; table = table_array.at(i); if (OB_UNLIKELY(nullptr == table || !table->is_memtable())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must be memtable", K(ret), K(i), KPC(table)); - } else if (FALSE_IT(memtable = reinterpret_cast(table))) { + } else if (FALSE_IT(memtable = reinterpret_cast(table))) { } else if (memtable->is_empty()) { FLOG_INFO("empty memtable discarded", KPC(memtable)); } else if (OB_UNLIKELY(count_ == MAX_MEMSTORE_CNT)) { @@ -873,16 +873,16 @@ int ObMemtableArray::rebuild(const common::ObIArray &table_array) { int ret = OB_SUCCESS; - const memtable::ObIMemtable *last_memtable = count_ > 0 ? memtable_array_[count_ - 1] : nullptr; + const ObIMemtable *last_memtable = count_ > 0 ? memtable_array_[count_ - 1] : nullptr; const share::SCN endscn = (NULL == last_memtable) ? share::SCN::min_scn() : last_memtable->get_end_scn(); for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) { - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; ObITable *table = table_array.at(i); if (OB_UNLIKELY(nullptr == table || !table->is_memtable())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must be memtable", K(ret), K(i), KPC(table)); - } else if (FALSE_IT(memtable = static_cast(table))) { + } else if (FALSE_IT(memtable = static_cast(table))) { } else if (memtable->is_empty()) { FLOG_INFO("Empty memtable discarded", KPC(memtable)); } else if (table->get_end_scn() < endscn) { @@ -912,12 +912,12 @@ int ObMemtableArray::rebuild( } else { // use clog checkpoint scn to filter memtable array for (int64_t i = 0; OB_SUCC(ret) && i < table_array.count(); ++i) { - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; ObITable *table = table_array.at(i); if (OB_UNLIKELY(nullptr == table || !table->is_memtable())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must be memtable", K(ret), K(i), KPC(table)); - } else if (FALSE_IT(memtable = static_cast(table))) { + } else if (FALSE_IT(memtable = static_cast(table))) { } else if (memtable->is_empty()) { FLOG_INFO("Empty memtable discarded", K(ret), KPC(memtable)); } else if (table->get_end_scn() <= clog_checkpoint_scn) { diff --git a/src/storage/tablet/ob_table_store_util.h b/src/storage/tablet/ob_table_store_util.h index b50c64449..83c3d6476 100644 --- a/src/storage/tablet/ob_table_store_util.h +++ b/src/storage/tablet/ob_table_store_util.h @@ -120,7 +120,7 @@ class ObMemtableArray { public: ObMemtableArray() : memtable_array_(), count_(0) {} - OB_INLINE memtable::ObIMemtable *operator[](const int64_t pos) const + OB_INLINE ObIMemtable *operator[](const int64_t pos) const { OB_ASSERT(pos < count_ && pos >= 0); return memtable_array_[pos]; @@ -141,7 +141,7 @@ public: TO_STRING_KV(K_(count)); private: bool exist_memtable_with_end_scn(const ObITable *table, const share::SCN &end_scn); - memtable::ObIMemtable *memtable_array_[MAX_MEMSTORE_CNT]; + ObIMemtable *memtable_array_[MAX_MEMSTORE_CNT]; int64_t count_; private: DISALLOW_COPY_AND_ASSIGN(ObMemtableArray); diff --git a/src/storage/tablet/ob_tablet.cpp b/src/storage/tablet/ob_tablet.cpp index f0fff733c..468cf4750 100644 --- a/src/storage/tablet/ob_tablet.cpp +++ b/src/storage/tablet/ob_tablet.cpp @@ -84,6 +84,7 @@ #include "src/storage/slog_ckpt/ob_linked_macro_block_writer.h" #include "storage/tablet/ob_tablet_macro_info_iterator.h" #include "storage/blocksstable/ob_shared_macro_block_manager.h" +#include "storage/ob_direct_load_table_guard.h" namespace oceanbase { @@ -4254,6 +4255,7 @@ int ObTablet::get_active_memtable(ObTableHandleV2 &handle) const int ObTablet::create_memtable( const int64_t schema_version, const SCN clog_checkpoint_scn, + const bool for_direct_load, const bool for_replay) { int ret = OB_SUCCESS; @@ -4271,7 +4273,7 @@ int ObTablet::create_memtable( ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid schema version", K(ret), K(schema_version)); } else if (FALSE_IT(time_guard.click("prepare_memtables"))) { - } else if (OB_FAIL(inner_create_memtable(new_clog_checkpoint_scn, schema_version, for_replay))) { + } else if (OB_FAIL(inner_create_memtable(new_clog_checkpoint_scn, schema_version, for_direct_load, for_replay))) { if (OB_ENTRY_EXIST == ret) { ret = OB_SUCCESS; } else if (OB_MINOR_FREEZE_NOT_ALLOW != ret) { @@ -4303,12 +4305,19 @@ int ObTablet::create_memtable( } } + STORAGE_LOG(DEBUG, + "Tablet finish create memtable", + K(schema_version), + K(clog_checkpoint_scn), + K(for_replay), + K(lbt())); return ret; } int ObTablet::inner_create_memtable( const SCN clog_checkpoint_scn, const int64_t schema_version, + const bool for_direct_load, const bool for_replay) { int ret = OB_SUCCESS; @@ -4328,14 +4337,18 @@ int ObTablet::inner_create_memtable( } } else if (OB_FAIL(get_protected_memtable_mgr_handle(protected_handle))) { LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(this)); - } else if (OB_FAIL(protected_handle->create_memtable(tablet_meta_, clog_checkpoint_scn, schema_version, - new_clog_checkpoint_scn, for_replay))) { + } else if (OB_FAIL(protected_handle->create_memtable(tablet_meta_, + CreateMemtableArg(schema_version, + clog_checkpoint_scn, + new_clog_checkpoint_scn, + for_replay, + for_direct_load)))) { if (OB_ENTRY_EXIST != ret && OB_MINOR_FREEZE_NOT_ALLOW != ret) { LOG_WARN("failed to create memtable", K(ret), K(ls_id), K(tablet_id), KPC(this)); } } else { LOG_INFO("succeeded to create memtable for tablet", K(ret), K(ls_id), K(tablet_id), - K(clog_checkpoint_scn), K(schema_version)); + K(clog_checkpoint_scn), K(schema_version), K(for_replay)); } return ret; @@ -5718,46 +5731,6 @@ int ObTablet::get_finish_medium_scn(int64_t &finish_medium_scn) const return ret; } -int ObTablet::set_memtable_clog_checkpoint_scn( - const ObMigrationTabletParam *tablet_meta) -{ - int ret = OB_SUCCESS; - ObTableHandleV2 handle; - memtable::ObMemtable *memtable = nullptr; - - ObProtectedMemtableMgrHandle *protected_handle = NULL; - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - LOG_WARN("not inited", K(ret), K_(is_inited)); - } else if (OB_ISNULL(tablet_meta)) { - // no need to set memtable clog checkpoint ts - } else if (tablet_meta->clog_checkpoint_scn_ <= tablet_meta_.clog_checkpoint_scn_) { - // do nothing - } else if (is_ls_inner_tablet()) { - if (OB_FAIL(get_protected_memtable_mgr_handle(protected_handle))) { - LOG_WARN("failed to get_protected_memtable_mgr_handle", K(ret), KPC(this)); - } else if (OB_UNLIKELY(protected_handle->has_memtable())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("ls inner tablet should not have memtable", K(ret), KPC(tablet_meta)); - } - } else if (OB_FAIL(get_boundary_memtable(handle))) { - if (OB_ENTRY_NOT_EXIST == ret) { - ret = OB_SUCCESS; - } else { - LOG_WARN("failed to get boundary memtable for tablet", K(ret), KPC(this), KPC(tablet_meta)); - } - } else if (OB_FAIL(handle.get_data_memtable(memtable))) { - LOG_WARN("failed to get memtable", K(ret), K(handle)); - } else if (OB_ISNULL(memtable)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null memtable", K(ret), KPC(memtable)); - } else if (OB_FAIL(memtable->set_migration_clog_checkpoint_scn(tablet_meta->clog_checkpoint_scn_))) { - LOG_WARN("failed to set migration clog checkpoint ts", K(ret), K(handle), KPC(this)); - } - - return ret; -} - int ObTablet::get_medium_info_list( common::ObArenaAllocator &allocator, compaction::ObMediumCompactionInfoList &medium_info_list) const @@ -6009,7 +5982,7 @@ int ObTablet::pull_memtables_without_ddl() int64_t start_pos = -1; for (int64_t i = 0; OB_SUCC(ret) && i < memtable_handles.count(); ++i) { - memtable::ObIMemtable *table = static_cast(memtable_handles.at(i).get_table()); + ObIMemtable *table = static_cast(memtable_handles.at(i).get_table()); if (OB_ISNULL(table) || !table->is_memtable()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must not null and must be memtable", K(ret), K(table)); @@ -6139,12 +6112,12 @@ int ObTablet::build_memtable(common::ObIArray &handle_array, co ObITable *table = nullptr; for (int64_t i = start_pos; OB_SUCC(ret) && i < handle_array.count(); ++i) { - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; table = handle_array.at(i).get_table(); if (OB_UNLIKELY(nullptr == table || !table->is_memtable())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must be memtable", K(ret), K(i), KPC(table)); - } else if (FALSE_IT(memtable = static_cast(table))) { + } else if (FALSE_IT(memtable = static_cast(table))) { } else if (memtable->is_empty()) { FLOG_INFO("Empty memtable discarded", KPC(memtable)); } else if (OB_FAIL(add_memtable(memtable))) { @@ -6273,12 +6246,12 @@ int ObTablet::rebuild_memtable(common::ObIArray &handle_array) LOG_DEBUG("before rebuild memtable", K(memtable_count_), K(last_idx), KP(last_memtable), K(end_scn), K(handle_array)); for (int64_t i = 0; OB_SUCC(ret) && i < handle_array.count(); ++i) { - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; ObITable *table = handle_array.at(i).get_table(); if (OB_UNLIKELY(nullptr == table || !table->is_memtable())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must be memtable", K(ret), K(i), KPC(table)); - } else if (FALSE_IT(memtable = static_cast(table))) { + } else if (FALSE_IT(memtable = static_cast(table))) { } else if (memtable->is_empty()) { FLOG_INFO("Empty memtable discarded", KPC(memtable)); } else if (table->get_end_scn() < end_scn) { @@ -6310,12 +6283,12 @@ int ObTablet::rebuild_memtable( } else { // use clog checkpoint scn to filter memtable handle array for (int64_t i = 0; OB_SUCC(ret) && i < handle_array.count(); ++i) { - memtable::ObIMemtable *memtable = nullptr; + ObIMemtable *memtable = nullptr; ObITable *table = handle_array.at(i).get_table(); if (OB_UNLIKELY(nullptr == table || !table->is_memtable())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table must be memtable", K(ret), K(i), KPC(table)); - } else if (FALSE_IT(memtable = static_cast(table))) { + } else if (FALSE_IT(memtable = static_cast(table))) { } else if (memtable->is_empty()) { FLOG_INFO("Empty memtable discarded", K(ret), KPC(memtable)); } else if (table->get_end_scn() <= clog_checkpoint_scn) { @@ -6329,7 +6302,7 @@ int ObTablet::rebuild_memtable( return ret; } -int ObTablet::add_memtable(memtable::ObIMemtable* const table) +int ObTablet::add_memtable(ObIMemtable* const table) { int ret = OB_SUCCESS; @@ -6366,7 +6339,7 @@ bool ObTablet::exist_memtable_with_end_scn(const ObITable *table, const SCN &end return is_exist; } -int ObTablet::assign_memtables(memtable::ObIMemtable * const * memtables, const int64_t memtable_count) +int ObTablet::assign_memtables(ObIMemtable * const * memtables, const int64_t memtable_count) { int ret = OB_SUCCESS; @@ -6374,10 +6347,10 @@ int ObTablet::assign_memtables(memtable::ObIMemtable * const * memtables, const ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid memtable argument", K(ret), KP(memtables), K(memtable_count)); } else { - MEMSET(memtables_, 0, sizeof(memtable::ObIMemtable*) * MAX_MEMSTORE_CNT); + MEMSET(memtables_, 0, sizeof(ObIMemtable*) * MAX_MEMSTORE_CNT); // deep copy memtables to tablet.memtables_ and inc ref for (int64_t i = 0; OB_SUCC(ret) && i < memtable_count; ++i) { - memtable::ObIMemtable * memtable = memtables[i]; + ObIMemtable * memtable = memtables[i]; if (OB_ISNULL(memtable)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null memtable ptr", K(ret), K(i), KP(memtables)); @@ -6424,10 +6397,10 @@ void ObTablet::reset_memtable() ObTenantMetaMemMgr *t3m = MTL(ObTenantMetaMemMgr*); for(int i = 0; i < MAX_MEMSTORE_CNT; ++i) { if (OB_NOT_NULL(memtables_[i])) { - const ObITable::TableType table_type = memtables_[i]->get_key().table_type_; const int64_t ref_cnt = memtables_[i]->dec_ref(); if (0 == ref_cnt) { - t3m->push_table_into_gc_queue(memtables_[i], table_type); + t3m->push_table_into_gc_queue(memtables_[i], + memtables_[i]->get_table_type()); } } memtables_[i] = nullptr; @@ -6551,7 +6524,12 @@ void ObTablet::reset_ddl_memtables() { for(int64_t i = 0; i < ddl_kv_count_; ++i) { ObDDLKV *ddl_kv = ddl_kvs_[i]; - ddl_kv->dec_ref(); + const int64_t ref_cnt = ddl_kv->dec_ref(); + if (0 == ref_cnt) { + MTL(ObTenantMetaMemMgr *)->release_ddl_kv(ddl_kv); + } else if (OB_UNLIKELY(ref_cnt < 0)) { + LOG_ERROR_RET(OB_ERR_UNEXPECTED, "table ref cnt may be leaked", K(ref_cnt), KP(ddl_kv)); + } ddl_kvs_[i] = nullptr; } ddl_kvs_ = nullptr; @@ -7464,5 +7442,33 @@ int ObTablet::get_all_minor_sstables(ObTableStoreIterator &table_store_iter) con return ret; } +int ObTablet::set_macro_block(const ObDDLMacroBlock ¯o_block, + const int64_t snapshot_version, + const uint64_t data_format_version) +{ + int ret = OB_SUCCESS; + ObDirectLoadTableGuard guard(*this, macro_block.scn_, true/*for_replay*/); + ObDDLKV *ddl_kv = nullptr; + if (OB_FAIL(guard.prepare_memtable(ddl_kv))) { + LOG_WARN("fail to prepare memtable", KR(ret)); + } else if (guard.is_write_filtered()) { + // do nothing + } else if (OB_ISNULL(ddl_kv)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected memtable is null", KR(ret)); + } else if (OB_FAIL(ddl_kv->set_max_end_scn(macro_block.scn_))) { + LOG_WARN("fail to set max end scn", KR(ret), KPC(ddl_kv), K(macro_block)); + } else if (OB_FAIL(ddl_kv->set_macro_block(*this, + macro_block, + snapshot_version, + data_format_version, + false /*can_freeze*/))) { + LOG_WARN("fail to set macro block", KR(ret), KPC(ddl_kv), K(macro_block), K(snapshot_version), K(data_format_version)); + } else if (OB_FAIL(ddl_kv->set_rec_scn(macro_block.scn_))) { + LOG_WARN("fail to set rec scn", KR(ret), KPC(ddl_kv), K(macro_block)); + } + return ret; +} + } // namespace storage } // namespace oceanbase diff --git a/src/storage/tablet/ob_tablet.h b/src/storage/tablet/ob_tablet.h index be8f226a9..048e1ac47 100644 --- a/src/storage/tablet/ob_tablet.h +++ b/src/storage/tablet/ob_tablet.h @@ -40,20 +40,10 @@ namespace oceanbase { -namespace common -{ -class ObThreadCond; -} - namespace share { class ObLSID; struct ObTabletAutoincInterval; - -namespace schema -{ -class ObTableSchema; -} } namespace logservice @@ -61,17 +51,6 @@ namespace logservice class ObLogHandler; } -namespace memtable -{ -class ObIMemtable; -class ObIMultiSourceDataUnit; -} - -namespace blocksstable -{ -class ObSSTable; -} - namespace compaction { class ObExtraMediumInfo; @@ -94,6 +73,7 @@ class ObAllVirtualMdsNodeStat; namespace storage { +class ObIMemtable; class ObStoreCtx; class ObTableHandleV2; class ObFreezer; @@ -508,7 +488,6 @@ public: int64_t &required_size, const bool need_checksums = true); int check_and_set_initial_state(); - int set_memtable_clog_checkpoint_scn(const ObMigrationTabletParam *tablet_meta); int read_mds_table( common::ObIAllocator &allocator, ObTabletMdsData &mds_data, @@ -578,6 +557,9 @@ public: int get_max_column_cnt_on_schema_recorder(int64_t &max_column_cnt); static int get_tablet_version(const char *buf, const int64_t len, int32_t &version); int get_all_minor_sstables(ObTableStoreIterator &table_store_iter) const; + int set_macro_block(const ObDDLMacroBlock ¯o_block, + const int64_t snapshot_version, + const uint64_t data_format_version); protected:// for MDS use virtual bool check_is_inited_() const override final { return is_inited_; } virtual const ObTabletMdsData &get_mds_data_() const override final { return mds_data_; } @@ -638,7 +620,10 @@ private: const lib::Worker::CompatMode compat_mode, ObFreezer *freezer); int build_read_info(common::ObArenaAllocator &allocator, const ObTablet *tablet = nullptr); - int create_memtable(const int64_t schema_version, const share::SCN clog_checkpoint_scn, const bool for_replay=false); + int create_memtable(const int64_t schema_version, + const share::SCN clog_checkpoint_scn, + const bool for_direct_load, + const bool for_replay); int try_update_start_scn(); int try_update_ddl_checkpoint_scn(); int try_update_table_store_flag(const ObUpdateTableStoreParam ¶m); @@ -663,11 +648,11 @@ private: ObStoreCtx &store_ctx, memtable::ObMemtable *&write_memtable); - // used for freeze_tablet int inner_create_memtable( - const share::SCN clog_checkpoint_scn = share::SCN::base_scn(),/*1 for first memtable, filled later*/ - const int64_t schema_version = 0/*0 for first memtable*/, - const bool for_replay = false); + const share::SCN clog_checkpoint_scn, + const int64_t schema_version, + const bool for_direct_load, + const bool for_replay); int inner_get_memtables(common::ObIArray &memtables, const bool need_active) const; @@ -798,9 +783,9 @@ private: int rebuild_memtable( const share::SCN &clog_checkpoint_scn, common::ObIArray &handle_array); - int add_memtable(memtable::ObIMemtable* const table); + int add_memtable(ObIMemtable* const table); bool exist_memtable_with_end_scn(const ObITable *table, const share::SCN &end_scn); - int assign_memtables(memtable::ObIMemtable * const *memtables, const int64_t memtable_count); + int assign_memtables(ObIMemtable * const *memtables, const int64_t memtable_count); int assign_ddl_kvs(ObDDLKV * const *ddl_kvs, const int64_t ddl_kv_count); int pull_ddl_memtables(ObArenaAllocator &allocator, ObDDLKV **&ddl_kvs_addr, int64_t &ddl_kv_count); void reset_ddl_memtables(); @@ -847,7 +832,7 @@ private: // through ObTabletPointerHandle. // may be some day will fix this issue, then the pointers have no need to exist. // won't persist - memtable::ObIMemtable *memtables_[MAX_MEMSTORE_CNT]; + ObIMemtable *memtables_[MAX_MEMSTORE_CNT]; ObArenaAllocator *allocator_; mutable common::SpinRWLock memtables_lock_; // size: 12B, alignment: 4B logservice::ObLogHandler *log_handler_; diff --git a/src/storage/tablet/ob_tablet_create_sstable_param.cpp b/src/storage/tablet/ob_tablet_create_sstable_param.cpp index 1dac53667..d8d8cd16d 100644 --- a/src/storage/tablet/ob_tablet_create_sstable_param.cpp +++ b/src/storage/tablet/ob_tablet_create_sstable_param.cpp @@ -75,7 +75,8 @@ ObTabletCreateSSTableParam::ObTabletCreateSSTableParam() nested_offset_(0), nested_size_(0), data_block_ids_(), - other_block_ids_() + other_block_ids_(), + uncommitted_tx_id_(0) { MEMSET(encrypt_key_, 0, share::OB_MAX_TABLESPACE_ENCRYPT_KEY_LENGTH); } @@ -230,6 +231,11 @@ int ObTabletCreateSSTableParam::init_for_merge(const compaction::ObBasicTabletMe } else { table_key.scn_range_ = static_param.scn_range_; } + if (is_minor_merge_type(static_param.get_merge_type()) && res.contain_uncommitted_row_) { + uncommitted_tx_id_ = static_param.tx_id_; + } else { + uncommitted_tx_id_ = 0; + } table_key_ = table_key; if (ObITable::TableType::COLUMN_ORIENTED_SSTABLE == table_key.table_type_ || diff --git a/src/storage/tablet/ob_tablet_create_sstable_param.h b/src/storage/tablet/ob_tablet_create_sstable_param.h index fc969985b..0b7714c89 100644 --- a/src/storage/tablet/ob_tablet_create_sstable_param.h +++ b/src/storage/tablet/ob_tablet_create_sstable_param.h @@ -120,7 +120,8 @@ public: K_(recycle_version), K_(nested_offset), K_(nested_size), - KPHEX_(encrypt_key, sizeof(encrypt_key_))); + KPHEX_(encrypt_key, sizeof(encrypt_key_)), + K_(uncommitted_tx_id)); private: static const int64_t DEFAULT_MACRO_BLOCK_CNT = 64; int inner_init_with_merge_res(const blocksstable::ObSSTableMergeRes &res); @@ -170,6 +171,7 @@ public: char encrypt_key_[share::OB_MAX_TABLESPACE_ENCRYPT_KEY_LENGTH]; common::ObSEArray data_block_ids_; common::ObSEArray other_block_ids_; + int64_t uncommitted_tx_id_; }; } // namespace storage diff --git a/src/storage/tablet/ob_tablet_memtable_mgr.cpp b/src/storage/tablet/ob_tablet_memtable_mgr.cpp index adf75a6cf..87a72d310 100644 --- a/src/storage/tablet/ob_tablet_memtable_mgr.cpp +++ b/src/storage/tablet/ob_tablet_memtable_mgr.cpp @@ -17,6 +17,7 @@ #include "storage/meta_mem/ob_tenant_meta_mem_mgr.h" #include "storage/ls/ob_freezer.h" #include "storage/tx_storage/ob_ls_service.h" +#include "storage/ddl/ob_tablet_ddl_kv.h" namespace oceanbase { @@ -58,15 +59,15 @@ void ObTabletMemtableMgr::destroy() STORAGE_LOG(DEBUG, "destroy tablet memtable mgr", KP(this), KPC(this)); MemMgrWLockGuard lock_guard(lock_); // release memtable - memtable::ObIMemtable *imemtable = nullptr; + ObIMemtable *imemtable = nullptr; int ret = OB_SUCCESS; for (int64_t pos = memtable_head_; pos < memtable_tail_; ++pos) { imemtable = tables_[get_memtable_idx(pos)]; if (OB_ISNULL(imemtable)) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "memtable is nullptr", K(ret), KP(imemtable), K(pos)); - } else if (imemtable->is_data_memtable()) { - memtable::ObMemtable *memtable = static_cast(imemtable); + } else if (imemtable->is_tablet_memtable()) { + ObITabletMemtable *memtable = static_cast(imemtable); memtable->remove_from_data_checkpoint(); memtable->set_frozen(); } @@ -82,11 +83,6 @@ void ObTabletMemtableMgr::destroy() is_inited_ = false; } -void ObTabletMemtableMgr::reset() -{ - destroy(); -} - int ObTabletMemtableMgr::init(const common::ObTabletID &tablet_id, const ObLSID &ls_id, ObFreezer *freezer, @@ -118,7 +114,6 @@ int ObTabletMemtableMgr::init(const common::ObTabletID &tablet_id, } else { tablet_id_ = tablet_id; t3m_ = t3m; - table_type_ = ObITable::TableType::DATA_MEMTABLE; freezer_ = freezer; retry_times_ = 0; is_inited_ = true; @@ -151,23 +146,9 @@ int ObTabletMemtableMgr::init_storage_recorder( return ret; } -int ObTabletMemtableMgr::reset_storage_recorder() -{ - int ret = OB_SUCCESS; - if (OB_UNLIKELY(!schema_recorder_.is_inited() || !medium_info_recorder_.is_inited())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("schema recorder or medium recorder is not init", K(ret), K_(schema_recorder), - K_(medium_info_recorder)); - } else { - schema_recorder_.reset(); - medium_info_recorder_.reset(); - } - return ret; -} - -inline int ObTabletMemtableMgr::try_resolve_boundary_on_create_memtable_for_leader_( - memtable::ObMemtable *last_frozen_memtable, - memtable::ObMemtable *new_memtable) +int ObTabletMemtableMgr::try_resolve_boundary_on_create_memtable_for_leader_( + ObITabletMemtable *last_frozen_tablet_memtable, + ObITabletMemtable *new_tablet_memtable) { int ret = OB_SUCCESS; bool double_check = false; @@ -175,43 +156,53 @@ inline int ObTabletMemtableMgr::try_resolve_boundary_on_create_memtable_for_lead int64_t write_ref = 0; int64_t unsubmitted_cnt = 0; do { - write_ref = last_frozen_memtable->get_write_ref(); - unsubmitted_cnt = last_frozen_memtable->get_unsubmitted_cnt(); + write_ref = last_frozen_tablet_memtable->get_write_ref(); + unsubmitted_cnt = last_frozen_tablet_memtable->get_unsubmitted_cnt(); if (0 == write_ref && 0 == unsubmitted_cnt) { share::SCN max_decided_scn; if (OB_FAIL(freezer_->get_max_consequent_callbacked_scn(max_decided_scn))) { TRANS_LOG(WARN, "get max decided scn fail", K(ret), K(freezer_->get_ls_id())); - } else if (max_decided_scn >= last_frozen_memtable->get_end_scn()) { + } else if (max_decided_scn >= last_frozen_tablet_memtable->get_end_scn()) { // logstream's continous apply has pass frozen memtable's right boundary can_resolve = true; } } if (!can_resolve && !double_check) { - last_frozen_memtable->set_resolved_active_memtable_left_boundary(false); + last_frozen_tablet_memtable->set_resolved_active_memtable_left_boundary(false); } double_check = !double_check; } while (!can_resolve && double_check); - if (write_ref > 0) { // NB: for the leader, if the write ref on the frozen memtable is greater // than 0, we cannot create a new memtable. Otherwise we may finish the // write on the new memtable before finishing the write on the frozen // memtable and cause the writes and callbacks on memtable_ctx out of order. ret = OB_EAGAIN; - TRANS_LOG(INFO, "last frozen's write flag is not 0 during create new memtable", - KPC(last_frozen_memtable), KPC(new_memtable)); + TRANS_LOG(INFO, + "last frozen's write flag is not 0 during create new memtable", + KPC(last_frozen_tablet_memtable), + KPC(new_tablet_memtable)); } else if (can_resolve) { - last_frozen_memtable->set_resolved_active_memtable_left_boundary(true); - last_frozen_memtable->resolve_right_boundary(); - TRANS_LOG(INFO, "[resolve_right_boundary] in create_memtable on leader", KPC(last_frozen_memtable)); - if (new_memtable != last_frozen_memtable) { - const SCN &new_start_scn = MAX(last_frozen_memtable->get_end_scn(), last_frozen_memtable->get_migration_clog_checkpoint_scn()); - new_memtable->resolve_left_boundary(new_start_scn); + SCN new_start_scn; + last_frozen_tablet_memtable->resolve_right_boundary(); + last_frozen_tablet_memtable->set_resolved_active_memtable_left_boundary(true); + if (new_tablet_memtable != last_frozen_tablet_memtable) { + new_start_scn = MAX(last_frozen_tablet_memtable->get_end_scn(), + last_frozen_tablet_memtable->get_migration_clog_checkpoint_scn()); + int tmp_ret = new_tablet_memtable->resolve_left_boundary(new_start_scn); + if (OB_SUCCESS != tmp_ret) { + TRANS_LOG(ERROR, "resolve left boundary failed", KR(tmp_ret), K(new_start_scn), KPC(new_tablet_memtable)); + } } + TRANS_LOG(INFO, + "[resolve_right_boundary] in create_memtable on leader", + K(new_start_scn), + KPC(last_frozen_tablet_memtable), + KPC(new_tablet_memtable)); } else if (unsubmitted_cnt > 0) { - new_memtable->set_logging_blocked(); - TRANS_LOG(INFO, "set new memtable logging blocked", KPC(last_frozen_memtable), KPC(new_memtable)); + new_tablet_memtable->set_logging_blocked(); + TRANS_LOG(INFO, "set new memtable logging blocked", KPC(last_frozen_tablet_memtable), KPC(new_tablet_memtable)); } return ret; } @@ -219,27 +210,16 @@ inline int ObTabletMemtableMgr::try_resolve_boundary_on_create_memtable_for_lead // There are two cases: // 1. create the first memtable for tablet // 2. create the new memtable after freezing the old memtable -int ObTabletMemtableMgr::create_memtable(const SCN clog_checkpoint_scn, - const int64_t schema_version, - const SCN new_clog_checkpoint_scn, - const bool for_replay) +int ObTabletMemtableMgr::create_memtable(const CreateMemtableArg &arg) { - ObTimeGuard time_guard("ObTabletMemtableMgr::create_memtable", 10 * 1000); // Write lock + ObTimeGuard time_guard("ObTabletMemtableMgr::create_memtable", 10 * 1000); MemMgrWLockGuard lock_guard(lock_); time_guard.click("lock"); int ret = OB_SUCCESS; - ObTableHandleV2 memtable_handle; - const bool has_memtable = has_memtable_(); + ObLSID ls_id; const uint32_t logstream_freeze_clock = freezer_->get_freeze_clock(); - memtable::ObMemtable *active_memtable = nullptr; - uint32_t memtable_freeze_clock = UINT32_MAX; - share::ObLSID ls_id; - int64_t memtable_count = get_memtable_count_(); - if (has_memtable && OB_NOT_NULL(active_memtable = get_active_memtable_())) { - memtable_freeze_clock = active_memtable->get_freeze_clock(); - } if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; @@ -248,116 +228,205 @@ int ObTabletMemtableMgr::create_memtable(const SCN clog_checkpoint_scn, ret = OB_ERR_UNEXPECTED; LOG_WARN("ls is null", K(ret)); } else if (FALSE_IT(ls_id = ls_->get_ls_id())) { - } else if (logstream_freeze_clock == memtable_freeze_clock) { - // new memtable has already existed - ret = OB_ENTRY_EXIST; - } else if (memtable_count >= MAX_MEMSTORE_CNT) { + } else if (has_memtable_() && OB_FAIL(check_boundary_memtable_(logstream_freeze_clock))) { + STORAGE_LOG(DEBUG, "check boundary memtable failed", KR(ret), K(arg), K(ls_id)); + } else if (get_memtable_count_() >= MAX_MEMSTORE_CNT) { ret = OB_MINOR_FREEZE_NOT_ALLOW; ob_usleep(1 * 1000); - if ((++retry_times_ % (60 * 1000)) == 0) { // 1 min + if ((++retry_times_ % (60 * 1000)) == 0) { // 1 min ObTableHandleV2 first_frozen_memtable; get_first_frozen_memtable_(first_frozen_memtable); - LOG_ERROR("cannot create more memtable", K(ret), K(ls_id), K(tablet_id_), K(MAX_MEMSTORE_CNT), + LOG_ERROR("cannot create more memtable", + K(ret), + K(ls_id), + K(tablet_id_), + K(MAX_MEMSTORE_CNT), K(get_memtable_count_()), KPC(first_frozen_memtable.get_table())); } - } else if (for_replay && clog_checkpoint_scn != new_clog_checkpoint_scn) { + } else if (arg.for_replay_ && arg.clog_checkpoint_scn_ != arg.new_clog_checkpoint_scn_) { ret = OB_EAGAIN; - LOG_INFO("clog_checkpoint_scn changed, need retry to replay", K(ls_id), K(tablet_id_), K(clog_checkpoint_scn), K(new_clog_checkpoint_scn)); - } else { - ObITable::TableKey table_key; - table_key.table_type_ = ObITable::DATA_MEMTABLE; - table_key.tablet_id_ = tablet_id_; - table_key.scn_range_.start_scn_ = clog_checkpoint_scn; - table_key.scn_range_.end_scn_.set_max(); - memtable::ObMemtable *memtable = NULL; - ObLSHandle ls_handle; - retry_times_ = 0; - - if (OB_FAIL(t3m_->acquire_memtable(memtable_handle))) { - LOG_WARN("failed to create memtable", K(ret), K(ls_id), K(tablet_id_)); - } else if (FALSE_IT(time_guard.click("acquire_memtable"))) { - } else if (OB_ISNULL(memtable = static_cast(memtable_handle.get_table()))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle)); - } else if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id, ls_handle, ObLSGetMod::DATA_MEMTABLE_MOD))) { - LOG_WARN("failed to get log stream", K(ret), K(ls_id), K(tablet_id_)); - } else if (OB_UNLIKELY(!ls_handle.is_valid())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected error, invalid ls handle", K(ret), K(ls_handle), K(ls_id), K(tablet_id_)); - } else if (OB_FAIL(memtable->init(table_key, - ls_handle, - freezer_, - this, - schema_version, - logstream_freeze_clock))) { - LOG_WARN("failed to init memtable", K(ret), K(ls_id), K(table_key), KP(freezer_), KP(this), - K(schema_version), K(logstream_freeze_clock)); - } else { - ObTableHandleV2 last_frozen_memtable_handle; - memtable::ObMemtable *last_frozen_memtable = nullptr; - if (OB_FAIL(get_last_frozen_memtable_(last_frozen_memtable_handle))) { - if (OB_ENTRY_NOT_EXIST != ret) { - LOG_WARN("fail to get last frozen memtable", K(ret)); - } else { - ret = OB_SUCCESS; - } - } else if (OB_FAIL(last_frozen_memtable_handle.get_data_memtable(last_frozen_memtable))) { - LOG_WARN("fail to get memtable", K(ret)); - } - - if (OB_FAIL(ret)) { - } else if (OB_NOT_NULL(last_frozen_memtable)) { - // for follower, must decide the boundary of frozen memtable - if (for_replay) { - last_frozen_memtable->resolve_right_boundary(); - TRANS_LOG(INFO, "[resolve_right_boundary] in create_memtable on replay", KPC(last_frozen_memtable)); - if (memtable != last_frozen_memtable) { - const SCN start_scn = MAX(last_frozen_memtable->get_end_scn(), - last_frozen_memtable->get_migration_clog_checkpoint_scn()); - memtable->resolve_left_boundary(start_scn); - } - } - // for leader, decide the right boundary of frozen memtable - else if (OB_FAIL(try_resolve_boundary_on_create_memtable_for_leader_(last_frozen_memtable, memtable))) { - TRANS_LOG(WARN, "try resolve boundary fail", K(ret)); - } - } else { - // there is no frozen memtable and new sstable will not be generated, - // meaning that clog_checkpoint_scn will not be updated now, - // so get newest clog_checkpoint_scn to set left boundary - memtable->resolve_left_boundary(new_clog_checkpoint_scn); - } - - time_guard.click("init memtable"); - if (OB_SUCC(ret)) { - if (MAX_MEMSTORE_CNT - 1 == memtable_count) { - // if the new memtable is last one in memtable_array - // not allow it to be freezed - // otherwise the number of memtables will be out of limit - memtable->set_allow_freeze(false); - FLOG_INFO("not allow memtable to be freezed", K(memtable_count), K(MAX_MEMSTORE_CNT), KPC(memtable)); - } - if (OB_FAIL(add_memtable_(memtable_handle))) { - LOG_WARN("failed to add memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle)); - } else if (FALSE_IT(time_guard.click("add memtable"))) { - } else if (OB_FAIL(memtable->add_to_data_checkpoint(freezer_->get_ls_data_checkpoint()))) { - LOG_WARN("add to data_checkpoint failed", K(ret), K(ls_id), KPC(memtable)); - clean_tail_memtable_(); - } else if (FALSE_IT(time_guard.click("add to data_checkpoint"))) { - } else { - LOG_INFO("succeed to create memtable", K(ret), K(ls_id), KPC(memtable), KPC(this)); - } - } - } + LOG_INFO("clog_checkpoint_scn changed, need retry to replay", K(ls_id), K(tablet_id_), K(arg)); + } else if (OB_FAIL(create_memtable_(arg, logstream_freeze_clock, time_guard))) { + STORAGE_LOG(WARN, "create memtable failed", KR(ret), K(ls_id)); } return ret; } -uint32_t ObTabletMemtableMgr::get_ls_freeze_clock() +int ObTabletMemtableMgr::check_boundary_memtable_(const uint32_t logstream_freeze_clock) { - return freezer_->get_freeze_clock(); + int ret = OB_SUCCESS; + ObTableHandleV2 table_handle; + ObITabletMemtable *tablet_memtable = nullptr; + if (OB_FAIL(get_boundary_memtable_(table_handle))) { + STORAGE_LOG(WARN, "get boundary memtable failed", KR(ret), K(table_handle)); + } else if (OB_FAIL(table_handle.get_tablet_memtable(tablet_memtable))) { + STORAGE_LOG(WARN, "get boundary memtable failed", KR(ret), K(table_handle)); + } else if (tablet_memtable->is_direct_load_memtable()) { + if (tablet_memtable->get_end_scn().is_max()) { + PAUSE(); + // if end_scn of direct load memtable has not decided, return OB_ENTRY_EXIST and Tablet will reset it to + // OB_SUCCESS. Then refresh_and_protect_table(refresh_and_protect_memtable) in StorageTableGuard will retry create + // memtable + ret = OB_ENTRY_EXIST; + } + } else if (tablet_memtable->is_data_memtable()) { + if (tablet_memtable->is_active_memtable() && tablet_memtable->get_freeze_clock() == logstream_freeze_clock) { + ret = OB_ENTRY_EXIST; + } + } else { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "Invalid table type", KR(ret), KPC(tablet_memtable)); + } + + if (OB_FAIL(ret)) { + STORAGE_LOG(DEBUG, "check boundary memtable failed", KR(ret), K(logstream_freeze_clock), KPC(tablet_memtable)); + } + return ret; +} + +int ObTabletMemtableMgr::create_memtable_(const CreateMemtableArg &arg, + const uint32_t logstream_freeze_clock, + ObTimeGuard &tg) +{ + int ret = OB_SUCCESS; + + ObTableHandleV2 memtable_handle; + ObITable::TableKey table_key; + const ObLSID ls_id = ls_->get_ls_id(); + table_key.table_type_ = arg.for_inc_direct_load_ ? ObITable::DIRECT_LOAD_MEMTABLE : ObITable::DATA_MEMTABLE; + table_key.tablet_id_ = tablet_id_; + table_key.scn_range_.start_scn_ = arg.clog_checkpoint_scn_; + table_key.scn_range_.end_scn_.set_max(); + ObITabletMemtable *new_tablet_memtable = NULL; + ObLSHandle ls_handle; + retry_times_ = 0; + + if (OB_FAIL(acquire_tablet_memtable_(arg.for_inc_direct_load_, memtable_handle))) { + LOG_WARN("failed to create memtable", K(ret), K(ls_id), K(tablet_id_)); + } else if (FALSE_IT(tg.click("acquire_memtable"))) { + } else if (OB_ISNULL(new_tablet_memtable = static_cast(memtable_handle.get_table()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle)); + } else if (OB_FAIL(MTL(ObLSService *)->get_ls(ls_id, ls_handle, ObLSGetMod::DATA_MEMTABLE_MOD))) { + LOG_WARN("failed to get log stream", K(ret), K(ls_id), K(tablet_id_)); + } else if (OB_UNLIKELY(!ls_handle.is_valid())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error, invalid ls handle", K(ret), K(ls_handle), K(ls_id), K(tablet_id_)); + } else if (OB_FAIL(new_tablet_memtable->init( + table_key, ls_handle, freezer_, this, arg.schema_version_, logstream_freeze_clock))) { + LOG_WARN("failed to init memtable", + K(ret), + K(ls_id), + K(table_key), + KP(freezer_), + KP(this), + K(arg), + K(logstream_freeze_clock)); + } else if (OB_FAIL(resolve_boundary_(new_tablet_memtable, arg))) { + LOG_WARN("failed to add memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle)); + } else if (FALSE_IT(tg.click("init memtable"))) { + } else if (FALSE_IT(block_freeze_if_memstore_full_(new_tablet_memtable))) { + } else if (OB_FAIL(add_memtable_(memtable_handle))) { + LOG_WARN("failed to add memtable", K(ret), K(ls_id), K(tablet_id_), K(memtable_handle)); + } else if (FALSE_IT(tg.click("add memtable"))) { + } else if (OB_FAIL(new_tablet_memtable->add_to_data_checkpoint(freezer_->get_ls_data_checkpoint()))) { + LOG_WARN("add to data_checkpoint failed", K(ret), K(ls_id), KPC(new_tablet_memtable)); + clean_tail_memtable_(); + } else if (FALSE_IT(tg.click("add to data_checkpoint"))) { + } else { + LOG_INFO("succeed to create memtable", K(arg), K(ret), K(ls_id), KPC(new_tablet_memtable), KPC(this)); + } + + return ret; +} + +int ObTabletMemtableMgr::resolve_boundary_(ObITabletMemtable *new_tablet_memtable, const CreateMemtableArg &arg) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + ObTableHandleV2 last_frozen_memtable_handle; + ObITabletMemtable *last_frozen_tablet_memtable = nullptr; + // step 1 : get frozen memtable if exist + if (OB_FAIL(get_last_frozen_memtable_(last_frozen_memtable_handle))) { + if (OB_ENTRY_NOT_EXIST != ret) { + LOG_WARN("fail to get last frozen memtable", K(ret)); + } else { + ret = OB_SUCCESS; + } + } else if (OB_FAIL(last_frozen_memtable_handle.get_tablet_memtable(last_frozen_tablet_memtable))) { + LOG_WARN("fail to get memtable", K(ret)); + } + + // step 2 : if frozen memtable exist, try deciding end_scn for frozen memtable + if (OB_FAIL(ret)) { + } else if (OB_NOT_NULL(last_frozen_tablet_memtable)) { + if (last_frozen_tablet_memtable->is_data_memtable()) { + (void)resolve_data_memtable_boundary_(last_frozen_tablet_memtable, new_tablet_memtable, arg); + } else if (last_frozen_tablet_memtable->is_direct_load_memtable()) { + (void)resolve_direct_load_memtable_boundary_(last_frozen_tablet_memtable, new_tablet_memtable, arg); + } else { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "Invalid table type", KR(ret), KPC(last_frozen_tablet_memtable)); + } + } else { + // use new clog_checkpoint_scn as start_scn for new memtable + (void)new_tablet_memtable->resolve_left_boundary(arg.new_clog_checkpoint_scn_); + } + + return ret; +} + +void ObTabletMemtableMgr::resolve_data_memtable_boundary_(ObITabletMemtable *frozen_tablet_memtable, + ObITabletMemtable *new_tablet_memtable, + const CreateMemtableArg &arg) +{ + int ret = OB_SUCCESS; + if (arg.for_replay_) { + SCN new_memtable_start_scn; + frozen_tablet_memtable->resolve_right_boundary(); + if (new_tablet_memtable != frozen_tablet_memtable) { + new_memtable_start_scn = + MAX(frozen_tablet_memtable->get_end_scn(), frozen_tablet_memtable->get_migration_clog_checkpoint_scn()); + (void)new_tablet_memtable->resolve_left_boundary(new_memtable_start_scn); + } + TRANS_LOG(INFO, "[resolve_right_boundary] in create_memtable on replay", KPC(frozen_tablet_memtable)); + } + // for leader, decide the right boundary of frozen memtable + else if (OB_FAIL(try_resolve_boundary_on_create_memtable_for_leader_(frozen_tablet_memtable, new_tablet_memtable))) { + TRANS_LOG(WARN, "try resolve boundary fail", K(ret)); + } +} + +void ObTabletMemtableMgr::resolve_direct_load_memtable_boundary_(ObITabletMemtable *frozen_tablet_memtable, + ObITabletMemtable *active_tablet_memtable, + const CreateMemtableArg &arg) +{ + int64_t start_ts = ObClockGenerator::getClock(); + + SCN new_memtable_start_scn; + if (frozen_tablet_memtable->get_end_scn().is_max()) { + int ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "frozen direct load memtable must have a valid end_scn", KPC(frozen_tablet_memtable)); + } else if (active_tablet_memtable != frozen_tablet_memtable) { + new_memtable_start_scn = + MAX(frozen_tablet_memtable->get_end_scn(), frozen_tablet_memtable->get_migration_clog_checkpoint_scn()); + (void)active_tablet_memtable->resolve_left_boundary(new_memtable_start_scn); + (void)frozen_tablet_memtable->set_resolved_active_memtable_left_boundary(true); + } +} + +void ObTabletMemtableMgr::block_freeze_if_memstore_full_(ObITabletMemtable *new_tablet_memtable) +{ + if (MAX_MEMSTORE_CNT - 1 == get_memtable_count_()) { + // if the new memtable is last one in memtable_array + // not allow it to be freezed + // otherwise the number of memtables will be out of limit + new_tablet_memtable->set_allow_freeze(false); + FLOG_INFO( + "not allow memtable to be freezed", K(get_memtable_count_()), K(MAX_MEMSTORE_CNT), KPC(new_tablet_memtable)); + } } bool ObTabletMemtableMgr::has_active_memtable() @@ -376,33 +445,33 @@ bool ObTabletMemtableMgr::has_active_memtable() return bool_ret; } -int64_t ObTabletMemtableMgr::get_memtable_count() const -{ - MemMgrRLockGuard lock_guard(lock_); - return get_memtable_count_(); -} - int ObTabletMemtableMgr::get_boundary_memtable(ObTableHandleV2 &handle) { int ret = OB_SUCCESS; MemMgrRLockGuard lock_guard(lock_); - memtable::ObIMemtable *memtable = nullptr; handle.reset(); + ret = get_boundary_memtable_(handle); + return ret; +} +int ObTabletMemtableMgr::get_boundary_memtable_(ObTableHandleV2 &handle) +{ + int ret = OB_SUCCESS; + ObITabletMemtable *tablet_memtable = nullptr; if (OB_UNLIKELY(get_memtable_count_() == 0)) { ret = OB_ENTRY_NOT_EXIST; } else if (memtable_tail_ > memtable_head_) { if (OB_FAIL(get_ith_memtable(memtable_tail_ - 1, handle))) { STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(memtable_tail_)); - } else if (OB_FAIL(handle.get_memtable(memtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { handle.reset(); LOG_WARN("there is no boundary memtable", K(ret)); } } - return ret; } + int ObTabletMemtableMgr::get_active_memtable(ObTableHandleV2 &handle) const { int ret = OB_SUCCESS; @@ -427,12 +496,12 @@ int ObTabletMemtableMgr::get_active_memtable_(ObTableHandleV2 &handle) const ret = OB_ENTRY_NOT_EXIST; LOG_DEBUG("no memtable exists", K(ret)); } else if (memtable_tail_ > memtable_head_) { - memtable::ObMemtable *memtable = nullptr; + ObITabletMemtable *tablet_memtable = nullptr; if (OB_FAIL(get_ith_memtable(memtable_tail_ - 1, handle))) { STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(memtable_tail_)); - } else if (OB_FAIL(handle.get_data_memtable(memtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { LOG_WARN("fail to get memtable", K(ret)); - } else if (!memtable->is_active_memtable()) { + } else if (!tablet_memtable->is_active_memtable()) { handle.reset(); ret = OB_ENTRY_NOT_EXIST; } @@ -440,7 +509,7 @@ int ObTabletMemtableMgr::get_active_memtable_(ObTableHandleV2 &handle) const return ret; } -int ObTabletMemtableMgr::get_last_frozen_memtable(ObTableHandleV2 &handle) const +int ObTabletMemtableMgr::get_last_frozen_memtable(ObTableHandleV2 &handle) { int ret = OB_SUCCESS; MemMgrRLockGuard lock_guard(lock_); @@ -457,7 +526,7 @@ int ObTabletMemtableMgr::get_last_frozen_memtable(ObTableHandleV2 &handle) const return ret; } -int ObTabletMemtableMgr::get_last_frozen_memtable_(ObTableHandleV2 &handle) const +int ObTabletMemtableMgr::get_last_frozen_memtable_(ObTableHandleV2 &handle) { int ret = OB_SUCCESS; handle.reset(); @@ -467,18 +536,18 @@ int ObTabletMemtableMgr::get_last_frozen_memtable_(ObTableHandleV2 &handle) cons } else if (memtable_tail_ > memtable_head_) { for (int64_t i = memtable_tail_ - 1; OB_SUCC(ret) && i >= memtable_head_; --i) { ObTableHandleV2 m_handle; - const ObMemtable *memtable = nullptr; + ObITabletMemtable *tablet_memtable = nullptr; if (OB_FAIL(get_ith_memtable(i, m_handle))) { STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i)); } else if (OB_UNLIKELY(!m_handle.is_valid())) { ret = OB_ERR_SYS; LOG_ERROR("memtable handle is invalid", K(ret), K(m_handle)); - } else if (OB_FAIL(m_handle.get_data_memtable(memtable))) { + } else if (OB_FAIL(m_handle.get_tablet_memtable(tablet_memtable))) { LOG_WARN("fail to get memtable", K(ret), K(m_handle)); - } else if (OB_ISNULL(memtable)) { + } else if (OB_ISNULL(tablet_memtable)) { ret = OB_ERR_SYS; LOG_ERROR("memtable must not null", K(ret), K(m_handle)); - } else if (memtable->is_frozen_memtable()) { + } else if (tablet_memtable->is_frozen_memtable()) { handle = m_handle; break; } @@ -493,41 +562,11 @@ int ObTabletMemtableMgr::get_last_frozen_memtable_(ObTableHandleV2 &handle) cons return ret; } -int ObTabletMemtableMgr::resolve_left_boundary_for_active_memtable(memtable::ObIMemtable *memtable, - SCN start_scn, - SCN snapshot_scn) +int ObTabletMemtableMgr::resolve_left_boundary_for_active_memtable(ObITabletMemtable *tablet_memtable, + const SCN start_scn) { ObTableHandleV2 handle; - ObIMemtable *active_memtable = nullptr; - int ret = OB_SUCCESS; - - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - LOG_WARN("not inited", K(ret), K_(is_inited)); - } else if (OB_FAIL(get_active_memtable(handle))) { - if (OB_ENTRY_NOT_EXIST != ret) { - LOG_WARN( "fail to get active memtable", K(ret)); - } - } else if (OB_FAIL(handle.get_memtable(active_memtable))) { - LOG_WARN("fail to get active memtable", K(ret)); - } else { - // set the start_scn of the new memtable - static_cast(active_memtable)->resolve_left_boundary(start_scn); - } - if (OB_ENTRY_NOT_EXIST== ret) { - ret = OB_SUCCESS; - } - if (OB_SUCC(ret)) { - static_cast(memtable)->set_resolved_active_memtable_left_boundary(true); - } - - return ret; -} - -int ObTabletMemtableMgr::unset_logging_blocked_for_active_memtable(memtable::ObIMemtable *memtable) -{ - ObTableHandleV2 handle; - ObIMemtable *active_memtable = nullptr; + ObITabletMemtable *active_tablet_memtable = nullptr; int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_inited_)) { @@ -537,17 +576,49 @@ int ObTabletMemtableMgr::unset_logging_blocked_for_active_memtable(memtable::ObI if (OB_ENTRY_NOT_EXIST != ret) { LOG_WARN("fail to get active memtable", K(ret)); } - } else if (OB_FAIL(handle.get_memtable(active_memtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(active_tablet_memtable))) { + LOG_WARN("fail to get active memtable", K(ret)); + } else { + // set the start_scn of the new memtable + int tmp_ret = active_tablet_memtable->resolve_left_boundary(start_scn); + if (OB_SUCCESS != tmp_ret) { + TRANS_LOG(ERROR, "resolve left boundary failed", K(start_scn), KPC(active_tablet_memtable), KPC(tablet_memtable)); + } + } + if (OB_ENTRY_NOT_EXIST == ret) { + ret = OB_SUCCESS; + } + if (OB_SUCC(ret)) { + tablet_memtable->set_resolved_active_memtable_left_boundary(true); + } + + return ret; +} + +int ObTabletMemtableMgr::unset_logging_blocked_for_active_memtable(ObITabletMemtable *tablet_memtable) +{ + ObTableHandleV2 handle; + ObITabletMemtable *active_tablet_memtable = nullptr; + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(!is_inited_)) { + ret = OB_NOT_INIT; + LOG_WARN("not inited", K(ret), K_(is_inited)); + } else if (OB_FAIL(get_active_memtable(handle))) { + if (OB_ENTRY_NOT_EXIST != ret) { + LOG_WARN("fail to get active memtable", K(ret)); + } + } else if (OB_FAIL(handle.get_tablet_memtable(active_tablet_memtable))) { LOG_WARN("fail to get active memtable", K(ret)); } else { // allow the new memtable to submit log - static_cast(active_memtable)->unset_logging_blocked(); + active_tablet_memtable->unset_logging_blocked(); } if (OB_ENTRY_NOT_EXIST== ret) { ret = OB_SUCCESS; } if (OB_SUCC(ret)) { - static_cast(memtable)->unset_active_memtable_logging_blocked(); + tablet_memtable->unset_active_memtable_logging_blocked(); } return ret; @@ -558,8 +629,7 @@ int ObTabletMemtableMgr::set_is_tablet_freeze_for_active_memtable( const int64_t trace_id) { handle.reset(); - memtable::ObIMemtable *active_memtable = nullptr; - memtable::ObMemtable *memtable = nullptr; + ObITabletMemtable *active_tablet_memtable = nullptr; int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_inited_)) { @@ -567,32 +637,31 @@ int ObTabletMemtableMgr::set_is_tablet_freeze_for_active_memtable( LOG_WARN("not inited", K(ret), K_(is_inited)); } else if (OB_FAIL(get_active_memtable(handle))) { LOG_DEBUG("fail to get active memtable", K(ret)); - } else if (OB_FAIL(handle.get_memtable(active_memtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(active_tablet_memtable))) { LOG_WARN("fail to get active memtable", K(ret)); if (ret == OB_NOT_INIT) { ret = OB_ENTRY_NOT_EXIST; LOG_WARN("active memtable is null", K(ret)); } - } else if (FALSE_IT(memtable = static_cast(active_memtable))) { - } else if (memtable->allow_freeze()) { - memtable->set_is_tablet_freeze(); + } else if (active_tablet_memtable->allow_freeze()) { + active_tablet_memtable->set_is_tablet_freeze(); if (checkpoint::INVALID_TRACE_ID != trace_id) { - memtable->set_trace_id(trace_id); + active_tablet_memtable->set_trace_id(trace_id); } } else { handle.reset(); - ret = OB_ENTRY_NOT_EXIST; - TRANS_LOG(INFO, "not set is_tablet_freeze because the memtable cannot be freezed", KPC(memtable)); + ret = OB_MINOR_FREEZE_NOT_ALLOW; + TRANS_LOG(INFO, "not set is_tablet_freeze because the memtable cannot be freezed", KPC(active_tablet_memtable)); } + return ret; } -int ObTabletMemtableMgr::get_memtable_for_replay(SCN replay_scn, - ObTableHandleV2 &handle) +int ObTabletMemtableMgr::get_memtable_for_replay(SCN replay_scn, ObTableHandleV2 &handle) { int ret = OB_SUCCESS; - ObMemtable *memtable = nullptr; + ObITabletMemtable *tablet_memtable = nullptr; handle.reset(); if (OB_UNLIKELY(!is_inited_)) { @@ -608,17 +677,18 @@ int ObTabletMemtableMgr::get_memtable_for_replay(SCN replay_scn, for (i = memtable_tail_ - 1; OB_SUCC(ret) && i >= memtable_head_; --i) { if (OB_FAIL(get_ith_memtable(i, handle))) { STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i)); - } else if (OB_FAIL(handle.get_data_memtable(memtable))) { + } else if (OB_FAIL(handle.get_tablet_memtable(tablet_memtable))) { handle.reset(); LOG_WARN("fail to get data memtable", K(ret)); } else { - if (replay_scn > memtable->get_start_scn() && replay_scn <= memtable->get_end_scn()) { + if (replay_scn > tablet_memtable->get_start_scn() && replay_scn <= tablet_memtable->get_end_scn()) { break; } else { handle.reset(); } } } + if (OB_SUCC(ret) && !handle.is_valid() && i < memtable_head_) { SCN clog_checkpoint_scn; if (OB_FAIL(get_newest_clog_checkpoint_scn(clog_checkpoint_scn))) { @@ -635,28 +705,6 @@ int ObTabletMemtableMgr::get_memtable_for_replay(SCN replay_scn, return ret; } -int ObTabletMemtableMgr::get_memtables( - ObTableHdlArray &handle, - const bool reset_handle, - const int64_t start_point, - const bool include_active_memtable) -{ - int ret = OB_SUCCESS; - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - LOG_WARN("not inited", K(ret), K_(is_inited)); - } else { - MemMgrRLockGuard lock_guard(lock_); - if (reset_handle) { - handle.reset(); - } - if (OB_FAIL(get_memtables_(handle, start_point, include_active_memtable))) { - LOG_WARN("fail to get memtables", K(ret), K(start_point), K(include_active_memtable)); - } - } - return ret; -} - int ObTabletMemtableMgr::get_memtables_nolock(ObTableHdlArray &handle) { int ret = OB_SUCCESS; @@ -685,12 +733,12 @@ int ObTabletMemtableMgr::get_all_memtables(ObTableHdlArray &handle) } DEF_REPORT_CHEKCPOINT_DIAGNOSE_INFO(UpdateReleaseTime, update_release_time) -int ObTabletMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable, +int ObTabletMemtableMgr::release_head_memtable_(ObIMemtable *imemtable, const bool force) { UNUSED(force); int ret = OB_SUCCESS; - memtable::ObMemtable *memtable = static_cast(imemtable); + ObITabletMemtable *memtable = static_cast(imemtable); if (OB_UNLIKELY(get_memtable_count_() <= 0)) { ret = OB_ERR_UNEXPECTED; @@ -702,7 +750,7 @@ int ObTabletMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable const int64_t idx = get_memtable_idx(memtable_head_); if (nullptr != tables_[idx] && memtable == tables_[idx]) { LOG_INFO("release head memtable", K(ret), K(ls_id), KPC(memtable)); - memtable::ObMtStat& mt_stat = memtable->get_mt_stat(); + ObMtStat& mt_stat = memtable->get_mt_stat(); if (0 == mt_stat.release_time_) { mt_stat.release_time_ = ObTimeUtility::current_time(); } else { @@ -713,11 +761,11 @@ int ObTabletMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable } memtable->remove_from_data_checkpoint(); memtable->set_is_flushed(); - memtable->set_freeze_state(ObMemtableFreezeState::RELEASED); + memtable->set_freeze_state(TabletMemtableFreezeState::RELEASED); memtable->set_frozen(); memtable->report_memtable_diagnose_info(UpdateReleaseTime()); release_head_memtable(); - memtable::ObMemtable *active_memtable = get_active_memtable_(); + ObITabletMemtable *active_memtable = get_active_memtable_(); if (OB_NOT_NULL(active_memtable) && !active_memtable->allow_freeze()) { active_memtable->set_allow_freeze(true); FLOG_INFO("allow active memtable to be freezed", K(ls_id), KPC(active_memtable)); @@ -730,10 +778,9 @@ int ObTabletMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable return ret; } -int ObTabletMemtableMgr::get_first_frozen_memtable(ObTableHandleV2 &handle) const +int ObTabletMemtableMgr::get_first_frozen_memtable(ObTableHandleV2 &handle) { int ret = OB_SUCCESS; - memtable::ObMemtable *memtable = NULL; MemMgrRLockGuard guard(lock_); if (OB_UNLIKELY(!is_inited_)) { @@ -748,12 +795,12 @@ int ObTabletMemtableMgr::get_first_frozen_memtable(ObTableHandleV2 &handle) cons return ret; } -memtable::ObMemtable *ObTabletMemtableMgr::get_active_memtable_() +ObITabletMemtable *ObTabletMemtableMgr::get_active_memtable_() { int ret = OB_SUCCESS; - memtable::ObMemtable *memtable = nullptr; + ObITabletMemtable *memtable = nullptr; if (memtable_tail_ > memtable_head_) { - memtable = static_cast(tables_[get_memtable_idx(memtable_tail_ - 1)]); + memtable = static_cast(tables_[get_memtable_idx(memtable_tail_ - 1)]); if (OB_ISNULL(memtable)) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "memtable is nullptr", K(ret), KP(memtable), K(memtable_tail_)); @@ -765,43 +812,27 @@ memtable::ObMemtable *ObTabletMemtableMgr::get_active_memtable_() return memtable; } -memtable::ObMemtable *ObTabletMemtableMgr::get_memtable_(const int64_t pos) const +ObITabletMemtable *ObTabletMemtableMgr::get_memtable_(const int64_t pos) const { int ret = OB_SUCCESS; - memtable::ObMemtable *memtable = nullptr; - memtable::ObMemtable *table = static_cast(tables_[get_memtable_idx(pos)]); + ObITabletMemtable *memtable = nullptr; + ObITabletMemtable *table = static_cast(tables_[get_memtable_idx(pos)]); if (OB_ISNULL(table)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("table is nullptr", K(ret), KP(table), K(pos)); - } else if (!table->is_data_memtable()) { + } else if (!table->is_tablet_memtable()) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("not data memtable", K(ret), K(pos), K(table->get_key())); } else { memtable = table; } - return const_cast(memtable); -} - -int64_t ObTabletMemtableMgr::get_unmerged_memtable_count_() const -{ - int64_t cnt = 0; - - for (int64_t i = memtable_head_; i < memtable_tail_; i++) { - ObMemtable *memtable = get_memtable_(i); - if (NULL == memtable) { - LOG_ERROR_RET(OB_ERR_UNEXPECTED, "memtable must not null"); - } else if (0 == memtable->get_minor_merged_time()) { - cnt++; - } - } - - return cnt; + return memtable; } void ObTabletMemtableMgr::clean_tail_memtable_() { if (memtable_tail_ > memtable_head_) { - ObMemtable *memtable = get_memtable_(memtable_tail_ - 1); + ObITabletMemtable *memtable = get_memtable_(memtable_tail_ - 1); if (OB_NOT_NULL(memtable)) { memtable->set_frozen(); } else { @@ -874,7 +905,7 @@ int ObTabletMemtableMgr::find_start_pos_(const int64_t start_point, int64_t &sta LOG_WARN("invalid start_point", K(ret), K(start_point)); } for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) { - ObMemtable *memtable = get_memtable_(i); + ObITabletMemtable *memtable = get_memtable_(i); if (OB_ISNULL(memtable)) { ret = OB_ERR_SYS; LOG_ERROR("memtable must not null", K(ret)); @@ -902,77 +933,19 @@ int64_t ObTabletMemtableMgr::to_string(char *buf, const int64_t buf_len) const return pos; } -int ObTabletMemtableMgr::find_start_pos_(const int64_t start_log_ts, - const int64_t start_snapshot_version, - int64_t &start_pos) -{ - int ret = OB_SUCCESS; - start_pos = -1; - if (OB_UNLIKELY(start_log_ts <= 0)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid start_snapshot_version", K(ret), K(start_snapshot_version), K(start_log_ts)); - } - for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) { - ObMemtable *memtable = get_memtable_(i); - if (OB_ISNULL(memtable)) { - ret = OB_ERR_SYS; - LOG_ERROR("memtable must not null", K(ret)); - } else if (memtable->get_end_scn().get_val_for_tx() == start_log_ts) { - if (memtable->get_snapshot_version() > start_snapshot_version) { - start_pos = i; - break; - } - } else if (memtable->get_end_scn().get_val_for_tx() > start_log_ts) { - start_pos = i; - break; - } - } - return ret; -} - -int ObTabletMemtableMgr::get_memtables_v2( - ObTableHdlArray &handle, - const int64_t start_log_ts, - const int64_t start_snapshot_version, - const bool reset_handle, - const bool include_active_memtable) -{ - int ret = OB_SUCCESS; - if (OB_UNLIKELY(!is_inited_)) { - ret = OB_NOT_INIT; - LOG_WARN("not inited", K(ret), K_(is_inited)); - } else { - MemMgrRLockGuard guard(lock_); - if (reset_handle) { - handle.reset(); - } - int64_t start_pos = memtable_head_; - if (0 < start_log_ts) { - if (OB_FAIL(find_start_pos_(start_log_ts, start_snapshot_version, start_pos))) { - LOG_WARN("failed to find_start_pos_", K(ret), K(start_log_ts), K(start_snapshot_version)); - } - } - if (OB_SUCC(ret) && OB_FAIL(add_tables_(start_pos, include_active_memtable, handle))) { - LOG_WARN("failed to add_tables", K(ret), K(start_log_ts), K(start_snapshot_version), - K(include_active_memtable), K(reset_handle)); - } - } - return ret; -} - -int ObTabletMemtableMgr::get_first_frozen_memtable_(ObTableHandleV2 &handle) const +int ObTabletMemtableMgr::get_first_frozen_memtable_(ObTableHandleV2 &handle) { int ret = OB_SUCCESS; for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; i++) { ObTableHandleV2 m_handle; - const ObMemtable *memtable = nullptr; + ObITabletMemtable *memtable = nullptr; if (OB_FAIL(get_ith_memtable(i, m_handle))) { STORAGE_LOG(WARN, "fail to get ith memtable", K(ret), K(i)); } else if (OB_UNLIKELY(!m_handle.is_valid())) { ret = OB_ERR_SYS; LOG_ERROR("memtable handle is invalid", K(ret), K(m_handle)); - } else if (OB_FAIL(m_handle.get_data_memtable(memtable))) { + } else if (OB_FAIL(m_handle.get_tablet_memtable(memtable))) { LOG_WARN("fail to get memtable", K(ret), K(m_handle)); } else if (OB_ISNULL(memtable)) { ret = OB_ERR_UNEXPECTED; @@ -1006,7 +979,7 @@ int ObTabletMemtableMgr::set_frozen_for_all_memtables() const share::ObLSID &ls_id = ls_->get_ls_id(); for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) { // memtable that cannot be released will block memtables behind it - ObMemtable *memtable = static_cast(tables_[get_memtable_idx(i)]); + ObITabletMemtable *memtable = static_cast(tables_[get_memtable_idx(i)]); if (OB_ISNULL(memtable)) { ret = OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "memtable is nullptr", K(ret), K(ls_id), KP(memtable), K(i)); @@ -1016,7 +989,119 @@ int ObTabletMemtableMgr::set_frozen_for_all_memtables() } } } + return ret; +} +int ObTabletMemtableMgr::acquire_tablet_memtable_(const bool for_inc_direct_load, ObTableHandleV2 &handle) +{ + int ret = OB_SUCCESS; + if (for_inc_direct_load) { + ret = t3m_->acquire_direct_load_memtable(handle); + } else { + ret = t3m_->acquire_data_memtable(handle); + } + return ret; +} + +int ObTabletMemtableMgr::freeze_direct_load_memtable(ObITabletMemtable *tablet_memtable) +{ + int ret = OB_SUCCESS; + MemMgrWLockGuard lock_guard(lock_); + ObTableHandleV2 boundary_memtable_handle; + ObITabletMemtable *boundary_memtable = nullptr; + if (OB_FAIL(get_boundary_memtable_(boundary_memtable_handle))) { + STORAGE_LOG(WARN, "get boundary memtable failed", KR(ret)); + } else if (!boundary_memtable_handle.is_valid()) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(WARN, "last memtable handle is unexpected invalid", KR(ret), K(boundary_memtable_handle)); + } else if (OB_FAIL(boundary_memtable_handle.get_tablet_memtable(boundary_memtable))) { + STORAGE_LOG(WARN, "get active tablet memtable failed", KR(ret), K(boundary_memtable_handle)); + } else if (OB_ISNULL(tablet_memtable)) { + ret = OB_ERR_UNEXPECTED; + STORAGE_LOG(ERROR, "tablet memtable is unexpected null", KR(ret)); + } else if (tablet_memtable != boundary_memtable || !(tablet_memtable->get_end_scn().is_max())) { + STORAGE_LOG(INFO, "this direct load memtable already freezed", KPC(tablet_memtable), KPC(boundary_memtable)); + } else if (!tablet_memtable->is_direct_load_memtable()) { + STORAGE_LOG(WARN, "not direct load memtable", KR(ret), KPC(tablet_memtable)); + } else if (!tablet_memtable->allow_freeze()) { + ret = OB_MINOR_FREEZE_NOT_ALLOW; + STORAGE_LOG(WARN, + "active direct load memtable is not allowd freeze", + K(get_memtable_count_()), + K(tables_), + KPC(tablet_memtable)); + } else { + const int64_t FREEZE_DIRECT_LOAD_MEMTABLE_WARN_INTERVAL = 100LL * 1000LL; + int64_t start_ts = ObClockGenerator::getClock(); + while (tablet_memtable->get_write_ref() > 0) { + // waiting for all write operation done. + if (TC_REACH_TIME_INTERVAL(FREEZE_DIRECT_LOAD_MEMTABLE_WARN_INTERVAL)) { + int64_t freeze_wait_time_ms = (ObClockGenerator::getClock() - start_ts) / 1000; + STORAGE_LOG_RET(WARN, + OB_ERR_TOO_MUCH_TIME, + "freeze direct load memtable cost too much time. has wait for(ms) : ", + K(freeze_wait_time_ms), + KPC(tablet_memtable)); + } + PAUSE(); + } + (void)tablet_memtable->resolve_right_boundary(); + (void)tablet_memtable->set_freeze_state(TabletMemtableFreezeState::FREEZING); + (void)tablet_memtable->set_frozen_time(ObClockGenerator::getClock()); + + STORAGE_LOG(INFO, "finish freeze direct load memtable", KP(this), KPC(tablet_memtable)); + } + + return ret; +} + + +int ObTabletMemtableMgr::get_direct_load_memtables_for_write(ObTableHdlArray &handles) +{ + int ret = OB_SUCCESS; + MemMgrRLockGuard lock_guard(lock_); + + int64_t last_data_memtable_pos = 0; + if (OB_FAIL(find_last_data_memtable_pos_(last_data_memtable_pos))) { + LOG_WARN("find last data memtable pos failed", KR(ret), KP(this)); + } else if (OB_FAIL(add_tables_(last_data_memtable_pos + 1, true/*include_active_memtable*/, handles))) { + LOG_WARN("add tables failed", KR(ret), KP(this)); + } else { + ObITabletMemtable *memtable = nullptr; + for (int64_t i = 0; OB_SUCC(ret) && i < handles.count(); i++) { + if (OB_ISNULL(memtable = static_cast(handles.at(i).get_table()))) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("unexpected nullptr", KR(ret), KP(this), KP(memtable)); + } else if (!memtable->is_direct_load_memtable()) { + if (1 == handles.count()) { + // The active memtable is data memtable, reset it + handles.reset(); + } else { + LOG_ERROR("invalid memtable", KR(ret), K(i), K(handles), KPC(memtable)); + } + } else { + memtable->inc_write_ref(); + } + } + } + + return ret; +} + +int ObTabletMemtableMgr::find_last_data_memtable_pos_(int64_t &last_pos) +{ + int ret = OB_SUCCESS; + last_pos = memtable_head_ - 1; + for (int64_t i = memtable_tail_-1; OB_SUCC(ret) && i >= memtable_head_; i--) { + ObITabletMemtable *memtable = get_memtable_(i); + if (OB_ISNULL(memtable)) { + ret = OB_ERR_SYS; + LOG_ERROR("memtable must not null", K(ret)); + } else if (memtable->is_data_memtable()) { + last_pos = i; + break; + } + } return ret; } diff --git a/src/storage/tablet/ob_tablet_memtable_mgr.h b/src/storage/tablet/ob_tablet_memtable_mgr.h index 345763c6a..f77679916 100644 --- a/src/storage/tablet/ob_tablet_memtable_mgr.h +++ b/src/storage/tablet/ob_tablet_memtable_mgr.h @@ -28,13 +28,11 @@ namespace oceanbase namespace memtable { class ObMemtable; -class ObIMemtable; -class ObIMultiSourceDataUnit; } namespace storage { -class ObIPartitionComponentFactory; +class ObIMemtable; class ObTenantMetaMemMgr; class ObFreezer; @@ -49,6 +47,18 @@ public: ObTabletMemtableMgr(); virtual ~ObTabletMemtableMgr(); + bool has_active_memtable(); + int get_memtables_nolock(ObTableHdlArray &handle); + int get_first_frozen_memtable(ObTableHandleV2 &handle); + ObStorageSchemaRecorder &get_storage_schema_recorder() { return schema_recorder_; } + compaction::ObTabletMediumCompactionInfoRecorder &get_medium_info_recorder() { return medium_info_recorder_; } + int unset_logging_blocked_for_active_memtable(ObITabletMemtable *memtable); + int resolve_left_boundary_for_active_memtable(ObITabletMemtable *memtable, + const share::SCN start_scn); + int freeze_direct_load_memtable(ObITabletMemtable *tablet_memtable); + int get_direct_load_memtables_for_write(ObTableHdlArray &handles); + +public: // derived from ObIMemtableMgr virtual int init(const common::ObTabletID &tablet_id, const share::ObLSID &ls_id, ObFreezer *freezer, @@ -57,89 +67,55 @@ public: virtual int get_active_memtable(ObTableHandleV2 &handle) const override; virtual int get_all_memtables(ObTableHdlArray &handle) override; virtual void destroy() override; - void reset(); - uint32_t get_ls_freeze_clock(); - - bool has_active_memtable(); - int64_t get_memtable_count() const; virtual int get_memtable_for_replay(share::SCN replay_scn, ObTableHandleV2 &handle) override; - int get_last_frozen_memtable(ObTableHandleV2 &handle) const; virtual int get_boundary_memtable(ObTableHandleV2 &handle) override; - int release_tail_memtable(memtable::ObIMemtable *memtable); - virtual int create_memtable( - const share::SCN clog_checkpoint_scn, - const int64_t schema_version, - const share::SCN newest_clog_checkpoint_scn, - const bool for_replay) override; - int get_memtables( - ObTableHdlArray &handle, - const bool reset_handle = true, - const int64_t start_point = -1, - const bool include_active_memtable = true); - int get_memtables_v2( - ObTableHdlArray &handle, - const int64_t start_log_ts, - const int64_t start_snapshot_version, - const bool reset_handle = true, - const bool include_active_memtable = true); - int get_memtables_nolock(ObTableHdlArray &handle); - int get_first_frozen_memtable(ObTableHandleV2 &handle) const; - int set_is_tablet_freeze_for_active_memtable(ObTableHandleV2 &handle, - const int64_t trace_id = checkpoint::INVALID_TRACE_ID); - - ObStorageSchemaRecorder &get_storage_schema_recorder() { return schema_recorder_; } - compaction::ObTabletMediumCompactionInfoRecorder &get_medium_info_recorder() { return medium_info_recorder_; } - - virtual int init_storage_recorder( - const ObTabletID &tablet_id, - const share::ObLSID &ls_id, - const int64_t max_saved_schema_version, - const int64_t max_saved_medium_scn, - const lib::Worker::CompatMode compat_mode, - logservice::ObLogHandler *log_handler) override; - virtual int reset_storage_recorder() override; + virtual int create_memtable(const CreateMemtableArg &arg) override; + virtual int get_last_frozen_memtable(ObTableHandleV2 &handle) override; + virtual int set_is_tablet_freeze_for_active_memtable(ObTableHandleV2 &handle, + const int64_t trace_id = checkpoint::INVALID_TRACE_ID); + virtual int init_storage_recorder(const ObTabletID &tablet_id, + const share::ObLSID &ls_id, + const int64_t max_saved_schema_version, + const int64_t max_saved_medium_scn, + const lib::Worker::CompatMode compat_mode, + logservice::ObLogHandler *log_handler) override; virtual int set_frozen_for_all_memtables() override; + DECLARE_VIRTUAL_TO_STRING; protected: - virtual int release_head_memtable_(memtable::ObIMemtable *memtable, + virtual int release_head_memtable_(ObIMemtable *memtable, const bool force = false) override; private: - //minor freeze - int64_t get_unmerged_memtable_count_() const; - memtable::ObMemtable *get_active_memtable_(); - int get_active_memtable_(ObTableHandleV2 &handle) const; - int get_memtables_( - ObTableHdlArray &handle, - const int64_t start_point, - const bool include_active_memtable); - int add_tables_( - const int64_t start_pos, - const bool include_active_memtable, - ObTableHdlArray &handle); - memtable::ObMemtable *get_memtable_(const int64_t pos) const; - int find_start_pos_(const int64_t start_point, int64_t &start_pos); - int find_start_pos_( - const int64_t start_log_ts, - const int64_t start_snapshot_version, - int64_t &start_pos); - int get_first_frozen_memtable_(ObTableHandleV2 &handle) const; + void block_freeze_if_memstore_full_(ObITabletMemtable *new_tablet_memtable); void clean_tail_memtable_(); - int get_last_frozen_memtable_(ObTableHandleV2 &handle) const; - int try_resolve_boundary_on_create_memtable_for_leader_(memtable::ObMemtable *last_frozen_memtable, - memtable::ObMemtable *new_memtable); - int resolve_left_boundary_for_active_memtable(memtable::ObIMemtable *memtable, - share::SCN start_scn, - share::SCN snapshot_version); - int unset_logging_blocked_for_active_memtable(memtable::ObIMemtable *memtable); + int resolve_boundary_(ObITabletMemtable *new_tablet_memtable, const CreateMemtableArg &arg); + int get_active_memtable_(ObTableHandleV2 &handle) const; + int get_boundary_memtable_(ObTableHandleV2 &handle); + int get_memtables_(ObTableHdlArray &handle, const int64_t start_point, const bool include_active_memtable); + int add_tables_(const int64_t start_pos, const bool include_active_memtable, ObTableHdlArray &handle); + int find_start_pos_(const int64_t start_point, int64_t &start_pos); + int find_last_data_memtable_pos_(int64_t &last_pos); + int get_first_frozen_memtable_(ObTableHandleV2 &handle); + int get_last_frozen_memtable_(ObTableHandleV2 &handle); + int try_resolve_boundary_on_create_memtable_for_leader_(ObITabletMemtable *last_frozen_tablet_memtable, + ObITabletMemtable *new_tablet_memtable); + int check_boundary_memtable_(const uint32_t logstream_freeze_clock); + void resolve_data_memtable_boundary_(ObITabletMemtable *frozen_tablet_memtable, + ObITabletMemtable *active_tablet_memtable, + const CreateMemtableArg &arg); + void resolve_direct_load_memtable_boundary_(ObITabletMemtable *frozen_tablet_memtable, + ObITabletMemtable *active_tablet_memtable, + const CreateMemtableArg &arg); + int create_memtable_(const CreateMemtableArg &arg, const uint32_t logstream_freeze_clock, ObTimeGuard &tg); + int acquire_tablet_memtable_(const bool for_inc_direct_load, ObTableHandleV2 &handle); + ObITabletMemtable *get_active_memtable_(); + ObITabletMemtable *get_memtable_(const int64_t pos) const; DISALLOW_COPY_AND_ASSIGN(ObTabletMemtableMgr); -private: - static const int64_t PRINT_READABLE_INFO_DURATION_US = 1000 * 1000 * 60 * 10L; //10min - private: ObLS *ls_; // 8B common::SpinRWLock lock_def_; //8B diff --git a/src/storage/tablet/ob_tablet_persister.cpp b/src/storage/tablet/ob_tablet_persister.cpp index cb95d48cc..0f75a453f 100644 --- a/src/storage/tablet/ob_tablet_persister.cpp +++ b/src/storage/tablet/ob_tablet_persister.cpp @@ -494,7 +494,7 @@ int ObTabletPersister::convert_tablet_to_mem_arg( arg.is_row_store_ = tablet.is_row_store(); arg.ddl_kvs_ = tablet.ddl_kvs_; arg.ddl_kv_count_ = tablet.ddl_kv_count_; - MEMCPY(arg.memtables_, tablet.memtables_, sizeof(memtable::ObIMemtable*) * MAX_MEMSTORE_CNT); + MEMCPY(arg.memtables_, tablet.memtables_, sizeof(ObIMemtable*) * MAX_MEMSTORE_CNT); arg.memtable_count_ = tablet.memtable_count_; } return ret; diff --git a/src/storage/tablet/ob_tablet_persister.h b/src/storage/tablet/ob_tablet_persister.h index 5930db63b..8402b51f6 100644 --- a/src/storage/tablet/ob_tablet_persister.h +++ b/src/storage/tablet/ob_tablet_persister.h @@ -102,7 +102,7 @@ public: bool is_row_store_; ObDDLKV **ddl_kvs_; int64_t ddl_kv_count_; - memtable::ObIMemtable *memtables_[MAX_MEMSTORE_CNT]; + ObIMemtable *memtables_[MAX_MEMSTORE_CNT]; int64_t memtable_count_; // If you want to add new member, make sure all member is assigned in 2 convert function. // ObTabletPersister::convert_tablet_to_mem_arg diff --git a/src/storage/tx/ob_direct_load_tx_ctx_define.cpp b/src/storage/tx/ob_direct_load_tx_ctx_define.cpp new file mode 100644 index 000000000..cfc514cbc --- /dev/null +++ b/src/storage/tx/ob_direct_load_tx_ctx_define.cpp @@ -0,0 +1,337 @@ +/** + * 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. + */ + +#include "storage/tx/ob_direct_load_tx_ctx_define.h" + +#define USING_LOG_PREFIX STORAGE + +namespace oceanbase +{ + +namespace transaction +{ + +// OB_SERIALIZE_MEMBER(ObTxDirectLoadIncBatchKey, primary_tablet_id_, secondary_tablet_id_); + +OB_SERIALIZE_MEMBER(ObTxDirectLoadIncBatchInfo, + batch_key_, /* 1 */ + start_scn_ /* 2 */); +// flag_.val_ /* 3 */); + +int ObTxDirectLoadIncBatchInfo::set_start_log_synced() +{ + int ret = OB_SUCCESS; + + if (!tmp_start_scn_.is_valid_and_not_min() + || (start_scn_.is_valid_and_not_min() && start_scn_ != tmp_start_scn_)) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(ERROR, "the tmp_start_scn is not valid in on_success", K(ret), KPC(this)); + } else { + start_scn_ = tmp_start_scn_; + } + + return ret; +} + +int ObDLIBatchSet::serialize(char *buf, const int64_t buf_len, int64_t &pos) const +{ + int ret = OB_SUCCESS; + + const int64_t hash_count = ObTxDirectLoadBatchSet::size(); + const int64_t origin_pos = pos; + + if (OB_FAIL(serialization::encode_vi64(buf, buf_len, pos, hash_count))) { + TRANS_LOG(WARN, "encode hash count failed", K(ret), K(hash_count), KP(buf), K(buf_len), K(pos)); + } else { + ObTxDirectLoadBatchSet::const_iterator iter = ObTxDirectLoadBatchSet::begin(); + + for (; iter != ObTxDirectLoadBatchSet::end() && OB_SUCC(ret); iter++) { + if (OB_FAIL(iter->first.serialize(buf, buf_len, pos))) { + TRANS_LOG(WARN, "serialize log key failed", K(ret), KP(buf), K(buf_len), K(pos)); + } + } + } + + if (OB_FAIL(ret)) { + TRANS_LOG(WARN, "serialize failed,return to the origin_pos", K(ret), K(pos), K(origin_pos), + KP(buf), K(buf_len)); + pos = origin_pos; + } + + return ret; +} + +int ObDLIBatchSet::deserialize(const char *buf, const int64_t data_len, int64_t &pos) +{ + int ret = OB_SUCCESS; + + int64_t hash_count = 0; + const int64_t origin_pos = pos; + const common::ObTabletID invalid_tablet_id(common::ObTabletID::INVALID_TABLET_ID); + + if (OB_FAIL(serialization::decode(buf, data_len, pos, hash_count))) { + TRANS_LOG(WARN, "decode hash count failed", K(ret), K(hash_count), KP(buf), K(data_len), + K(pos)); + } else { + for (int64_t i = 0; i < hash_count && OB_SUCC(ret); i++) { + ObTxDirectLoadIncBatchInfo tmp_info; + if (OB_FAIL(tmp_info.deserialize(buf, data_len, pos))) { + TRANS_LOG(WARN, "deserialize direct load inc log key", K(ret), K(hash_count), KP(buf), + K(data_len), K(pos)); + } else if (!tmp_info.get_batch_key().is_valid()) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "invalid deserialized log key", K(ret), K(tmp_info), K(i), K(hash_count), + KP(buf), K(data_len), K(pos)); + } else if (OB_FAIL(ObTxDirectLoadBatchSet::set_refactored(tmp_info))) { + TRANS_LOG(WARN, "insert into hash set failed", K(ret), K(tmp_info), K(i), K(hash_count), + KP(buf), K(data_len), K(pos)); + } + } + } + + if (OB_SUCC(ret) && ObTxDirectLoadBatchSet::size() < hash_count) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "too few hash members after deserialized", K(ret), + K(ObTxDirectLoadBatchSet::size()), K(hash_count), KP(buf), K(data_len), K(pos)); + } + + if (OB_FAIL(ret)) { + TRANS_LOG(WARN, "deserialize failed,return to the origin_pos", K(ret), K(pos), K(origin_pos), + KP(buf), K(data_len)); + pos = origin_pos; + } + + return ret; +} + +int64_t ObDLIBatchSet::get_serialize_size() const +{ + int ret = OB_SUCCESS; + + const int64_t hash_count = ObTxDirectLoadBatchSet::size(); + int64_t total_size = 0; + + total_size += serialization::encoded_length_vi64(hash_count); + + ObTxDirectLoadBatchSet::const_iterator iter = ObTxDirectLoadBatchSet::begin(); + + for (; iter != ObTxDirectLoadBatchSet::end() && OB_SUCC(ret); iter++) { + total_size += iter->first.get_serialize_size(); + } + return total_size; +} + +int ObDLIBatchSet::before_submit_ddl_start(const ObDDLIncLogBasic &key, const share::SCN &start_scn) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + ObMemAttr mem_attr(MTL_ID(), "DLI_BATCH_HASH"); + if (!key.is_valid()) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid argument", K(ret), K(key)); + } else if (!created() && OB_FAIL(create(32, mem_attr, mem_attr))) { + TRANS_LOG(WARN, "create batch hash set failed", K(ret), K(key)); + } else { + ObTxDirectLoadIncBatchInfo batch_info(key); + + if (OB_FAIL(set_refactored(batch_info, 0))) { + if (OB_HASH_EXIST != ret) { + TRANS_LOG(WARN, "insert batch info into hash_set failed", K(ret), K(batch_info)); + } else { + + const ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_NOT_NULL(info_in_hashset)) { + if ((info_in_hashset->is_ddl_start_logging() + && info_in_hashset->get_tmp_start_scn() != start_scn) + || (info_in_hashset->is_ddl_start_log_synced() + && info_in_hashset->get_start_scn() != start_scn)) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, "try to submit ddl start twice with the same key ", K(ret), + KPC(info_in_hashset), K(batch_info), K(start_scn)); + } else if (!start_scn.is_valid_and_not_min() && info_in_hashset->is_ddl_end_logging()) { + ret = OB_EAGAIN; + TRANS_LOG(WARN, "the last ddl end log is logging", K(ret), K(info_in_hashset), + K(batch_info), K(start_scn)); + } else if (OB_FAIL(set_refactored(batch_info, 1))) { + TRANS_LOG(WARN, "overwrite existed batch_info failed", K(ret), KPC(info_in_hashset), + K(batch_info), K(start_scn)); + } + + } else { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(ERROR, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset)); + } + } + } + } + return ret; +} + +int ObDLIBatchSet::submit_ddl_start_succ(const ObDDLIncLogBasic &key, const share::SCN &start_scn) +{ + int ret = OB_SUCCESS; + + ObTxDirectLoadIncBatchInfo batch_info(key); + + ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_ISNULL(info_in_hashset)) { + + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(ERROR, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset), K(start_scn)); + } else { + info_in_hashset->set_tmp_start_scn(start_scn); + // info_in_hashset->clear_start_log_synced(); + } + return ret; +} + +int ObDLIBatchSet::sync_ddl_start_succ(const ObDDLIncLogBasic &key, const share::SCN &start_scn) +{ + int ret = OB_SUCCESS; + + ObTxDirectLoadIncBatchInfo batch_info(key); + + ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_ISNULL(info_in_hashset)) { + + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(ERROR, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset), K(start_scn)); + } else if (OB_FAIL(info_in_hashset->set_start_log_synced())) { + TRANS_LOG(WARN, "set ddl start synced log failed", K(ret), K(batch_info), K(info_in_hashset), + K(start_scn)); + } + return ret; +} + +int ObDLIBatchSet::sync_ddl_start_fail(const ObDDLIncLogBasic &key) +{ + int ret = OB_SUCCESS; + + ObTxDirectLoadIncBatchInfo batch_info(key); + + ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_ISNULL(info_in_hashset)) { + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(ERROR, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset)); + } else { + info_in_hashset->set_tmp_start_scn(share::SCN::invalid_scn()); + } + + return ret; +} + +int ObDLIBatchSet::before_submit_ddl_end(const ObDDLIncLogBasic &key, const share::SCN &end_scn) +{ + int ret = OB_SUCCESS; + + + ObTxDirectLoadIncBatchInfo batch_info(key); + + ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_ISNULL(info_in_hashset)) { + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(WARN, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset),K(end_scn)); + } else if (info_in_hashset->is_ddl_end_logging()){ + ret = OB_ENTRY_EXIST; + TRANS_LOG(WARN, "The DDL end is logging", K(ret), K(batch_info),KPC(info_in_hashset),K(end_scn)); + } + + return ret; +} + +int ObDLIBatchSet::submit_ddl_end_succ(const ObDDLIncLogBasic &key, const share::SCN &end_scn) +{ + int ret = OB_SUCCESS; + + ObTxDirectLoadIncBatchInfo batch_info(key); + + ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_ISNULL(info_in_hashset)) { + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(WARN, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset)); + } else { + info_in_hashset->set_tmp_end_scn(end_scn); + } + return ret; +} + +int ObDLIBatchSet::sync_ddl_end_succ(const ObDDLIncLogBasic &key, const share::SCN &end_scn) +{ + int ret = OB_SUCCESS; + ObTxDirectLoadIncBatchInfo batch_info(key); + if (OB_FAIL(erase_refactored(batch_info))) { + if (OB_HASH_NOT_EXIST == ret) { + ret = OB_ENTRY_NOT_EXIST; + } + TRANS_LOG(WARN, "erase from hash set failed", K(ret), K(batch_info), K(end_scn)); + } + return ret; +} + +int ObDLIBatchSet::sync_ddl_end_fail(const ObDDLIncLogBasic &key) +{ + + int ret = OB_SUCCESS; + ObTxDirectLoadIncBatchInfo batch_info(key); + + ObTxDirectLoadIncBatchInfo *info_in_hashset = get(batch_info); + if (OB_ISNULL(info_in_hashset)) { + + ret = OB_ENTRY_NOT_EXIST; + TRANS_LOG(ERROR, "a existed batch_info hasn't found", K(ret), K(batch_info), + KPC(info_in_hashset)); + } else { + info_in_hashset->set_tmp_end_scn(share::SCN::invalid_scn()); + } + return ret; +} + +int ObDLIBatchSet::remove_unlog_batch_info(const ObTxDirectLoadBatchKeyArray &batch_key_array) +{ + int ret = OB_SUCCESS; + + for (int i = 0; i < batch_key_array.count() && OB_SUCC(ret); i++) { + + ObTxDirectLoadIncBatchInfo batch_info(batch_key_array[i]); + if (OB_FAIL(erase_refactored(batch_info))) { + TRANS_LOG(WARN, "erase from hash set failed", K(ret), K(batch_info), K(i), + K(batch_key_array.count())); + } + } + return ret; +} + +int ObDLIBatchSet::assign(const ObDLIBatchSet &other) +{ + int ret = OB_SUCCESS; + + reuse(); + ObDLIBatchSet::const_iterator iter = other.begin(); + + while (iter != other.end() && OB_SUCC(ret)) { + if (OB_FAIL(set_refactored(iter->first, 1))) { + TRANS_LOG(WARN, "overwrite existed batch_info failed", K(ret), K(iter->first)); + } + iter++; + } + + return ret; +} +} // namespace transaction + +} // namespace oceanbase diff --git a/src/storage/tx/ob_direct_load_tx_ctx_define.h b/src/storage/tx/ob_direct_load_tx_ctx_define.h new file mode 100644 index 000000000..eb8399f2b --- /dev/null +++ b/src/storage/tx/ob_direct_load_tx_ctx_define.h @@ -0,0 +1,141 @@ +/** + * 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. + */ + +// class ObPartTransCtx +// { +// public: + +#ifndef OCEANBASE_TRANSACTION_DIRECT_LOAD_TX_CTX_DEFINE_HEADER +#define OCEANBASE_TRANSACTION_DIRECT_LOAD_TX_CTX_DEFINE_HEADER + +#include "common/ob_tablet_id.h" +#include "lib/container/ob_se_array.h" +#include "lib/hash/ob_hashset.h" +#include "share/scn.h" +#include "storage/ddl/ob_ddl_inc_clog.h" +#include "storage/tx/ob_tx_serialization.h" + +namespace oceanbase +{ + +namespace transaction +{ + +using namespace storage; + +class ObTxDirectLoadIncBatchInfo +{ + OB_UNIS_VERSION(1); + +public: + ObTxDirectLoadIncBatchInfo() : batch_key_(), start_scn_(), tmp_start_scn_(), tmp_end_scn_() {} + ObTxDirectLoadIncBatchInfo(const ObDDLIncLogBasic &ddl_inc_basic) + : batch_key_(ddl_inc_basic), start_scn_(), tmp_start_scn_(), tmp_end_scn_() + {} + +public: + uint64_t hash() const { return batch_key_.hash(); } + int hash(uint64_t &hash_val) const { return batch_key_.hash(hash_val); } + + bool operator==(const ObTxDirectLoadIncBatchInfo &other) const + { + return batch_key_ == other.batch_key_; + } + +private: + static const int64_t LOG_SYNC_SUCC_BIT = 1UL << 1; + +public: + const ObDDLIncLogBasic &get_batch_key() const { return batch_key_; } + + // void set_start_scn(const share::SCN scn) { start_scn_ = scn; } + share::SCN get_start_scn() const { return start_scn_; } + void set_tmp_start_scn(const share::SCN scn) { tmp_start_scn_ = scn; } + share::SCN get_tmp_start_scn() const { return tmp_start_scn_; } + void set_tmp_end_scn(const share::SCN scn) { tmp_end_scn_ = scn; } + share::SCN get_tmp_end_scn() const { return tmp_end_scn_; } + + bool need_compensate_ddl_end() const { return is_start_log_synced() && !is_ddl_end_logging(); } + bool is_ddl_start_logging() const + { + return tmp_start_scn_.is_valid_and_not_min() && !start_scn_.is_valid_and_not_min(); + } + bool is_ddl_start_log_synced() const { return is_start_log_synced(); } + bool is_ddl_end_logging() const { return tmp_end_scn_.is_valid_and_not_min(); } + +private: + // union Flag + // { + // int64_t val_; + // struct BitFlag + // { + // bool start_log_sync_succ_ : 1; + // + // TO_STRING_KV(K(start_log_sync_succ_)); + // } bit_; + // }; + // +public: + int set_start_log_synced(); // void clear_start_log_synced() { start_scn_.set_invalid(); } + bool is_start_log_synced() const { return start_scn_.is_valid_and_not_min(); } + + TO_STRING_KV(K(batch_key_), K(start_scn_), K(tmp_start_scn_), K(tmp_end_scn_)); + +private: + ObDDLIncLogBasic batch_key_; + share::SCN start_scn_; + // Flag flag_; + + /*in memory*/ + share::SCN tmp_start_scn_; + share::SCN tmp_end_scn_; +}; + +typedef common::hash::ObHashSet + ObTxDirectLoadBatchSet; +typedef common::ObSEArray ObTxDirectLoadBatchKeyArray; + +// hash_count | hashkey 1 | hashkey 2 | hashkey 3 | ... +class ObDLIBatchSet : public ObTxDirectLoadBatchSet +{ +public: + NEED_SERIALIZE_AND_DESERIALIZE; + + // bool operator==(const ObDLIBatchSet &other) const + // { + // return this == &other; + // } +public: + int before_submit_ddl_start(const ObDDLIncLogBasic &key, + const share::SCN &start_scn = share::SCN::invalid_scn()); + int submit_ddl_start_succ(const ObDDLIncLogBasic &key, const share::SCN &start_scn); + int sync_ddl_start_succ(const ObDDLIncLogBasic &key, const share::SCN &start_scn); + int sync_ddl_start_fail(const ObDDLIncLogBasic &key); + + int before_submit_ddl_end(const ObDDLIncLogBasic &key, + const share::SCN &end_scn = share::SCN::invalid_scn()); + int submit_ddl_end_succ(const ObDDLIncLogBasic &key, const share::SCN &end_scn); + int sync_ddl_end_succ(const ObDDLIncLogBasic &key, const share::SCN &end_scn); + int sync_ddl_end_fail(const ObDDLIncLogBasic &key); + + int remove_unlog_batch_info(const ObTxDirectLoadBatchKeyArray &batch_key_array); + + int assign(const ObDLIBatchSet &other); +}; + +} // namespace transaction +} // namespace oceanbase + +#endif + +// +// }; diff --git a/src/storage/tx/ob_trans_ctx_mgr_v4.h b/src/storage/tx/ob_trans_ctx_mgr_v4.h index 70ef9dcae..908f1c1b6 100644 --- a/src/storage/tx/ob_trans_ctx_mgr_v4.h +++ b/src/storage/tx/ob_trans_ctx_mgr_v4.h @@ -34,6 +34,7 @@ class ObTabletID; namespace storage { +class ObIMemtable; class ObLSTxService; class ObTransSubmitLogFunctor; class ObTxCtxTable; @@ -43,7 +44,6 @@ struct ObTransferMoveTxParam; namespace memtable { -class ObIMemtable; class ObMemtable; class ObIMemtableCtx; } diff --git a/src/storage/tx/ob_trans_define.cpp b/src/storage/tx/ob_trans_define.cpp index 612691ab9..dd54fc0d1 100644 --- a/src/storage/tx/ob_trans_define.cpp +++ b/src/storage/tx/ob_trans_define.cpp @@ -770,6 +770,7 @@ void ObTxExecInfo::reset() exec_epoch_ = 0; serial_final_scn_.reset(); serial_final_seq_no_.reset(); + dli_batch_set_.destroy(); } void ObTxExecInfo::destroy(ObTxMDSCache &mds_cache) @@ -898,6 +899,8 @@ int ObTxExecInfo::assign(const ObTxExecInfo &exec_info) TRANS_LOG(WARN, "commit parts assign error", KR(ret), K(exec_info)); } else if (OB_FAIL(transfer_parts_.assign(exec_info.transfer_parts_))) { TRANS_LOG(WARN, "transfer_epoch assign error", KR(ret), K(exec_info)); + } else if (OB_FAIL(dli_batch_set_.assign(exec_info.dli_batch_set_))) { + TRANS_LOG(WARN, "direct load inc batch set assign error", K(ret), K(exec_info.dli_batch_set_)); } else { // Prepare version should be initialized before state_ // for ObTransPartCtx::get_prepare_version_if_preapred(); @@ -968,7 +971,9 @@ OB_SERIALIZE_MEMBER(ObTxExecInfo, checksum_, checksum_scn_, serial_final_scn_, - serial_final_seq_no_); + serial_final_seq_no_, + dli_batch_set_ // FARM COMPAT WHITELIST + ); bool ObMulSourceDataNotifyArg::is_redo_submitted() const { return redo_submitted_; } diff --git a/src/storage/tx/ob_trans_define.h b/src/storage/tx/ob_trans_define.h index 171386a21..0a9e0491a 100644 --- a/src/storage/tx/ob_trans_define.h +++ b/src/storage/tx/ob_trans_define.h @@ -31,6 +31,7 @@ #include "storage/tx/ob_committer_define.h" #include "storage/tx/ob_trans_result.h" #include "storage/tx/ob_xa_define.h" +#include "storage/tx/ob_direct_load_tx_ctx_define.h" #include "ob_multi_data_source.h" #include "share/scn.h" @@ -1870,7 +1871,8 @@ public: K_(is_empty_ctx_created_by_transfer), K_(exec_epoch), K_(serial_final_scn), - K_(serial_final_seq_no)); + K_(serial_final_seq_no), + K_(dli_batch_set)); return pos; } ObTxState state_; @@ -1915,6 +1917,7 @@ public: // used to decide whether a branch level savepoint rollback log // need set pre-barrier to wait previous redo replayed ObTxSEQ serial_final_seq_no_; + ObDLIBatchSet dli_batch_set_; }; static const int64_t USEC_PER_SEC = 1000 * 1000; diff --git a/src/storage/tx/ob_trans_part_ctx.cpp b/src/storage/tx/ob_trans_part_ctx.cpp index 3cf6db8d3..2794ab307 100644 --- a/src/storage/tx/ob_trans_part_ctx.cpp +++ b/src/storage/tx/ob_trans_part_ctx.cpp @@ -44,6 +44,8 @@ #include "storage/tablet/ob_tablet_transfer_tx_ctx.h" #include "storage/tx/ob_ctx_tx_data.h" #include "logservice/ob_log_service.h" +#include "storage/ddl/ob_ddl_inc_clog_callback.h" +#include "storage/tx/ob_tx_log_operator.h" namespace oceanbase { @@ -242,6 +244,8 @@ void ObPartTransCtx::destroy() K(busy_cbs_.get_size())); } + (void)check_dli_batch_completed_(ObTxLogType::TX_CLEAR_LOG); + if (exec_info_.is_dup_tx_ && OB_NOT_NULL(ls_tx_ctx_mgr_)) { if (OB_FAIL(ls_tx_ctx_mgr_->get_ls_log_adapter()->remove_commiting_dup_trx(trans_id_))) { TRANS_LOG(WARN, "remove committing dup table trx failed", K(ret), KPC(this)); @@ -2333,6 +2337,11 @@ int ObPartTransCtx::on_success_ops_(ObTxLogCb *log_cb) } else { log_cb->get_mds_range().reset(); } + } else if (ObTxLogType::TX_DIRECT_LOAD_INC_LOG == log_type) { + ObTxCtxLogOperator dli_log_op(this, log_cb); + if (OB_FAIL(dli_log_op(ObTxLogOpType::APPLY_SUCC))) { + TRANS_LOG(WARN, "try to apply direct load inc log failed", K(ret), KPC(this)); + } } else if (ObTxLogType::TX_BIG_SEGMENT_LOG == log_type) { remove_unsynced_segment_cb_(log_cb->get_log_ts()); } else if (ObTxLogType::TX_ACTIVE_INFO_LOG == log_type) { @@ -2663,6 +2672,12 @@ int ObPartTransCtx::on_failure(ObTxLogCb *log_cb) if (is_contain(log_cb->get_cb_arg_array(), ObTxLogType::TX_BIG_SEGMENT_LOG)) { remove_unsynced_segment_cb_(log_cb->get_log_ts()); } + if (ObTxLogType::TX_DIRECT_LOAD_INC_LOG == log_type) { + ObTxCtxLogOperator dli_log_op(this, log_cb); + if (OB_FAIL(dli_log_op(ObTxLogOpType::APPLY_FAIL))) { + TRANS_LOG(WARN, "try to apply direct load inc log failed", K(ret), KPC(this)); + } + } if (ObTxLogType::TX_ROLLBACK_TO_LOG == log_type) { ObTxData *tx_data = log_cb->get_tx_data(); if (OB_FAIL(ctx_tx_data_.free_tmp_tx_data(tx_data))) { @@ -3034,6 +3049,8 @@ int ObPartTransCtx::submit_redo_commit_info_log_(ObTxLogBlock &log_block, TRANS_LOG(WARN, "submit redo log failed", KR(ret), K(*this)); } else if (OB_FAIL(check_dup_trx_with_submitting_all_redo(log_block, helper))) { TRANS_LOG(WARN, "check dup trx with submitting all redo failed", K(ret)); + } else if (OB_FAIL(check_dli_batch_completed_(ObTxLogType::TX_COMMIT_INFO_LOG))) { + TRANS_LOG(WARN, "check direct load inc batch completed", K(ret), KPC(this)); } else if (OB_FAIL(decide_state_log_barrier_type_(ObTxLogType::TX_COMMIT_INFO_LOG, barrier))) { TRANS_LOG(WARN, "decide commit info log barrier failed", K(ret), K(barrier), KPC(this)); } else { @@ -3176,6 +3193,7 @@ int ObPartTransCtx::submit_prepare_log_() ret = OB_TRANS_KILLED; TRANS_LOG(WARN, "tx has been aborting, can not submit prepare log", K(ret)); } + bool contain_commit_info = false; if (OB_SUCC(ret)) { if (!sub_state_.is_info_log_submitted()) { @@ -3443,6 +3461,8 @@ int ObPartTransCtx::submit_commit_log_() if (OB_SUCC(ret)) { if (OB_FAIL(set_start_scn_in_commit_log_(commit_log))) { TRANS_LOG(WARN, "set start scn in commit log failed", K(ret), K(commit_log)); + } else if (OB_FAIL(check_dli_batch_completed_(ObTxLogType::TX_COMMIT_LOG))) { + TRANS_LOG(WARN, "check dli batch completed error", KR(ret), K(*this)); } else if ((exec_info_.multi_data_source_.count() > 0 || mds_cache_.count() > 0) && OB_FAIL(try_alloc_retain_ctx_func_())) { TRANS_LOG(WARN, "alloc retain ctx func for mds trans failed", K(ret), K(mds_cache_), KPC(this)); @@ -3594,11 +3614,13 @@ int ObPartTransCtx::submit_abort_log_() using LogBarrierType = logservice::ObReplayBarrierType; logservice::ObReplayBarrierType barrier = LogBarrierType::NO_NEED_BARRIER; - if (OB_FAIL(mds_cache_.reserve_final_notify_array(exec_info_.multi_data_source_))) { + if (OB_FAIL(check_dli_batch_completed_(ObTxLogType::TX_ABORT_LOG))) { + TRANS_LOG(WARN, "check dli batch completed error", KR(ret), K(*this)); + } else if (OB_FAIL(mds_cache_.reserve_final_notify_array(exec_info_.multi_data_source_))) { TRANS_LOG(WARN, "reserve final notify array failed", K(ret), K(mds_cache_), KPC(this)); } else if (OB_FAIL(mds_cache_.generate_final_notify_array(exec_info_.multi_data_source_, - true /*need_merge_cache*/, - false /*allow_log_overflow*/))) { + true /*need_merge_cache*/, + false /*allow_log_overflow*/))) { TRANS_LOG(WARN, "gen abort mds array failed", K(ret)); } @@ -3739,6 +3761,183 @@ int ObPartTransCtx::submit_record_log_() return ret; } +template +int ObPartTransCtx::submit_direct_load_inc_log_( + DLI_LOG &dli_log, + const ObTxDirectLoadIncLog::DirectLoadIncLogType dli_log_type, + const ObDDLIncLogBasic &batch_key, + logservice::AppendCb *extra_cb, + const logservice::ObReplayBarrierType replay_barrier, + const int64_t replay_hint, + share::SCN &scn, + bool need_free_extra_cb) +{ + + int ret = OB_SUCCESS; + + ObTxLogBlock log_block; + + ObTxDLIncLogBuf dli_buf; + ObTxDirectLoadIncLog::ConstructArg construct_arg(dli_log_type, batch_key, dli_buf); + + ObTxDirectLoadIncLog::SubmitArg submit_arg; + submit_arg.reset(); + submit_arg.replay_barrier_type_ = replay_barrier; + submit_arg.replay_hint_ = replay_hint; + submit_arg.log_cb_ = nullptr; + submit_arg.extra_cb_ = extra_cb; + submit_arg.need_free_extra_cb_ = need_free_extra_cb; + submit_arg.base_scn_ = share::SCN::min_scn(); + submit_arg.suggested_buf_size_ = dli_log.get_serialize_size() + 200; + + ObTxCtxLogOperator dli_log_op(this, &log_block, &construct_arg, submit_arg); + if (OB_FAIL(dli_buf.serialize_log_object(&dli_log))) { + TRANS_LOG(WARN, "serialize direct load log failed", K(ret), K(dli_log), K(replay_hint), + KPC(this)); + } else if (OB_FAIL(dli_log_op(ObTxLogOpType::SUBMIT))) { + TRANS_LOG(WARN, "try to submit direct load inc log failed", K(ret), KPC(this)); + } else { + scn = dli_log_op.get_scn(); + } + + TRANS_LOG(INFO, " submit direct load inc log", K(ret), K(get_trans_id()), + K(get_ls_id()), K(dli_log), K(dli_log_type), K(batch_key), K(replay_barrier), + K(replay_hint), K(scn)); + return ret; +} + +int ObPartTransCtx::submit_direct_load_inc_redo_log(storage::ObDDLRedoLog &ddl_redo_log, + logservice::AppendCb *extra_cb, + const int64_t replay_hint, + share::SCN &scn) +{ + common::ObTimeGuard timeguard("ObPartTransCtx::submit_direct_load_inc_redo_log", 1 * 1000 * 1000); // 1s + ObDDLIncLogBasic inc_log_basic; + return submit_direct_load_inc_log_( + ddl_redo_log, ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_REDO, inc_log_basic, extra_cb, + logservice::ObReplayBarrierType::NO_NEED_BARRIER, replay_hint, scn); +} + +int ObPartTransCtx::submit_direct_load_inc_start_log(storage::ObDDLIncStartLog &ddl_start_log, + logservice::AppendCb *extra_cb, + share::SCN &scn) +{ + common::ObTimeGuard timeguard("ObPartTransCtx::submit_direct_load_inc_start_log", 1 * 1000 * 1000); // 1s + ObDDLIncLogBasic inc_log_basic = ddl_start_log.get_log_basic(); + return submit_direct_load_inc_log_( + ddl_start_log, ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START, inc_log_basic, extra_cb, + logservice::ObReplayBarrierType::STRICT_BARRIER, get_trans_id().get_id(), scn); +} + +int ObPartTransCtx::submit_direct_load_inc_commit_log(storage::ObDDLIncCommitLog &ddl_commit_log, + logservice::AppendCb *extra_cb, + share::SCN &scn, + bool need_free_extra_cb) +{ + common::ObTimeGuard timeguard("ObPartTransCtx::submit_direct_load_inc_commit_log", 1 * 1000 * 1000); // 1s + ObDDLIncLogBasic inc_log_basic = ddl_commit_log.get_log_basic(); + return submit_direct_load_inc_log_( + ddl_commit_log, ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END, inc_log_basic, extra_cb, + logservice::ObReplayBarrierType::STRICT_BARRIER, get_trans_id().get_id(), scn, need_free_extra_cb); +} + +int ObPartTransCtx::check_dli_batch_completed_(ObTxLogType submit_log_type) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + + if (exec_info_.dli_batch_set_.size() > 0) { + int64_t need_ddl_end_count = 0; + + ObTxDirectLoadBatchKeyArray unused_batch_key_array; + for (ObDLIBatchSet::iterator iter = exec_info_.dli_batch_set_.begin(); iter != exec_info_.dli_batch_set_.end(); + iter++) { + if (iter->first.need_compensate_ddl_end()) { + TRANS_LOG(INFO, " need compensate ddl end log", K(ret), K(tmp_ret), + K(submit_log_type), K(trans_id_), K(ls_id_), K(iter->first)); + if (ObTxLogType::TX_ABORT_LOG == submit_log_type + || ObTxLogType::TX_COMMIT_INFO_LOG == submit_log_type) { + ObDDLIncCommitLog inc_commit_log; + ObDDLIncCommitClogCb *extra_cb = static_cast( + mtl_malloc(sizeof(ObDDLIncCommitClogCb), "TxExtraCb")); + + share::SCN submitted_scn; + if (OB_ISNULL(extra_cb)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + TRANS_LOG(WARN, "alloc memory failed", K(ret), K(ls_id_), K(trans_id_), + K(submit_log_type)); + } else { + new (extra_cb) ObDDLIncCommitClogCb(); + } + + if (OB_TMP_FAIL(ret)) { + // do nothing + } else if (OB_TMP_FAIL(extra_cb->init(ls_id_, iter->first.get_batch_key()))) { + TRANS_LOG(WARN, "init extra cb failed", K(ret), K(iter->first), K(trans_id_), K(ls_id_)); + extra_cb->~ObDDLIncCommitClogCb(); + mtl_free(extra_cb); + } else if (OB_TMP_FAIL(inc_commit_log.init(iter->first.get_batch_key()))) { + TRANS_LOG(WARN, "init inc commit log failed", K(ret), K(inc_commit_log), K(iter->first), + K(trans_id_), K(ls_id_)); + extra_cb->~ObDDLIncCommitClogCb(); + mtl_free(extra_cb); + } else if (OB_TMP_FAIL( + submit_direct_load_inc_commit_log(inc_commit_log, extra_cb, submitted_scn, true))) { + TRANS_LOG(WARN, "submit direct load inc commit log failed", K(ret), K(inc_commit_log), + KPC(extra_cb), K(submitted_scn), K(trans_id_), K(ls_id_)); + extra_cb->~ObDDLIncCommitClogCb(); + mtl_free(extra_cb); + } else { + } + } + + if (iter->first.need_compensate_ddl_end()) { + need_ddl_end_count += 1; + } + } else if (iter->first.is_ddl_start_logging()) { + need_ddl_end_count += 1; + TRANS_LOG(INFO, "the DDL inc start is logging", K(ret), K(tmp_ret), K(iter->first), K(trans_id_), + K(ls_id_)); + } else if (iter->first.is_ddl_end_logging()) { + TRANS_LOG(INFO, "the DDL inc end is logging", K(ret), K(tmp_ret), K(iter->first), + K(trans_id_), K(ls_id_)); + } else if (OB_TMP_FAIL(unused_batch_key_array.push_back(iter->first.get_batch_key()))) { + TRANS_LOG(WARN, "push back unused batch key failed", K(ret), K(tmp_ret), K(submit_log_type), + K(trans_id_), K(ls_id_), K(iter->first)); + } else { + TRANS_LOG(INFO, " Try to remove unused batch info", K(ret), + K(tmp_ret), K(submit_log_type), K(trans_id_), K(ls_id_), K(iter->first), + K(unused_batch_key_array.count())); + } + } + + if (OB_TMP_FAIL(exec_info_.dli_batch_set_.remove_unlog_batch_info(unused_batch_key_array))) { + TRANS_LOG(WARN, "remove unlog batch_info failed", K(ret), K(tmp_ret), K(submit_log_type), + K(trans_id_), K(ls_id_), K(unused_batch_key_array)); + } + + if (OB_SUCC(ret) && need_ddl_end_count > 0) { + if (ObTxLogTypeChecker::is_state_log(submit_log_type) + && submit_log_type != ObTxLogType::TX_ABORT_LOG + && (get_downstream_state() >= ObTxState::REDO_COMPLETE + || submit_log_type != ObTxLogType::TX_CLEAR_LOG)) { + ret = OB_TRANS_NEED_ROLLBACK; + TRANS_LOG(ERROR, " incompleted direct load inc batch info with state log", + K(ret), K(tmp_ret), K(submit_log_type), K(trans_id_), K(ls_id_), + K(need_ddl_end_count)); + } else { + ret = OB_TRANS_CANNOT_BE_KILLED; + TRANS_LOG(WARN, + " The trx can not be finished because of a incompleted " + "direct load inc batch info", + K(ret), K(tmp_ret), K(submit_log_type), K(trans_id_), K(ls_id_), + K(need_ddl_end_count)); + } + } + } + + return ret; +} int ObPartTransCtx::submit_big_segment_log_() { int ret = OB_SUCCESS; diff --git a/src/storage/tx/ob_trans_part_ctx.h b/src/storage/tx/ob_trans_part_ctx.h index f537904a6..b23112c1f 100644 --- a/src/storage/tx/ob_trans_part_ctx.h +++ b/src/storage/tx/ob_trans_part_ctx.h @@ -40,6 +40,7 @@ class ObAddr; namespace storage { struct ObStoreRowLockState; +class ObDDLRedoLog; } namespace transaction @@ -143,6 +144,9 @@ private: const T &tmp_info_; }; +template +class ObTxCtxLogOperator; + // participant transaction context class ObPartTransCtx : public ObTransCtx, public ObTsCbTask, @@ -156,6 +160,8 @@ class ObPartTransCtx : public ObTransCtx, friend class ObTxELRHandler; friend class ObIRetainCtxCheckFunctor; friend class memtable::ObRedoLogGenerator; + template + friend class ObTxCtxLogOperator; public: ObPartTransCtx() : ObTransCtx("participant", ObTransCtxType::PARTICIPANT), ObTsCbTask(), @@ -348,6 +354,8 @@ private: int on_success_ops_(ObTxLogCb * log_cb); void check_and_register_timeout_task_(); int recover_ls_transfer_status_(); + + int check_dli_batch_completed_(ObTxLogType submit_log_type); public: // ======================================================== // newly added for 4.0 @@ -367,6 +375,17 @@ public: // for instant logging and freezing int submit_redo_after_write(const bool force, const ObTxSEQ &write_seq_no); int submit_redo_log_for_freeze(const uint32_t freeze_clock); + int submit_direct_load_inc_redo_log(storage::ObDDLRedoLog &ddl_redo_log, + logservice::AppendCb *extra_cb, + const int64_t replay_hint, + share::SCN &scn); + int submit_direct_load_inc_start_log(storage::ObDDLIncStartLog &ddl_start_log, + logservice::AppendCb *extra_cb, + share::SCN &scn); + int submit_direct_load_inc_commit_log(storage::ObDDLIncCommitLog &ddl_commit_log, + logservice::AppendCb *extra_cb, + share::SCN &scn, + bool need_free_extra_cb = false); int return_redo_log_cb(ObTxLogCb *log_cb); int push_replaying_log_ts(const share::SCN log_ts_ns, const int64_t log_entry_no); int push_replayed_log_ts(const share::SCN log_ts_ns, @@ -520,6 +539,15 @@ private: int submit_pending_log_block_(ObTxLogBlock &log_block, memtable::ObRedoLogSubmitHelper &helper, const logservice::ObReplayBarrierType &barrier); + template + int submit_direct_load_inc_log_(DLI_LOG &dli_log, + const ObTxDirectLoadIncLog::DirectLoadIncLogType dli_log_type, + const ObDDLIncLogBasic &batch_key, + logservice::AppendCb *extra_cb, + const logservice::ObReplayBarrierType replay_barrier, + const int64_t replay_hint, + share::SCN &scn, + bool need_free_extra_cb = false); bool should_switch_to_parallel_logging_(); void switch_to_parallel_logging_(const share::SCN serial_final_scn, const ObTxSEQ max_seq_no); diff --git a/src/storage/tx/ob_trans_service.h b/src/storage/tx/ob_trans_service.h index 510fa1db0..7453ede85 100644 --- a/src/storage/tx/ob_trans_service.h +++ b/src/storage/tx/ob_trans_service.h @@ -73,28 +73,12 @@ class ObAliveServerTracer; namespace storage { -struct ObStoreCtx; -class ObIFreezeCb; -class LeaderActiveArg; -class ObLSService; -class ObLSTxService; +class ObIMemtable; } namespace memtable { -class ObIMemtable; -class ObMemtable; -class ObIMemtableCtx; class ObMemtableCtx; -class ObIMemtableCtxFactory; -} - -namespace rpc -{ -namespace frame -{ -class ObReqTransport; -} } namespace obrpc diff --git a/src/storage/tx/ob_trans_submit_log_cb.cpp b/src/storage/tx/ob_trans_submit_log_cb.cpp index 79abef12f..44c63bee3 100644 --- a/src/storage/tx/ob_trans_submit_log_cb.cpp +++ b/src/storage/tx/ob_trans_submit_log_cb.cpp @@ -107,7 +107,13 @@ void ObTxLogCb::reset() is_dynamic_ = false; cb_arg_array_.reset(); mds_range_.reset(); - //is_callbacking_ = false; + + if (OB_NOT_NULL(extra_cb_) && need_free_extra_cb_) { + mtl_free(extra_cb_); + } + need_free_extra_cb_ = false; + + // is_callbacking_ = false; first_part_scn_.invalid_scn(); } @@ -119,6 +125,12 @@ void ObTxLogCb::reuse() is_callbacked_ = false; cb_arg_array_.reset(); mds_range_.reset(); + + if (OB_NOT_NULL(extra_cb_) && need_free_extra_cb_) { + mtl_free(extra_cb_); + } + need_free_extra_cb_ = false; + first_part_scn_.invalid_scn(); } diff --git a/src/storage/tx/ob_trans_submit_log_cb.h b/src/storage/tx/ob_trans_submit_log_cb.h index 03d4fc9f5..ac3439918 100644 --- a/src/storage/tx/ob_trans_submit_log_cb.h +++ b/src/storage/tx/ob_trans_submit_log_cb.h @@ -74,7 +74,7 @@ class ObTxLogCb : public ObTxBaseLogCb, public common::ObDLinkBase { public: - ObTxLogCb() { reset(); } + ObTxLogCb() : extra_cb_(nullptr), need_free_extra_cb_(false) { reset(); } ~ObTxLogCb() { destroy(); } int init(const share::ObLSID &key, const ObTransID &trans_id, @@ -109,6 +109,18 @@ public: int64_t get_execute_hint() { return trans_id_.hash(); } ObTxMDSRange &get_mds_range() { return mds_range_; } + void set_ddl_log_type(const ObTxDirectLoadIncLog::DirectLoadIncLogType ddl_log_type) + { + ddl_log_type_ = ddl_log_type; + } + ObTxDirectLoadIncLog::DirectLoadIncLogType get_ddl_log_type() { return ddl_log_type_; } + void set_ddl_batch_key(const storage::ObDDLIncLogBasic &batch_key) { dli_batch_key_ = batch_key; } + const storage::ObDDLIncLogBasic &get_batch_key() { return dli_batch_key_; } + + void set_extra_cb(logservice::AppendCb *extra_cb) { extra_cb_ = extra_cb; } + logservice::AppendCb *get_extra_cb() { return extra_cb_; } + void set_need_free_extra_cb() { need_free_extra_cb_ = true; } + bool need_free_extra_cb() { return need_free_extra_cb_; } void set_first_part_scn(const share::SCN &first_part_scn) { first_part_scn_ = first_part_scn; } share::SCN get_first_part_scn() const { return first_part_scn_; } @@ -128,6 +140,8 @@ public: K(mds_range_), K(cb_arg_array_), K(first_part_scn_), + KP(extra_cb_), + K(need_free_extra_cb_), K(callbacks_.count())); private: DISALLOW_COPY_AND_ASSIGN(ObTxLogCb); @@ -143,6 +157,10 @@ private: ObTxMDSRange mds_range_; ObTxCbArgArray cb_arg_array_; share::SCN first_part_scn_; + ObTxDirectLoadIncLog::DirectLoadIncLogType ddl_log_type_; + storage::ObDDLIncLogBasic dli_batch_key_; + logservice::AppendCb * extra_cb_; + bool need_free_extra_cb_; //bool is_callbacking_; }; diff --git a/src/storage/tx/ob_tx_log.cpp b/src/storage/tx/ob_tx_log.cpp index b822f0cf4..9b605531d 100644 --- a/src/storage/tx/ob_tx_log.cpp +++ b/src/storage/tx/ob_tx_log.cpp @@ -351,6 +351,8 @@ OB_TX_SERIALIZE_MEMBER(ObTxRollbackToLog, compat_bytes_, /* 1 */ from_, /* 2 */ OB_TX_SERIALIZE_MEMBER(ObTxMultiDataSourceLog, compat_bytes_, /* 1 */ data_); +OB_TX_SERIALIZE_MEMBER(ObTxDirectLoadIncLog, compat_bytes_, /* 1 */ ddl_log_type_, /* 2 */ log_buf_); + int ObTxActiveInfoLog::before_serialize() { int ret = OB_SUCCESS; @@ -603,6 +605,29 @@ int ObTxMultiDataSourceLog::before_serialize() return ret; } +int ObTxDirectLoadIncLog::before_serialize() +{ + int ret = OB_SUCCESS; + + if (compat_bytes_.is_inited()) { + if (OB_FAIL(compat_bytes_.set_all_member_need_ser())) { + TRANS_LOG(WARN, "reset all compat_bytes_ valid failed", K(ret)); + } + } else { + if (OB_FAIL(compat_bytes_.init(2))) { + TRANS_LOG(WARN, "init compat_bytes_ failed", K(ret)); + } + } + + if (OB_SUCC(ret)) { + TX_NO_NEED_SER(false, 1, compat_bytes_); + TX_NO_NEED_SER(false, 2, compat_bytes_); + } + + return ret; +} + + // ============================== Tx Log Body =========================== const ObTxLogType ObTxRedoLog::LOG_TYPE = ObTxLogType::TX_REDO_LOG; @@ -617,6 +642,7 @@ const ObTxLogType ObTxRecordLog::LOG_TYPE = ObTxLogType::TX_RECORD_LOG; const ObTxLogType ObTxStartWorkingLog::LOG_TYPE = ObTxLogType::TX_START_WORKING_LOG; const ObTxLogType ObTxRollbackToLog::LOG_TYPE = ObTxLogType::TX_ROLLBACK_TO_LOG; const ObTxLogType ObTxMultiDataSourceLog::LOG_TYPE = ObTxLogType::TX_MULTI_DATA_SOURCE_LOG; +const ObTxLogType ObTxDirectLoadIncLog::LOG_TYPE = ObTxLogType::TX_DIRECT_LOAD_INC_LOG; int ObTxRedoLog::set_mutator_buf(char *buf) { @@ -910,6 +936,67 @@ int ObTxMultiDataSourceLog::fill_MDS_data(const ObTxBufferNode &node) return ret; } +int64_t ObTxDLIncLogBuf::get_serialize_size() const +{ + return serialization::encoded_length(dli_buf_size_) + dli_buf_size_; +} + +int ObTxDLIncLogBuf::serialize(char *buf, const int64_t buf_len, int64_t &pos) const +{ + int ret = OB_SUCCESS; + int64_t tmp_pos = pos; + if (OB_ISNULL(submit_buf_) || dli_buf_size_ <= 0) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid argument", KP(submit_buf_), K(dli_buf_size_)); + } else if (OB_FAIL(serialization::encode_vi64(buf, buf_len, tmp_pos, dli_buf_size_))) { + TRANS_LOG(WARN, "encode buf size failed", K(ret), KP(buf), K(buf_len), K(tmp_pos), KPC(this)); + } else if (tmp_pos + dli_buf_size_ > buf_len) { + ret = OB_SIZE_OVERFLOW; + TRANS_LOG(WARN, "the log buf is not enough", K(ret), KP(buf), K(buf_len), K(tmp_pos), + KPC(this)); + } else { + memcpy(buf + tmp_pos, submit_buf_, dli_buf_size_); +#ifdef ENABLE_DEBUG_LOG + // TRANS_LOG(INFO, "after serialize buf_size", K(ret), KP(buf), + // KP(submit_buf_), K(tmp_pos), K(pos), K(dli_buf_size_),KPHEX(submit_buf_,dli_buf_size_),KPHEX(buf+tmp_pos,dli_buf_size_ )); +#endif + tmp_pos = tmp_pos + dli_buf_size_; + } + + if (OB_SUCC(ret)) { + pos = tmp_pos; + } + + return ret; +} + +int ObTxDLIncLogBuf::deserialize(const char *buf, const int64_t data_len, int64_t &pos) +{ + int ret = OB_SUCCESS; + int64_t tmp_pos = pos; + if (OB_FAIL(serialization::decode_vi64(buf, data_len, tmp_pos, &dli_buf_size_))) { + TRANS_LOG(WARN, "deserialize direct_load_inc buf_size failed", K(ret), KP(buf), K(data_len), + K(tmp_pos), KPC(this)); + } else if (tmp_pos + dli_buf_size_ > data_len) { + ret = OB_SIZE_OVERFLOW; + TRANS_LOG(WARN, "the log buf is not enough", K(ret), KP(buf), K(data_len), K(tmp_pos), + KPC(this)); + } else { + replay_buf_ = buf + tmp_pos; +#ifdef ENABLE_DEBUG_LOG + // TRANS_LOG(INFO, "after deserialize buf_size", K(ret), KP(buf), + // KP(replay_buf_), K(tmp_pos), K(pos), K(dli_buf_size_), KPHEX(replay_buf_,dli_buf_size_)); +#endif + tmp_pos = tmp_pos + dli_buf_size_; + } + + if (OB_SUCC(ret)) { + pos = tmp_pos; + } + + return ret; +} + OB_SERIALIZE_MEMBER(ObTxDataBackup, start_log_ts_); int ObTxActiveInfoLog::ob_admin_dump(ObAdminMutatorStringArg &arg) @@ -1060,6 +1147,22 @@ int ObTxRollbackToLog::ob_admin_dump(ObAdminMutatorStringArg &arg) return ret; } +int ObTxDirectLoadIncLog::ob_admin_dump(share::ObAdminMutatorStringArg &arg) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(arg.writer_ptr_)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid arg writer is NULL", K(arg), K(ret)); + } else { + arg.writer_ptr_->dump_key(""); + arg.writer_ptr_->start_object(); + //TODO direct_load_inc + //dump direct_load_inc log_buf as a string in ob_admin log_tool + arg.writer_ptr_->end_object(); + } + return ret; +} + int ObTxMultiDataSourceLog::ob_admin_dump(ObAdminMutatorStringArg &arg) { int ret = OB_SUCCESS; diff --git a/src/storage/tx/ob_tx_log.h b/src/storage/tx/ob_tx_log.h index b5ccf197a..58329987a 100644 --- a/src/storage/tx/ob_tx_log.h +++ b/src/storage/tx/ob_tx_log.h @@ -15,6 +15,7 @@ #include #include "share/ob_ls_id.h" +#include "storage/ddl/ob_ddl_clog.h" #include "storage/tx/ob_trans_define.h" #include "storage/tx/ob_tx_data_define.h" #include "storage/tx/ob_tx_serialization.h" @@ -58,10 +59,15 @@ namespace common class ObDataBuffer; } // namespace common +namespace storage +{ +class ObLSDDLLogHandler; +} + namespace transaction { -// class ObTxLogCb; +class ObTxLogCb; class ObPartTransCtx; typedef int64_t TxID; @@ -75,8 +81,7 @@ enum class ObTxLogType : int64_t TX_REDO_LOG = 0x1, TX_ROLLBACK_TO_LOG = 0x2, TX_MULTI_DATA_SOURCE_LOG = 0x4, - // reserve for other data log - TX_RESERVE_FOR_DATA_LOG = 0x8, + TX_DIRECT_LOAD_INC_LOG = 0x8, TX_ACTIVE_INFO_LOG = 0x10, TX_RECORD_LOG = 0x20, TX_COMMIT_INFO_LOG = 0x40, @@ -136,7 +141,7 @@ static inline ObTxLogType operator|(const ObTxLogType left, const ObTxLogType ri static const ObTxLogType TX_LOG_TYPE_MASK = (ObTxLogType::TX_REDO_LOG | ObTxLogType::TX_ROLLBACK_TO_LOG | ObTxLogType::TX_MULTI_DATA_SOURCE_LOG | - ObTxLogType::TX_RESERVE_FOR_DATA_LOG | + ObTxLogType::TX_DIRECT_LOAD_INC_LOG | ObTxLogType::TX_ACTIVE_INFO_LOG | ObTxLogType::TX_RECORD_LOG | ObTxLogType::TX_COMMIT_INFO_LOG | @@ -148,6 +153,13 @@ static const ObTxLogType TX_LOG_TYPE_MASK = (ObTxLogType::TX_REDO_LOG | class ObTxLogTypeChecker { public: + static bool is_data_log(const ObTxLogType log_type) + { + return ObTxLogType::TX_REDO_LOG == log_type || ObTxLogType::TX_RECORD_LOG == log_type + || ObTxLogType::TX_ROLLBACK_TO_LOG == log_type + || ObTxLogType::TX_MULTI_DATA_SOURCE_LOG == log_type + || ObTxLogType::TX_DIRECT_LOAD_INC_LOG == log_type; + } static bool is_state_log(const ObTxLogType log_type) { return ObTxLogType::TX_PREPARE_LOG == log_type || @@ -377,6 +389,257 @@ private: ObTxBufferNodeArray data_; }; +class ObTxDLIncLogBuf +{ +public: + NEED_SERIALIZE_AND_DESERIALIZE; + + ObTxDLIncLogBuf() : submit_buf_(nullptr), replay_buf_(nullptr), dli_buf_size_(0), is_alloc_(false) + {} + // ObTxDLIncLogBuf(void *buf, const int64_t buf_size) + // : dli_buf_(buf), dli_buf_size_(buf_size), is_alloc_(false) + // {} + + template + int serialize_log_object(const DDL_LOG *ddl_log) + { + int ret = OB_SUCCESS; + if (OB_NOT_NULL(submit_buf_) || dli_buf_size_ > 0 || is_alloc_ || OB_ISNULL(ddl_log)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid arguments", K(ret), KPC(this), KPC(ddl_log)); + } else { + is_alloc_ = true; + dli_buf_size_ = ddl_log->get_serialize_size(); + submit_buf_ = static_cast(share::mtl_malloc(dli_buf_size_, "DLI_TMP_BUF")); + memset(submit_buf_, 0, dli_buf_size_); + int64_t pos = 0; + if (OB_ISNULL(submit_buf_)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + TRANS_LOG(WARN, "alloc memory failed", K(ret), KPC(this), KPC(ddl_log)); + } else if (ddl_log->serialize(static_cast(submit_buf_), dli_buf_size_, pos)) { + TRANS_LOG(WARN, "serialize ddl log buf failed", K(ret), KPC(this), KPC(ddl_log)); + } + + // TRANS_LOG(INFO, "serialize ddl log object", K(ret), KPC(ddl_log), K(pos), + // K(dli_buf_size_)); int tmp_ret = OB_SUCCESS; int64_t tmp_pos = 0; DDL_LOG tmp_ddl_log; if + // (OB_TMP_FAIL(tmp_ddl_log.deserialize(submit_buf_, dli_buf_size_, tmp_pos))) { + // TRANS_LOG(WARN, "deserialize ddl log buf failed", K(ret), K(tmp_ret), KPC(this), + // K(tmp_ddl_log), KPC(ddl_log)); + // } + +#ifdef ENABLE_DEBUG_LOG + TRANS_LOG(INFO, " serialize ddl log object", K(ret), KP(submit_buf_), + K(pos), K(dli_buf_size_), KPC(ddl_log)); +#endif + } + return ret; + } + + template + int deserialize_log_object(DDL_LOG *ddl_log) const + { + int ret = OB_SUCCESS; + int64_t pos = 0; + if (OB_ISNULL(replay_buf_) || dli_buf_size_ <= 0 || OB_ISNULL(ddl_log)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid arguments", K(ret), KPC(this), KPC(ddl_log)); + } else if (OB_FAIL(ddl_log->deserialize(replay_buf_, dli_buf_size_, pos))) { + TRANS_LOG(WARN, "deserialize ddl log buf failed", K(ret), KPC(this), KPC(ddl_log)); + } + +#ifdef ENABLE_DEBUG_LOG + TRANS_LOG(INFO, " deserialize ddl log object", K(ret), KP(replay_buf_), + K(pos), K(dli_buf_size_), KPC(ddl_log)); +#endif + return ret; + } + + const char *get_buf() { return replay_buf_; } + int64_t get_buf_size() { return dli_buf_size_; } + + void reset() + { + if (is_alloc_) { + if (OB_NOT_NULL(submit_buf_)) { + share::mtl_free(submit_buf_); + } + is_alloc_ = false; + } + submit_buf_ = nullptr; + dli_buf_size_ = 0; + } + + ~ObTxDLIncLogBuf() { reset(); } + TO_STRING_KV(KP(submit_buf_), KP(replay_buf_), K(dli_buf_size_), K(is_alloc_)); + +private: + char *submit_buf_; + const char *replay_buf_; + int64_t dli_buf_size_; + + bool is_alloc_; +}; + +class TxSubmitBaseArg +{ +public: + ObTxLogCb *log_cb_; + share::SCN base_scn_; + int64_t replay_hint_; + logservice::ObReplayBarrierType replay_barrier_type_; + int64_t suggested_buf_size_; + bool hold_tx_ctx_ref_; + + TxSubmitBaseArg() { reset(); } + // ~TxSubmitBaseArg() = default; + void reset() + { + log_cb_ = nullptr; + base_scn_.set_invalid(); + replay_hint_ = 0; + replay_barrier_type_ = logservice::ObReplayBarrierType::NO_NEED_BARRIER; + suggested_buf_size_ = 0; + hold_tx_ctx_ref_ = 0; + } + bool is_valid() + { + return log_cb_ != nullptr && base_scn_.is_valid() && replay_hint_ >= 0 + && replay_barrier_type_ != logservice::ObReplayBarrierType::INVALID_BARRIER + && hold_tx_ctx_ref_ >= 0; + } + TO_STRING_KV(KP(log_cb_), + K(base_scn_), + K(replay_hint_), + K(replay_barrier_type_), + K(suggested_buf_size_), + K(hold_tx_ctx_ref_)); +}; + +class TxReplayBaseArg +{ +public: + int64_t part_log_no_; + TxReplayBaseArg() { reset(); } + // ~TxReplayBaseArg() = default; + void reset() { part_log_no_ = -1; } + bool is_valid() { return part_log_no_ > 0; } + TO_STRING_KV(K(part_log_no_)); +}; + +class ObTxDirectLoadIncLog +{ + OB_UNIS_VERSION(1); + +public: + enum class DirectLoadIncLogType + { + UNKNOWN = 0, + DLI_REDO = 1, + DLI_START = 2, + DLI_END = 3 + }; + + class TempRef + { + public: + // empty class, only for template + ObTxDLIncLogBuf dli_log_buf_; + }; + class ConstructArg + { + public: + DirectLoadIncLogType ddl_log_type_; + ObDDLIncLogBasic batch_key_; + ObTxDLIncLogBuf &dli_buf_; + + TO_STRING_KV(K(ddl_log_type_), K(batch_key_), K(dli_buf_)); + + ConstructArg(DirectLoadIncLogType ddl_log_type, + const ObDDLIncLogBasic &batch_key, + ObTxDLIncLogBuf &dli_buf_ref) + : ddl_log_type_(ddl_log_type), batch_key_(batch_key), dli_buf_(dli_buf_ref) + {} + ConstructArg(ObTxDirectLoadIncLog::TempRef &temp_ref) + : ddl_log_type_(DirectLoadIncLogType::UNKNOWN), batch_key_(), + dli_buf_(temp_ref.dli_log_buf_) + {} + }; + class ReplayArg : public oceanbase::transaction::TxReplayBaseArg + { + public: + ObLSDDLLogHandler *ddl_log_handler_ptr_; + DirectLoadIncLogType ddl_log_type_; + ObDDLIncLogBasic batch_key_; + + ReplayArg() { reset(); } + void reset() + { + oceanbase::transaction::TxReplayBaseArg::reset(); + ddl_log_handler_ptr_ = nullptr; + ddl_log_type_ = DirectLoadIncLogType::UNKNOWN; + batch_key_.reset(); + } + INHERIT_TO_STRING_KV("base_replay_arg_", + oceanbase::transaction::TxReplayBaseArg, + KP(ddl_log_handler_ptr_), + K(ddl_log_type_), + K(batch_key_)); + }; + class SubmitArg : public oceanbase::transaction::TxSubmitBaseArg + { + public: + logservice::AppendCb *extra_cb_; + bool need_free_extra_cb_; + + SubmitArg() { reset(); } + void reset() + { + oceanbase::transaction::TxSubmitBaseArg::reset(); + extra_cb_ = nullptr; + need_free_extra_cb_ = false; + } + INHERIT_TO_STRING_KV("base_submit_arg_", + oceanbase::transaction::TxSubmitBaseArg, + KPC(extra_cb_), K(need_free_extra_cb_)); + }; + + ObTxDirectLoadIncLog(const ObTxDirectLoadIncLog::ConstructArg &arg) + : ddl_log_type_(arg.ddl_log_type_), log_buf_(arg.dli_buf_) + { + before_serialize(); + } + + // const ObDDLRedoLog &get_ddl_redo_log() { return ddl_redo_log_; } + + DirectLoadIncLogType get_ddl_log_type() { return ddl_log_type_; } + const ObTxDLIncLogBuf &get_dli_buf() { return log_buf_; } + + int ob_admin_dump(share::ObAdminMutatorStringArg &arg); + + static const ObTxLogType LOG_TYPE; + TO_STRING_KV(K(LOG_TYPE), K(ddl_log_type_), K(log_buf_)); + +public: + int before_serialize(); + +#ifdef ENABLE_DEBUG_LOG + // only for unittest + static int64_t direct_load_inc_submit_log_cnt_; + static int64_t direct_load_inc_apply_log_cnt_; + static int64_t direct_load_inc_submit_log_size_; + static int64_t direct_load_inc_apply_log_size_; + +#endif + +private: + ObTxSerCompatByte compat_bytes_; + + DirectLoadIncLogType ddl_log_type_; + + ObTxDLIncLogBuf &log_buf_; + // ObDDLRedoLog &ddl_redo_log_; +}; + class ObTxActiveInfoLogTempRef { public: ObTxActiveInfoLogTempRef() : scheduler_(), app_trace_id_str_(), proposal_leader_(), xid_() {} diff --git a/src/storage/tx/ob_tx_log_operator.h b/src/storage/tx/ob_tx_log_operator.h new file mode 100644 index 000000000..9e9887cfc --- /dev/null +++ b/src/storage/tx/ob_tx_log_operator.h @@ -0,0 +1,784 @@ +/** + * Copyright (c) 2024 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_TX_LOG_OPERATOR_HEADER +#define OCEANBASE_TX_LOG_OPERATOR_HEADER + +#include "storage/ls/ob_ls_ddl_log_handler.h" +#include "storage/tx/ob_trans_define.h" +#include "storage/tx/ob_trans_part_ctx.h" +#include "storage/tx/ob_tx_log.h" + +namespace oceanbase +{ +namespace transaction +{ + +/**************************************** + * Public TxLog Operator Template + * Begin + ****************************************/ +enum class ObTxLogOpType +{ + SUBMIT, + APPLY_SUCC, + APPLY_FAIL, + REPLAY +}; + +template +class ObTxCtxLogOperator +{ +private: + int construct_log_object_(); + + // submit log function + int prepare_generic_resource_(); + int prepare_special_resource_(); + int submit_prev_log_(); + int insert_into_log_block_(); + int pre_check_for_log_submiting_(); + int submit_log_block_out_(); + int common_submit_log_succ_(); + void after_submit_log_succ_(); + void after_submit_log_fail_(const int submit_ret); + int log_sync_succ_() + { + int ret = OB_NOT_SUPPORTED; + TRANS_LOG(WARN, "empty function of log_sync_succ", K(ret), KPC(this)); + return ret; + } + int log_sync_fail_() + { + int ret = OB_NOT_SUPPORTED; + TRANS_LOG(WARN, "empty function of log_sync_fail", K(ret), KPC(this)); + return ret; + } + + // replay log function + int deserialize_log_() + { + int ret = OB_SUCCESS; + + if (OB_FAIL(construct_log_object_())) { + TRANS_LOG(WARN, "construct log object failed", K(ret), KPC(this)); + } else if (OB_FAIL(log_block_->deserialize_log_body(*log_object_ptr_))) { + TRANS_LOG(WARN, "deserialize log body failed", K(ret), KPC(this)); + } + return ret; + } + int replay_in_ctx_() + { + int ret = OB_SUCCESS; + + return ret; + } + int replay_out_ctx_() + { + int ret = OB_SUCCESS; + + return ret; + } + int replay_fail_out_ctx_() + { + int ret = OB_SUCCESS; + + return ret; + } + int replay_log_() + { + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + if (OB_FAIL(deserialize_log_())) { + TRANS_LOG(WARN, "deserialize the log failed", K(ret), K(tx_ctx_->trans_id_), + K(tx_ctx_->ls_id_), KPC(this)); + } else if (OB_FAIL(replay_out_ctx_())) { + TRANS_LOG(WARN, "replay log out ctx failed", K(ret), K(tx_ctx_->trans_id_), + K(tx_ctx_->ls_id_), KPC(this)); + } else if (OB_FAIL(replay_in_ctx_())) { + TRANS_LOG(WARN, "replay log in ctx failed", K(ret), K(tx_ctx_->trans_id_), K(tx_ctx_->ls_id_), + KPC(this)); + } + + if (OB_FAIL(ret)) { + if (OB_TMP_FAIL(replay_fail_out_ctx_())) { + TRANS_LOG(ERROR, "an error occurred while handling replay failure outside of the tx_ctx ", + K(tmp_ret), K(ret), KPC(this)); + } + } + return ret; + } + +public: + // submit + ObTxCtxLogOperator(ObPartTransCtx *tx_ctx_ptr, + ObTxLogBlock *log_block_ptr, + typename T::ConstructArg *construct_arg, + const typename T::SubmitArg &submit_arg) + : tx_ctx_(tx_ctx_ptr), log_object_ptr_(nullptr), log_block_(log_block_ptr), + construct_arg_(construct_arg), scn_(), lsn_() + { + log_op_arg_.submit_arg_.reset(); + log_op_arg_.submit_arg_ = submit_arg; + }; + + // apply + ObTxCtxLogOperator(ObPartTransCtx *tx_ctx_ptr, ObTxLogCb *log_cb_ptr) + : tx_ctx_(tx_ctx_ptr), log_object_ptr_(nullptr), log_block_(nullptr), construct_arg_(nullptr), + scn_(log_cb_ptr->get_log_ts()), lsn_(log_cb_ptr->get_lsn()) + { + log_op_arg_.submit_arg_.reset(); + log_op_arg_.submit_arg_.log_cb_ = log_cb_ptr; + }; + + // replay + ObTxCtxLogOperator(ObPartTransCtx *tx_ctx_ptr, + ObTxLogBlock *log_block_ptr, + typename T::ConstructArg *construct_arg, + const typename T::ReplayArg &replay_arg, + const share::SCN scn, + const palf::LSN lsn) + : tx_ctx_(tx_ctx_ptr), log_object_ptr_(nullptr), log_block_(log_block_ptr), + construct_arg_(construct_arg), scn_(scn), lsn_(lsn) + { + log_op_arg_.replay_arg_.reset(); + log_op_arg_.replay_arg_ = replay_arg; + }; + + ~ObTxCtxLogOperator() + { + if (OB_NOT_NULL(log_object_ptr_)) { + log_object_ptr_->~T(); + } + }; + + int operator()(const ObTxLogOpType op_type); + + TO_STRING_KV(KPC(construct_arg_), KPC(tx_ctx_), K(scn_), K(lsn_), KPC(log_block_)); + +public: + const share::SCN &get_scn() { return scn_; } + const palf::LSN &get_lsn() { return lsn_; } + +private: + ObPartTransCtx *tx_ctx_; + char log_object_memory_[sizeof(T)]; + T *log_object_ptr_; + ObTxLogBlock *log_block_; + typename T::ConstructArg *construct_arg_; + + share::SCN scn_; + palf::LSN lsn_; + + union LogOpArg + { + typename T::SubmitArg submit_arg_; + typename T::ReplayArg replay_arg_; + + LogOpArg(){}; + ~LogOpArg(){}; + + } log_op_arg_; + // bool retain_in_memory_; TODO: retain prev log in log_block +}; + +template +OB_INLINE int ObTxCtxLogOperator::prepare_generic_resource_() +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(tx_ctx_) || OB_ISNULL(log_block_)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid arguments", K(ret), KPC(this)); + } else if (!log_block_->is_inited()) { + { + CtxLockGuard guard; + if (!tx_ctx_->lock_.is_locked_by_self()) { + tx_ctx_->get_ctx_guard(guard, CtxLockGuard::MODE::CTX); + } + + // From 4.3, we must init the cluster_version_ of the log block header before init the log + // block. + // the log_entry_no will be backfill before log-block to be submitted + log_block_->get_header().init(tx_ctx_->cluster_id_, tx_ctx_->cluster_version_, + INT64_MAX /*log_entry_no*/, tx_ctx_->trans_id_, + tx_ctx_->exec_info_.scheduler_); + } + log_op_arg_.submit_arg_.suggested_buf_size_ = log_op_arg_.submit_arg_.suggested_buf_size_ <= 0 + ? ObTxAdaptiveLogBuf::NORMAL_LOG_BUF_SIZE + : log_op_arg_.submit_arg_.suggested_buf_size_; + if (OB_FAIL(log_block_->init_for_fill(log_op_arg_.submit_arg_.suggested_buf_size_))) { + TRANS_LOG(WARN, "init log block for fill failed", K(ret), KPC(this)); + } + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(tx_ctx_->prepare_log_cb_(false, log_op_arg_.submit_arg_.log_cb_))) { + if (OB_UNLIKELY(OB_TX_NOLOGCB != ret)) { + TRANS_LOG(WARN, "get log cb failed", K(ret), KPC(this)); + } + } else if (OB_FAIL(tx_ctx_->acquire_ctx_ref_())) { + TRANS_LOG(ERROR, "acquire ctx ref failed", KR(ret), K(tx_ctx_->trans_id_), K(tx_ctx_->ls_id_), + KPC(this)); + } else if (OB_FALSE_IT(log_op_arg_.submit_arg_.hold_tx_ctx_ref_ = true)) { + // do nothing + } + + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::prepare_special_resource_() +{ + int ret = OB_SUCCESS; + // do nothing + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::submit_prev_log_() +{ + int ret = OB_SUCCESS; + // do nothing + // TODO submit memtable redo, mds redo, dlc redo, commit info before the prepare + // T::LOG_TYPE + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::construct_log_object_() +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(construct_arg_)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid construct arg pointer", K(ret), KPC(construct_arg_)); + } else { + memset(log_object_memory_, 0, sizeof(T)); + new (log_object_memory_) T(*construct_arg_); + log_object_ptr_ = (T *)(log_object_memory_); + } + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::insert_into_log_block_() +{ + int ret = OB_SUCCESS; + + if (OB_FAIL(log_block_->add_new_log(*log_object_ptr_))) { + if (OB_BUF_NOT_ENOUGH != ret) { + TRANS_LOG(WARN, "add new log failed", KR(ret), KPC(this)); + } else { + TRANS_LOG(DEBUG, "the buffer is not enough in log_block", K(ret), K(tx_ctx_->trans_id_), + K(tx_ctx_->ls_id_), KPC(this)); + } + } + + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::pre_check_for_log_submiting_() +{ + int ret = OB_SUCCESS; + + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::submit_log_block_out_() +{ + int ret = OB_SUCCESS; + bool is_2pc_state_log = false; + + if (tx_ctx_->is_exiting()) { + ret = OB_TRANS_IS_EXITING; + TRANS_LOG(WARN, "the tx ctx is exiting", K(ret), K(T::LOG_TYPE), KPC(tx_ctx_)); + } else if (tx_ctx_->is_force_abort_logging_() + || tx_ctx_->get_downstream_state() == ObTxState::ABORT) { + ret = OB_TRANS_KILLED; + TRANS_LOG(WARN, "tx has been aborting, can not submit log", K(ret), K(T::LOG_TYPE), + KPC(tx_ctx_)); + } else if (tx_ctx_->is_follower_()) { + ret = OB_NOT_MASTER; + TRANS_LOG(WARN, "we can not submit a tx log on the follower", K(ret), K(T::LOG_TYPE), + KPC(tx_ctx_)); + } else if (tx_ctx_->exec_info_.data_complete_ + && tx_ctx_->start_working_log_ts_ > tx_ctx_->exec_info_.max_applying_log_ts_) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(WARN, + "There exists a data completed transaction whose start_working_log_ts_ is greater " + "than any of its log_ts", + K(ret), K(T::LOG_TYPE), KPC(tx_ctx_)); + tx_ctx_->print_trace_log_(); + } else if (ObTxLogTypeChecker::is_data_log(T::LOG_TYPE) + && tx_ctx_->get_downstream_state() >= ObTxState::REDO_COMPLETE) { + ret = OB_STATE_NOT_MATCH; + TRANS_LOG(WARN, "the data log can not be submitted after the commit info log", K(ret), + K(T::LOG_TYPE), KPC(tx_ctx_)); + } else if (OB_UNLIKELY(tx_ctx_->is_2pc_blocking())) { + ret = OB_EAGAIN; + TRANS_LOG(WARN, "tx submit log failed because of 2pc blocking", K(ret), KPC(this)); + // It is safe to merge the intermediate_participants because we will block + // the persistent state machine with is_2pc_blocking. The detailed design + // can be found in the implementation of the merge_intermediate_participants. + } else if (is_contain_stat_log(log_block_->get_cb_arg_array()) + && FALSE_IT(is_2pc_state_log = true)) { + } else if (is_2pc_state_log && OB_FAIL(tx_ctx_->merge_intermediate_participants())) { + TRANS_LOG(WARN, "fail to merge intermediate participants", K(ret), KPC(this)); + } else { + const int64_t real_replay_hint = log_op_arg_.submit_arg_.replay_hint_ > 0 + ? log_op_arg_.submit_arg_.replay_hint_ + : tx_ctx_->trans_id_.get_id(); + log_block_->get_header().set_log_entry_no(tx_ctx_->exec_info_.next_log_entry_no_); + if (OB_FAIL(log_block_->seal(real_replay_hint, log_op_arg_.submit_arg_.replay_barrier_type_))) { + TRANS_LOG(WARN, "seal log block fail", K(ret)); + } else if (OB_SUCC(tx_ctx_->ls_tx_ctx_mgr_->get_ls_log_adapter()->submit_log( + log_block_->get_buf(), log_block_->get_size(), log_op_arg_.submit_arg_.base_scn_, + log_op_arg_.submit_arg_.log_cb_, false))) { + tx_ctx_->busy_cbs_.add_last(log_op_arg_.submit_arg_.log_cb_); + scn_ = log_op_arg_.submit_arg_.log_cb_->get_log_ts(); + lsn_ = log_op_arg_.submit_arg_.log_cb_->get_lsn(); + } + } + + return ret; +} + +template +OB_INLINE int ObTxCtxLogOperator::common_submit_log_succ_() +{ + int ret = OB_SUCCESS; + if (OB_SUCC(ret) + && OB_FAIL(tx_ctx_->update_rec_log_ts_(false /*for_replay*/, share::SCN::invalid_scn()))) { + TRANS_LOG(WARN, "update rec log ts failed", KR(ret), KPC(log_op_arg_.submit_arg_.log_cb_), + K(*this)); + } + if (OB_SUCC(ret)) { + const ObTxCbArgArray &cb_arg_array = log_block_->get_cb_arg_array(); + if (cb_arg_array.count() == 0) { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(ERROR, "cb arg array is empty", K(ret), K(*this)); + } else if (OB_FAIL(log_op_arg_.submit_arg_.log_cb_->get_cb_arg_array().assign(cb_arg_array))) { + TRANS_LOG(WARN, "assign cb arg array failed", K(ret)); + } + } + if (OB_SUCC(ret)) { + if (!tx_ctx_->ctx_tx_data_.get_start_log_ts().is_valid()) { + if (OB_FAIL(tx_ctx_->ctx_tx_data_.set_start_log_ts( + log_op_arg_.submit_arg_.log_cb_->get_log_ts()))) { + TRANS_LOG(WARN, "set tx data start log ts failed", K(ret), K(tx_ctx_->ctx_tx_data_)); + } + } + } + return ret; +} + +template +OB_INLINE void ObTxCtxLogOperator::after_submit_log_succ_() +{} + +template +OB_INLINE void ObTxCtxLogOperator::after_submit_log_fail_(const int submit_ret) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + if (OB_BUF_NOT_ENOUGH == submit_ret) { + // do nothing + // TODO submit prev log block with BUF_NOT_ENOUGH. It will reuse the generic_resource and + // rewrite err_ret. + tmp_ret = OB_NOT_SUPPORTED; + } + + if (submit_ret != OB_BUF_NOT_ENOUGH || tmp_ret != OB_SUCCESS) { + if (OB_NOT_NULL(log_op_arg_.submit_arg_.log_cb_)) { + if (log_op_arg_.submit_arg_.log_cb_->get_prev() != nullptr + || log_op_arg_.submit_arg_.log_cb_->get_next() != nullptr) { + TRANS_LOG(ERROR, "the log cb is not alone", K(submit_ret), K(tmp_ret), + K(tx_ctx_->get_trans_id()), K(tx_ctx_->get_ls_id()), + KPC(log_op_arg_.submit_arg_.log_cb_), K(T::LOG_TYPE), KPC(this)); + } + if (OB_TMP_FAIL(tx_ctx_->return_log_cb_(log_op_arg_.submit_arg_.log_cb_))) { + TRANS_LOG(ERROR, "free the log cb failed", K(submit_ret), K(tmp_ret), + K(tx_ctx_->get_trans_id()), K(tx_ctx_->get_ls_id()), + KPC(log_op_arg_.submit_arg_.log_cb_), K(T::LOG_TYPE), KPC(this)); + } + } + if (log_op_arg_.submit_arg_.hold_tx_ctx_ref_) { + tx_ctx_->release_ctx_ref_(); + } + log_block_->reset(); + } +} + +template +OB_INLINE int ObTxCtxLogOperator::operator()(const ObTxLogOpType op_type) +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + if (op_type == ObTxLogOpType::REPLAY) { + if (OB_FAIL(replay_log_())) { + TRANS_LOG(WARN, "replay log failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } + } else if (op_type == ObTxLogOpType::SUBMIT) { + if (OB_FAIL(prepare_special_resource_())) { + TRANS_LOG(WARN, "prepare special resource failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } else if (OB_FAIL(prepare_generic_resource_())) { + TRANS_LOG(WARN, "prepare generic resource failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } else if (OB_FAIL(construct_log_object_())) { + TRANS_LOG(WARN, "construct log object failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } else if (OB_FAIL(insert_into_log_block_())) { + TRANS_LOG(WARN, "insert tx log into log block failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } else { + CtxLockGuard guard; + if (!tx_ctx_->lock_.is_locked_by_self()) { + tx_ctx_->get_ctx_guard(guard, CtxLockGuard::MODE::CTX); + } + + // TRANS_LOG(INFO, " prepare to submit log",K(ret),KPC(this)); + if (OB_FAIL(pre_check_for_log_submiting_())) { + TRANS_LOG(WARN, "pre check for log submitting",K(ret), K(T::LOG_TYPE), KPC(this)); + } else if (OB_FAIL(submit_log_block_out_())) { + TRANS_LOG(WARN, "submit tx log block into palf failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } else if (OB_TMP_FAIL(common_submit_log_succ_())) { + TRANS_LOG(WARN, "common after_submit_log_succ failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } else { + (void)after_submit_log_succ_(); + tx_ctx_->exec_info_.next_log_entry_no_++; + tx_ctx_->reuse_log_block_(*log_block_); + } + } + + if (OB_FAIL(ret)) { + (void)after_submit_log_fail_(ret); + } + + } else if (op_type == ObTxLogOpType::APPLY_SUCC) { + + if (OB_FAIL(log_sync_succ_())) { + TRANS_LOG(ERROR, "invoke on_success for tx_log failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } + + } else if (op_type == ObTxLogOpType::APPLY_FAIL) { + + if (OB_FAIL(log_sync_fail_())) { + TRANS_LOG(WARN, "invoke on_failure for tx_log failed", K(ret), K(T::LOG_TYPE), KPC(this)); + } + + } else { + ret = OB_ERR_UNEXPECTED; + TRANS_LOG(ERROR, "invalid tx log op type", K(ret), K(op_type), K(T::LOG_TYPE), KPC(this)); + } + return ret; +} + +/**************************************** + * Public TxLog Operator Template + * End + ****************************************/ + +/**************************************** + * Direct Load Inc TxLog Operator + * Begin + ****************************************/ + +template <> +OB_INLINE int ObTxCtxLogOperator::prepare_special_resource_() +{ + int ret = OB_SUCCESS; + CtxLockGuard guard; + if (!tx_ctx_->lock_.is_locked_by_self()) { + tx_ctx_->get_ctx_guard(guard, CtxLockGuard::MODE::CTX); + } + + if (OB_ISNULL(log_op_arg_.submit_arg_.extra_cb_)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid extra_cb", K(ret), KPC(construct_arg_), K(log_op_arg_.submit_arg_)); + } else if (OB_FAIL(tx_ctx_->exec_info_.redo_lsns_.reserve(tx_ctx_->exec_info_.redo_lsns_.count() + + 1))) { + TRANS_LOG(WARN, "reserve memory for redo lsn failed", K(ret)); + } + + return ret; +} + +template <> +OB_INLINE int ObTxCtxLogOperator::pre_check_for_log_submiting_() +{ + int ret = OB_SUCCESS; + + if (construct_arg_->ddl_log_type_ == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START + && OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.before_submit_ddl_start( + construct_arg_->batch_key_))) { + TRANS_LOG(WARN, "register ddl_start key failed", K(ret), KPC(construct_arg_), KPC(this)); + } else if (construct_arg_->ddl_log_type_ == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END + && OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.before_submit_ddl_end( + construct_arg_->batch_key_))) { + TRANS_LOG(WARN, "register ddl_end key failed", K(ret), KPC(construct_arg_), KPC(this)); + } + return ret; +} + +template <> +OB_INLINE void ObTxCtxLogOperator::after_submit_log_succ_() +{ + int ret = OB_SUCCESS; + + if (OB_FAIL( + tx_ctx_->exec_info_.redo_lsns_.push_back(log_op_arg_.submit_arg_.log_cb_->get_lsn()))) { + TRANS_LOG(WARN, "push back redo lsns failed", K(ret), KPC(this), + KPC(log_op_arg_.submit_arg_.log_cb_)); + } else if (construct_arg_->ddl_log_type_ == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START + && OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.submit_ddl_start_succ( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "update ddl_start scn after submit_log failed", K(ret), KPC(construct_arg_), + KPC(this)); + } else if (construct_arg_->ddl_log_type_ == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END + && OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.submit_ddl_end_succ( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "update ddl_end key after submit_log failed", K(ret), KPC(construct_arg_), + KPC(this)); + + } else { + log_op_arg_.submit_arg_.log_cb_->set_extra_cb(log_op_arg_.submit_arg_.extra_cb_); + if (log_op_arg_.submit_arg_.need_free_extra_cb_) { + log_op_arg_.submit_arg_.log_cb_->set_need_free_extra_cb(); + } + log_op_arg_.submit_arg_.log_cb_->set_extra_cb(log_op_arg_.submit_arg_.extra_cb_); + log_op_arg_.submit_arg_.log_cb_->set_ddl_log_type(construct_arg_->ddl_log_type_); + log_op_arg_.submit_arg_.log_cb_->set_ddl_batch_key(construct_arg_->batch_key_); + log_op_arg_.submit_arg_.log_cb_->get_extra_cb()->__set_scn(scn_); + } + TRANS_LOG(INFO, " after submit log succ", K(ret), KPC(this)); +} + +template <> +OB_INLINE int ObTxCtxLogOperator::log_sync_succ_() +{ + int ret = OB_SUCCESS; + + const ObTxDirectLoadIncLog::DirectLoadIncLogType ddl_log_type = + log_op_arg_.submit_arg_.log_cb_->get_ddl_log_type(); + const storage::ObDDLIncLogBasic batch_key = log_op_arg_.submit_arg_.log_cb_->get_batch_key(); + const share::SCN scn = log_op_arg_.submit_arg_.log_cb_->get_log_ts(); + + if (OB_ISNULL(log_op_arg_.submit_arg_.log_cb_) + || OB_ISNULL(log_op_arg_.submit_arg_.log_cb_->get_extra_cb())) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid log_cb or extra_cb", K(ret), K(log_op_arg_.submit_arg_)); + } else if (ddl_log_type == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START + && OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.sync_ddl_start_succ(batch_key, scn))) { + TRANS_LOG(WARN, "update ddl_start key after log_sync_succ failed", K(ret), + KPC(log_op_arg_.submit_arg_.log_cb_)); + } else if (ddl_log_type == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END + && OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.sync_ddl_end_succ(batch_key, scn))) { + TRANS_LOG(WARN, "update ddl_end key after log_sync_succ failed", K(ret), + KPC(log_op_arg_.submit_arg_.log_cb_)); + + } else if (OB_FAIL(log_op_arg_.submit_arg_.log_cb_->get_extra_cb()->on_success())) { + TRANS_LOG(WARN, "invoke the on_success of a extra_cb_ failed", K(ret), + KPC(log_op_arg_.submit_arg_.log_cb_)); + } else { + TRANS_LOG(INFO, " sync log succ", K(ret), KPC(this)); + } + + return ret; +} + +template <> +OB_INLINE int ObTxCtxLogOperator::log_sync_fail_() +{ + int ret = OB_SUCCESS; + const ObTxDirectLoadIncLog::DirectLoadIncLogType ddl_log_type = + log_op_arg_.submit_arg_.log_cb_->get_ddl_log_type(); + if (OB_ISNULL(log_op_arg_.submit_arg_.log_cb_) + || OB_ISNULL(log_op_arg_.submit_arg_.log_cb_->get_extra_cb())) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid log_cb or extra_cb", K(ret), K(log_op_arg_.submit_arg_)); + } else if (OB_FAIL(log_op_arg_.submit_arg_.log_cb_->get_extra_cb()->on_failure())) { + TRANS_LOG(WARN, "invoke the on_failure of a extra_cb_ failed", K(ret), + KPC(log_op_arg_.submit_arg_.log_cb_)); + } else { + CtxLockGuard guard; + if (!tx_ctx_->lock_.is_locked_by_self()) { + tx_ctx_->get_ctx_guard(guard, CtxLockGuard::MODE::CTX); + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (ddl_log_type == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START) { + if (OB_FAIL( + tx_ctx_->exec_info_.dli_batch_set_.sync_ddl_start_fail(construct_arg_->batch_key_))) { + TRANS_LOG(WARN, "update ddl_start key after log_sync_fail failed", K(ret), + KPC(construct_arg_), K(scn_), KPC(tx_ctx_)); + } + } else if (ddl_log_type == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END) { + if (OB_FAIL( + tx_ctx_->exec_info_.dli_batch_set_.sync_ddl_end_fail(construct_arg_->batch_key_))) { + TRANS_LOG(WARN, "update ddl_end key after log_sync_fail failed", K(ret), + KPC(construct_arg_), K(scn_), KPC(tx_ctx_)); + } + } + TRANS_LOG(INFO, " sync log fail", K(ret), KPC(this)); + } + + return ret; +} + +template <> +OB_INLINE int ObTxCtxLogOperator::replay_out_ctx_() +{ + int ret = OB_SUCCESS; + + construct_arg_->ddl_log_type_ = log_object_ptr_->get_ddl_log_type(); + if (OB_ISNULL(log_op_arg_.replay_arg_.ddl_log_handler_ptr_)) { + ret = OB_INVALID_ARGUMENT; + TRANS_LOG(WARN, "invalid argument", K(ret), K(log_op_arg_.replay_arg_)); + } else { + if (log_object_ptr_->get_ddl_log_type() + == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_REDO) { + + storage::ObDDLRedoLog ddl_redo; + if (OB_FAIL(log_object_ptr_->get_dli_buf().deserialize_log_object(&ddl_redo))) { + TRANS_LOG(WARN, "deserialize ddl redo log failed", K(ret), K(ddl_redo), + K(log_op_arg_.replay_arg_)); + } else if (OB_FAIL(log_op_arg_.replay_arg_.ddl_log_handler_ptr_->get_ddl_log_replayer() + .replay_redo(ddl_redo, scn_))) { + TRANS_LOG(WARN, "replay direct_load_inc redo for ddl_log_handler failed", K(ret), + KPC(log_object_ptr_), K(log_op_arg_.replay_arg_)); + } + + } else if (log_object_ptr_->get_ddl_log_type() + == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START) { + + storage::ObDDLIncStartLog ddl_start; + if (OB_FAIL(log_object_ptr_->get_dli_buf().deserialize_log_object(&ddl_start))) { + TRANS_LOG(WARN, "deserialize ddl redo log failed", K(ret), K(ddl_start), + K(log_op_arg_.replay_arg_)); + } else if (OB_FAIL(log_op_arg_.replay_arg_.ddl_log_handler_ptr_->get_ddl_log_replayer() + .replay_inc_start(ddl_start, scn_))) { + TRANS_LOG(WARN, "replay direct_load_inc redo for ddl_log_handler failed", K(ret), + KPC(log_object_ptr_), K(log_op_arg_.replay_arg_)); + } + + construct_arg_->batch_key_ = ddl_start.get_log_basic(); + + } else if (log_object_ptr_->get_ddl_log_type() + == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END) { + + storage::ObDDLIncCommitLog ddl_commit; + if (OB_FAIL(log_object_ptr_->get_dli_buf().deserialize_log_object(&ddl_commit))) { + TRANS_LOG(WARN, "deserialize ddl redo log failed", K(ret), K(ddl_commit), + K(log_op_arg_.replay_arg_)); + } else if (OB_FAIL(log_op_arg_.replay_arg_.ddl_log_handler_ptr_->get_ddl_log_replayer() + .replay_inc_commit(ddl_commit, scn_))) { + TRANS_LOG(WARN, "replay direct_load_inc redo for ddl_log_handler failed", K(ret), + KPC(log_object_ptr_), K(log_op_arg_.replay_arg_)); + } + + construct_arg_->batch_key_ = ddl_commit.get_log_basic(); + } + } + + TRANS_LOG(INFO, " replay out ctx", K(ret), KPC(this), K(log_object_ptr_), + K(log_op_arg_.replay_arg_)); + + return ret; +} + +template <> +OB_INLINE int ObTxCtxLogOperator::replay_fail_out_ctx_() +{ + int ret = OB_SUCCESS; + // TODO direct_load_inc + // replay data into ddl kv? + TRANS_LOG(INFO, " replay fail out ctx", K(ret)); + + return ret; +} + +template <> +OB_INLINE int ObTxCtxLogOperator::replay_in_ctx_() +{ + int ret = OB_SUCCESS; + + CtxLockGuard guard; + if (!tx_ctx_->lock_.is_locked_by_self()) { + tx_ctx_->get_ctx_guard(guard, CtxLockGuard::MODE::CTX); + } + + bool need_replay = true; + if (OB_FAIL(tx_ctx_->check_replay_avaliable_(lsn_, scn_, log_op_arg_.replay_arg_.part_log_no_, + need_replay))) { + TRANS_LOG(INFO, "check replay avaliable failed", K(ret), K(ObTxDirectLoadIncLog::LOG_TYPE), + KPC(this)); + } else if (!need_replay) { + TRANS_LOG(INFO, "need not replay log", KPC(log_object_ptr_), K(log_op_arg_.replay_arg_), + KPC(tx_ctx_)); + } else if (construct_arg_->ddl_log_type_ + == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_START) { + if (OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.before_submit_ddl_start( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "register ddl_start key failed", K(ret), KPC(construct_arg_), K(scn_), + KPC(tx_ctx_)); + } else if (OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.submit_ddl_start_succ( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "update ddl_start key after submit_log failed", K(ret), KPC(construct_arg_), + K(scn_), KPC(tx_ctx_)); + } else if (OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.sync_ddl_start_succ( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "update ddl_start key after log_sync_succ failed", K(ret), + KPC(construct_arg_), K(scn_), KPC(tx_ctx_)); + } + } else if (construct_arg_->ddl_log_type_ == ObTxDirectLoadIncLog::DirectLoadIncLogType::DLI_END) { + if (OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.before_submit_ddl_end(construct_arg_->batch_key_, + scn_))) { + TRANS_LOG(WARN, "register ddl_end key failed", K(ret), KPC(construct_arg_), K(scn_), + KPC(tx_ctx_)); + if (OB_ENTRY_NOT_EXIST == ret || OB_ENTRY_EXIST == ret) { + ret = OB_SUCCESS; + } + } else if (OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.submit_ddl_end_succ( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "update ddl_end key after submit_log failed", K(ret), KPC(construct_arg_), + K(scn_), KPC(tx_ctx_)); + if (OB_ENTRY_NOT_EXIST == ret) { + ret = OB_SUCCESS; + } + + } else if (OB_FAIL(tx_ctx_->exec_info_.dli_batch_set_.sync_ddl_end_succ( + construct_arg_->batch_key_, scn_))) { + TRANS_LOG(WARN, "update ddl_end key after log_sync_succ failed", K(ret), KPC(construct_arg_), + K(scn_), KPC(tx_ctx_)); + if (OB_ENTRY_NOT_EXIST == ret) { + ret = OB_SUCCESS; + } + } + } + + TRANS_LOG(INFO, " replay in ctx", K(ret), KPC(this), K(log_object_ptr_), + K(log_op_arg_.replay_arg_)); + return ret; +} + +/**************************************** + * Direct Load Inc TxLog Operator + * End + ****************************************/ + +} // namespace transaction + +} // namespace oceanbase + +#endif diff --git a/src/storage/tx/ob_tx_replay_executor.cpp b/src/storage/tx/ob_tx_replay_executor.cpp index 966fbc2d0..f3b272794 100644 --- a/src/storage/tx/ob_tx_replay_executor.cpp +++ b/src/storage/tx/ob_tx_replay_executor.cpp @@ -21,6 +21,7 @@ #include "storage/tx/ob_trans_service.h" #include "storage/tx/ob_trans_part_ctx.h" +#include "storage/tx/ob_tx_log_operator.h" #include "storage/tx/ob_tx_replay_executor.h" #include "storage/tx/ob_timestamp_service.h" #include "storage/tx/ob_trans_id_service.h" @@ -224,6 +225,18 @@ int ObTxReplayExecutor::replay_tx_log_(const ObTxLogType log_type) } break; } + case ObTxLogType::TX_DIRECT_LOAD_INC_LOG: { + ObTxDirectLoadIncLog::ReplayArg replay_arg; + replay_arg.part_log_no_ = tx_part_log_no_; + replay_arg.ddl_log_handler_ptr_ = ls_->get_ddl_log_handler(); + ObTxDirectLoadIncLog::TempRef temp_ref; + ObTxDirectLoadIncLog::ConstructArg construct_arg(temp_ref); + ObTxCtxLogOperator dli_log_op(ctx_, &log_block_, &construct_arg, replay_arg, log_ts_ns_, lsn_); + if (OB_FAIL(dli_log_op(ObTxLogOpType::REPLAY))) { + TRANS_LOG(WARN, "[Replay Tx] replay direct load inc log error", KR(ret)); + } + break; + } case ObTxLogType::TX_RECORD_LOG: { if (OB_FAIL(replay_record_())) { TRANS_LOG(WARN, "[Replay Tx] replay record log error", KR(ret)); diff --git a/src/storage/tx/ob_tx_replay_executor.h b/src/storage/tx/ob_tx_replay_executor.h index 2b17f9227..977c1ee98 100644 --- a/src/storage/tx/ob_tx_replay_executor.h +++ b/src/storage/tx/ob_tx_replay_executor.h @@ -132,7 +132,7 @@ private: virtual int replay_one_row_in_memtable_(memtable::ObMutatorRowHeader& row_head, memtable::ObMemtableMutatorIterator *mmi_ptr); int prepare_memtable_replay_(storage::ObStorageTableGuard &w_guard, - memtable::ObIMemtable *&mem_ptr); + ObIMemtable *&mem_ptr); int replay_row_(storage::ObStoreCtx &store_ctx, storage::ObTablet *tablet, memtable::ObMemtableMutatorIterator *mmi_ptr); diff --git a/src/storage/tx_storage/ob_tenant_freezer.cpp b/src/storage/tx_storage/ob_tenant_freezer.cpp index 3139d4b9a..028b19b03 100644 --- a/src/storage/tx_storage/ob_tenant_freezer.cpp +++ b/src/storage/tx_storage/ob_tenant_freezer.cpp @@ -297,7 +297,7 @@ int ObTenantFreezer::tablet_freeze_(ObLS *ls, need_retry = false; retry_times++; if (OB_SUCC(need_rewrite_tablet_meta - ? ls->tablet_freeze_with_rewrite_meta(tablet_id, abs_timeout_ts) + ? ls->tablet_freeze_with_rewrite_meta(tablet_id, nullptr/* result */, abs_timeout_ts) : ls->tablet_freeze(tablet_id, is_sync, abs_timeout_ts))) { } else { current_ts = ObTimeUtil::current_time(); diff --git a/src/storage/tx_table/ob_tx_ctx_memtable.cpp b/src/storage/tx_table/ob_tx_ctx_memtable.cpp index e89457438..6ff4d1686 100644 --- a/src/storage/tx_table/ob_tx_ctx_memtable.cpp +++ b/src/storage/tx_table/ob_tx_ctx_memtable.cpp @@ -201,12 +201,12 @@ int ObTxCtxMemtable::on_memtable_flushed() return get_ls_tx_ctx_mgr()->on_tx_ctx_table_flushed(); } -bool ObTxCtxMemtable::is_frozen_memtable() const +bool ObTxCtxMemtable::is_frozen_memtable() { return ATOMIC_LOAD(&is_frozen_); } -bool ObTxCtxMemtable::is_active_memtable() const +bool ObTxCtxMemtable::is_active_memtable() { return !ATOMIC_LOAD(&is_frozen_); } diff --git a/src/storage/tx_table/ob_tx_ctx_memtable.h b/src/storage/tx_table/ob_tx_ctx_memtable.h index 6b6a01e64..7abdd0a70 100644 --- a/src/storage/tx_table/ob_tx_ctx_memtable.h +++ b/src/storage/tx_table/ob_tx_ctx_memtable.h @@ -37,7 +37,7 @@ namespace storage // // [1]: // [2]: -class ObTxCtxMemtable : public memtable::ObIMemtable, public checkpoint::ObCommonCheckpoint +class ObTxCtxMemtable : public ObIMemtable, public checkpoint::ObCommonCheckpoint { public: ObTxCtxMemtable(); @@ -47,8 +47,8 @@ public: void reset(); int on_memtable_flushed() override; - bool is_frozen_memtable() const override; - bool is_active_memtable() const override; + bool is_frozen_memtable() override; + bool is_active_memtable() override; // ================ INHERITED FROM ObIMemtable =============== // We need to inherient the memtable method for merge process to iterate the diff --git a/src/storage/tx_table/ob_tx_ctx_memtable_mgr.cpp b/src/storage/tx_table/ob_tx_ctx_memtable_mgr.cpp index 74c3b7359..d8598c750 100644 --- a/src/storage/tx_table/ob_tx_ctx_memtable_mgr.cpp +++ b/src/storage/tx_table/ob_tx_ctx_memtable_mgr.cpp @@ -66,23 +66,14 @@ int ObTxCtxMemtableMgr::init(const common::ObTabletID &tablet_id, ls_id_ = ls_id; freezer_ = freezer; t3m_ = t3m; - table_type_ = ObITable::TableType::TX_CTX_MEMTABLE; is_inited_ = true; LOG_INFO("tx ctx memtable mgr init successfully", K(ls_id), K(tablet_id), K(this)); return ret; } -int ObTxCtxMemtableMgr::create_memtable(const SCN last_replay_scn, - const int64_t schema_version, - const SCN newest_clog_checkpoint_scn, - const bool for_replay) +int ObTxCtxMemtableMgr::create_memtable(const CreateMemtableArg &arg) { - UNUSED(last_replay_scn); - UNUSED(schema_version); - UNUSED(newest_clog_checkpoint_scn); - UNUSED(for_replay); - int ret = OB_SUCCESS; ObTableHandleV2 handle; ObITable::TableKey table_key; @@ -132,7 +123,7 @@ int ObTxCtxMemtableMgr::create_memtable(const SCN last_replay_scn, const ObTxCtxMemtable *ObTxCtxMemtableMgr::get_tx_ctx_memtable_(const int64_t pos) const { int ret = OB_SUCCESS; - const memtable::ObIMemtable *imemtable = tables_[get_memtable_idx(pos)]; + const ObIMemtable *imemtable = tables_[get_memtable_idx(pos)]; const ObTxCtxMemtable *memtable = nullptr; if (OB_ISNULL(imemtable)) { ret = OB_NOT_INIT; @@ -186,7 +177,7 @@ int ObTxCtxMemtableMgr::unregister_from_common_checkpoint_(const ObTxCtxMemtable return ret; } -int ObTxCtxMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable, +int ObTxCtxMemtableMgr::release_head_memtable_(ObIMemtable *imemtable, const bool force) { int ret = OB_SUCCESS; diff --git a/src/storage/tx_table/ob_tx_ctx_memtable_mgr.h b/src/storage/tx_table/ob_tx_ctx_memtable_mgr.h index 89f0dc381..ad161c8bd 100644 --- a/src/storage/tx_table/ob_tx_ctx_memtable_mgr.h +++ b/src/storage/tx_table/ob_tx_ctx_memtable_mgr.h @@ -56,16 +56,13 @@ public: virtual void destroy() override; // create_memtable is used for creating the only memtable for CheckpointMgr - virtual int create_memtable(const share::SCN last_replay_scn, - const int64_t schema_version, - const share::SCN newest_clog_checkpoint_scn, - const bool for_replay=false) override; + virtual int create_memtable(const CreateMemtableArg &arg) override; const ObTxCtxMemtable *get_tx_ctx_memtable_(const int64_t pos) const; DECLARE_VIRTUAL_TO_STRING; protected: - virtual int release_head_memtable_(memtable::ObIMemtable *imemtable, + virtual int release_head_memtable_(ObIMemtable *imemtable, const bool force) override; int unregister_from_common_checkpoint_(const ObTxCtxMemtable *memtable); diff --git a/src/storage/tx_table/ob_tx_data_memtable.h b/src/storage/tx_table/ob_tx_data_memtable.h index a4f5babc6..9a74d63fa 100644 --- a/src/storage/tx_table/ob_tx_data_memtable.h +++ b/src/storage/tx_table/ob_tx_data_memtable.h @@ -38,7 +38,7 @@ class ObTxDataTable; // The basic unit that manages tx_data -class ObTxDataMemtable : public memtable::ObIMemtable +class ObTxDataMemtable : public ObIMemtable { private: // The MINI_MERGE of TxDataTable uses recycle_scn to recycle the pre-processed commit versions. But it no need be @@ -255,7 +255,7 @@ public: // ObTxDataMemtable public: /* derived from ObITable */ - virtual bool is_active_memtable() const override { return ObTxDataMemtable::State::ACTIVE == state_; } + virtual bool is_active_memtable() override { return ObTxDataMemtable::State::ACTIVE == state_; } /** * @brief Scan this memtable to flush the tx data @@ -287,7 +287,7 @@ public: /* derived from ObITable */ // not supported virtual int get_frozen_schema_version(int64_t &schema_version) const override; // check if this memtable is frozen - virtual bool is_frozen_memtable() const { return ObTxDataMemtable::State::FROZEN == state_; } + virtual bool is_frozen_memtable() { return ObTxDataMemtable::State::FROZEN == state_; } public: /* derived from ObIMemtable */ virtual int64_t get_occupied_size() const; diff --git a/src/storage/tx_table/ob_tx_data_memtable_mgr.cpp b/src/storage/tx_table/ob_tx_data_memtable_mgr.cpp index bffe0afa4..e23cc6cb3 100644 --- a/src/storage/tx_table/ob_tx_data_memtable_mgr.cpp +++ b/src/storage/tx_table/ob_tx_data_memtable_mgr.cpp @@ -85,7 +85,6 @@ int ObTxDataMemtableMgr::init(const common::ObTabletID &tablet_id, ls_id_ = ls_id; tablet_id_ = tablet_id; t3m_ = t3m; - table_type_ = ObITable::TableType::TX_DATA_MEMTABLE; freezer_ = freezer; tx_data_table_ = tx_table->get_tx_data_table(); ls_tablet_svr_ = ls_handle.get_ls()->get_tablet_svr(); @@ -124,7 +123,7 @@ int ObTxDataMemtableMgr::offline() return ret; } -int ObTxDataMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable, +int ObTxDataMemtableMgr::release_head_memtable_(ObIMemtable *imemtable, const bool force) { int ret = OB_SUCCESS; @@ -152,23 +151,19 @@ int ObTxDataMemtableMgr::release_head_memtable_(memtable::ObIMemtable *imemtable return ret; } -int ObTxDataMemtableMgr::create_memtable(const SCN clog_checkpoint_scn, - const int64_t schema_version, - const SCN newest_clog_checkpoint_scn, - const bool for_replay) +int ObTxDataMemtableMgr::create_memtable(const CreateMemtableArg &arg) { - UNUSED(newest_clog_checkpoint_scn); - UNUSED(for_replay); int ret = OB_SUCCESS; if (IS_NOT_INIT) { ret = OB_NOT_INIT; STORAGE_LOG(WARN, "ObTxDataMemtableMgr has not initialized", K(ret), K_(is_inited)); - } else if (OB_UNLIKELY(schema_version < 0)) { + } else if (OB_UNLIKELY(arg.schema_version_ < 0)) { ret = OB_INVALID_ARGUMENT; - STORAGE_LOG(WARN, "invalid argument", K(ret), K(schema_version)); + STORAGE_LOG(WARN, "invalid argument", K(ret), K(arg.schema_version_)); } else { MemMgrWLockGuard lock_guard(lock_); - if (OB_FAIL(create_memtable_(clog_checkpoint_scn, schema_version, ObTxDataHashMap::DEFAULT_BUCKETS_CNT))) { + if (OB_FAIL( + create_memtable_(arg.clog_checkpoint_scn_, arg.schema_version_, ObTxDataHashMap::DEFAULT_BUCKETS_CNT))) { STORAGE_LOG(WARN, "create memtable fail.", KR(ret)); } else { // create memtable success @@ -209,7 +204,6 @@ int ObTxDataMemtableMgr::create_memtable_(const SCN clog_checkpoint_scn, // create memtable success STORAGE_LOG(INFO, "create tx data memtable done", KR(ret), KPC(tx_data_memtable), KPC(this)); } - return ret; } @@ -428,7 +422,7 @@ int ObTxDataMemtableMgr::get_all_memtables_for_write(ObTxDataMemtableWriteGuard write_guard.reset(); MemMgrRLockGuard lock_guard(lock_); for (int64_t i = memtable_head_; OB_SUCC(ret) && i < memtable_tail_; ++i) { - if (OB_FAIL(write_guard.push_back_table(tables_[get_memtable_idx(i)], t3m_, table_type_))) { + if (OB_FAIL(write_guard.push_back_table(tables_[get_memtable_idx(i)], t3m_))) { STORAGE_LOG(WARN, "push back table to write guard failed", KR(ret), K(ls_id_)); } } diff --git a/src/storage/tx_table/ob_tx_data_memtable_mgr.h b/src/storage/tx_table/ob_tx_data_memtable_mgr.h index 8b4d81ee1..e33bc1c1f 100644 --- a/src/storage/tx_table/ob_tx_data_memtable_mgr.h +++ b/src/storage/tx_table/ob_tx_data_memtable_mgr.h @@ -39,12 +39,13 @@ public: } ~ObTxDataMemtableWriteGuard() { reset(); } - int push_back_table(memtable::ObIMemtable *i_memtable, ObTenantMetaMemMgr *t3m, const ObITable::TableType table_type) + int push_back_table(ObIMemtable *i_memtable, ObTenantMetaMemMgr *t3m) { int ret = OB_SUCCESS; ObTxDataMemtable *tx_data_memtable = nullptr; - if (OB_FAIL(handles_[size_].set_table(static_cast(i_memtable), t3m, table_type))) { - STORAGE_LOG(WARN, "set i memtable to handle failed", KR(ret), KP(i_memtable), KP(t3m), K(table_type)); + if (OB_FAIL(handles_[size_].set_table( + static_cast(i_memtable), t3m, ObITable::TableType::TX_DATA_MEMTABLE))) { + STORAGE_LOG(WARN, "set i memtable to handle failed", KR(ret), KP(i_memtable), KP(t3m)); } else if (OB_FAIL(handles_[size_].get_tx_data_memtable(tx_data_memtable))) { STORAGE_LOG(ERROR, "get tx data memtable from memtable handle failed", KR(ret), K(handles_[size_])); } else if (OB_ISNULL(tx_data_memtable)) { @@ -112,15 +113,12 @@ public: // ObTxDataMemtableMgr /** * @brief Using to create a new active tx data memtable * + * @param[in] schema_version schema_version, not used * @param[in] clog_checkpoint_ts clog_checkpoint_ts, using to init multiversion_start, * base_version and start_scn. The start_scn will be modified if this function is called by * freeze(). - * @param[in] schema_version schema_version, not used */ - virtual int create_memtable(const share::SCN clog_checkpoint_scn, - const int64_t schema_version, - const share::SCN newest_clog_checkpoint_scn, - const bool for_replay=false) override; + virtual int create_memtable(const CreateMemtableArg &arg) override; /** * @brief Get the last tx data memtable in memtable list. * @@ -164,7 +162,7 @@ public: // getter and setter int64_t get_mini_merge_recycle_commit_versions_ts() { return mini_merge_recycle_commit_versions_ts_; } protected: - virtual int release_head_memtable_(memtable::ObIMemtable *imemtable, + virtual int release_head_memtable_(ObIMemtable *imemtable, const bool force); private: // ObTxDataMemtableMgr diff --git a/src/storage/tx_table/ob_tx_data_table.cpp b/src/storage/tx_table/ob_tx_data_table.cpp index 710ebcc20..8c93f888f 100644 --- a/src/storage/tx_table/ob_tx_data_table.cpp +++ b/src/storage/tx_table/ob_tx_data_table.cpp @@ -228,7 +228,8 @@ int ObTxDataTable::online() handle))) { LOG_WARN("get tablet failed", K(ret)); } else if (FALSE_IT(tablet = handle.get_obj())) { - } else if (OB_FAIL(ls_tablet_svr->create_memtable(LS_TX_DATA_TABLET, 0 /* schema_version */))) { + } else if (OB_FAIL(ls_tablet_svr->create_memtable( + LS_TX_DATA_TABLET, 0 /* schema_version */, false /* for_inc_direct_load */, false /*for_replay*/))) { LOG_WARN("failed to create memtable", K(ret)); } else { // load tx data table succeed diff --git a/src/storage/tx_table/ob_tx_table.cpp b/src/storage/tx_table/ob_tx_table.cpp index 1ff4a0f03..f99446ee5 100644 --- a/src/storage/tx_table/ob_tx_table.cpp +++ b/src/storage/tx_table/ob_tx_table.cpp @@ -471,7 +471,8 @@ int ObTxTable::load_tx_ctx_table_() } else if (FALSE_IT(tablet = handle.get_obj())) { } else if (OB_FAIL(tablet->fetch_table_store(table_store_wrapper))) { LOG_WARN("fail to fetch table store", K(ret)); - } else if (OB_FAIL(ls_tablet_svr->create_memtable(LS_TX_CTX_TABLET, 0 /* schema_version */))) { + } else if (OB_FAIL(ls_tablet_svr->create_memtable( + LS_TX_CTX_TABLET, 0 /* schema_version */, false /* for_inc_direct_load */, false /*for_replay*/))) { LOG_WARN("failed to create memtable", K(ret)); } else { const ObSSTableArray &sstables = table_store_wrapper.get_member()->get_minor_sstables(); diff --git a/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc0.csv b/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc0.csv new file mode 100644 index 000000000..d05139f21 --- /dev/null +++ b/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc0.csv @@ -0,0 +1,2 @@ +0,0 +1,1 \ No newline at end of file diff --git a/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc1.csv b/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc1.csv new file mode 100644 index 000000000..074b6784f --- /dev/null +++ b/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc1.csv @@ -0,0 +1,2 @@ +2,2 +3,3 \ No newline at end of file diff --git a/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc2.csv b/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc2.csv new file mode 100644 index 000000000..a0b1d65be --- /dev/null +++ b/tools/deploy/mysql_test/test_suite/direct_load_data/data/misc/load_data_inc2.csv @@ -0,0 +1,2 @@ +4,4 +5,5 \ No newline at end of file diff --git a/unittest/libobcdc/test_ob_cdc_part_trans_resolver.cpp b/unittest/libobcdc/test_ob_cdc_part_trans_resolver.cpp index 8b6c69c21..4f29dad64 100644 --- a/unittest/libobcdc/test_ob_cdc_part_trans_resolver.cpp +++ b/unittest/libobcdc/test_ob_cdc_part_trans_resolver.cpp @@ -92,7 +92,7 @@ using namespace logfetcher; LSFetchCtx *ls_fetch_ctx = NULL; \ ObLogFetcherStartParameters start_paras; \ start_paras.reset(start_ts_ns, start_lsn); \ - EXPECT_EQ(OB_SUCCESS, ls_fetch_mgr.add_ls(tls_id, start_paras, false, \ + EXPECT_EQ(OB_SUCCESS, ls_fetch_mgr.add_ls(tls_id, start_paras, false, false, \ ClientFetchingMode::FETCHING_MODE_INTEGRATED, "|")); \ EXPECT_EQ(OB_SUCCESS, ls_fetch_mgr.get_ls_fetch_ctx(tls_id, ls_fetch_ctx)); \ ObTxLogGenerator log_generator(tenant_id, ls_id, tx_id, cluster_id); diff --git a/unittest/sql/optimizer/storage_perf/ob_storage_perf_data.h b/unittest/sql/optimizer/storage_perf/ob_storage_perf_data.h index 6f6b9f9e1..9ba1cdc2f 100644 --- a/unittest/sql/optimizer/storage_perf/ob_storage_perf_data.h +++ b/unittest/sql/optimizer/storage_perf/ob_storage_perf_data.h @@ -74,7 +74,6 @@ private: storage::ObSSStore ssstore_; memtable::ObMemtable memtable_; blocksstable::ObSSTable *sstable_; - storage::ObPartitionComponentFactory cp_fty_; blocksstable::ObPartitionMeta meta_; storage::ObPartitionStorage storage_; blocksstable::ObDataFile data_file_; diff --git a/unittest/sql/optimizer/storage_perf/ob_storage_perf_read.h b/unittest/sql/optimizer/storage_perf/ob_storage_perf_read.h index 164bc4cc7..55b8ba1f4 100644 --- a/unittest/sql/optimizer/storage_perf/ob_storage_perf_read.h +++ b/unittest/sql/optimizer/storage_perf/ob_storage_perf_read.h @@ -25,7 +25,6 @@ #include "storage/blocksstable/ob_macro_block_marker.h" #include "storage/blocksstable/ob_storage_cache_suite.h" #include "storage/ob_partition_meta.h" -#include "storage/ob_partition_component_factory.h" #include "storage/ob_partition_storage.h" #include "storage/ob_base_storage.h" #include "lib/stat/ob_diagnose_info.h" @@ -225,7 +224,6 @@ private: storage::ObSSStore ssstore_; memtable::ObMemtable memtable_; blocksstable::ObSSTable *sstable_; - storage::ObPartitionComponentFactory cp_fty_; blocksstable::ObPartitionMeta meta_; storage::ObPartitionStorage *storage_; ObRestoreSchema *restore_schema_; diff --git a/unittest/storage/mock_ob_partition_component_factory.h b/unittest/storage/mock_ob_partition_component_factory.h deleted file mode 100644 index 1899fd7fa..000000000 --- a/unittest/storage/mock_ob_partition_component_factory.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * 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 MOCK_OB_PARTITION_COMPONENT_FACTORY_H_ -#define MOCK_OB_PARTITION_COMPONENT_FACTORY_H_ - -namespace oceanbase -{ -namespace storage -{ - -class MockObIPartitionComponentFactory : public ObIPartitionComponentFactory -{ -public: - - MOCK_METHOD1(get_ls, - ObLS * (const uint64_t tenant_id)); - MOCK_METHOD1(get_partition, - ObIPartitionGroup * (const uint64_t tenant_id)); - MOCK_METHOD0(get_ssstore, - ObSSStore * ()); - MOCK_METHOD0(get_trans_service, - transaction::ObTransService * ()); - MOCK_METHOD0(get_clog_mgr, - clog::ObICLogMgr * ()); - MOCK_METHOD0(get_partition_service, - ObPartitionService * ()); - MOCK_METHOD0(get_election_mgr, - election::ObElectionMgr * ()); - MOCK_METHOD1(get_log_service, - clog::ObIPartitionLogService * (const uint64_t tenant_id)); - MOCK_METHOD0(get_replay_engine_wrapper, - clog::ObLogReplayEngineWrapper * ()); - - MOCK_METHOD1(free, - void(ObIPartitionGroup *partition)); - MOCK_METHOD1(free, - void(ObReplayStatus *status)); - MOCK_METHOD1(free, - void(ObSSStore *store)); - MOCK_METHOD1(free, - void(transaction::ObTransService *txs)); - MOCK_METHOD1(free, - void(clog::ObICLogMgr *clog_mgr)); - MOCK_METHOD1(free, - void(ObPartitionService *ptt_service)); - MOCK_METHOD1(free, - void(replayengine::ObILogReplayEngine *rp_eg)); - MOCK_METHOD1(free, - void(oceanbase::election::ObIElectionMgr *election_mgr)); - MOCK_METHOD1(free, - void(clog::ObIPartitionLogService *log_service)); - MOCK_METHOD1(free, - void(clog::ObLogReplayEngineWrapper *rp_eg)); -}; - -} // namespace storage -} // namespace oceanbase - -#endif diff --git a/unittest/storage/mockcontainer/mock_ob_partition_service.h b/unittest/storage/mockcontainer/mock_ob_partition_service.h index d2de1a8e5..629adfed3 100644 --- a/unittest/storage/mockcontainer/mock_ob_partition_service.h +++ b/unittest/storage/mockcontainer/mock_ob_partition_service.h @@ -27,7 +27,6 @@ #include "common/storage/ob_freeze_define.h" #include "storage/tx/ob_trans_define.h" #include "storage/tx/ob_trans_service.h" -#include "storage/ob_i_partition_component_factory.h" #include "sql/ob_end_trans_callback.h" namespace oceanbase @@ -56,9 +55,8 @@ public: MOCK_METHOD0(force_refresh_locality_info, int()); - MOCK_METHOD6(init, + MOCK_METHOD5(init, int(const blocksstable::ObStorageEnv &env, const common::ObAddr &self_addr, - ObIPartitionComponentFactory *cp_fty, share::schema::ObMultiVersionSchemaService *schema_service, share::ObRsMgr *rs_mgr, rpc::frame::ObReqTransport *req_transport)); diff --git a/unittest/storage/mockcontainer/mock_ob_server.h b/unittest/storage/mockcontainer/mock_ob_server.h index 19f1ada39..930793acb 100644 --- a/unittest/storage/mockcontainer/mock_ob_server.h +++ b/unittest/storage/mockcontainer/mock_ob_server.h @@ -19,7 +19,6 @@ #include "share/ob_rs_mgr.h" #include "share/ob_srv_rpc_proxy.h" #include "storage/blocksstable/ob_block_sstable_struct.h" -#include "storage/ob_partition_component_factory.h" #include "storage/tx/ob_gts_rpc.h" #include "sql/session/ob_sql_session_mgr.h" #include "observer/ob_srv_network_frame.h" @@ -105,7 +104,6 @@ public: protected: bool is_inited_; protected: - ObPartitionComponentFactory partition_cfy_; //MockObSchemaService schema_service_; ObRestoreSchema restore_schema_; MockSchemaService *schema_service_; diff --git a/unittest/storage/perf_external_sort.cpp b/unittest/storage/perf_external_sort.cpp index c52cc015b..18a1ada23 100644 --- a/unittest/storage/perf_external_sort.cpp +++ b/unittest/storage/perf_external_sort.cpp @@ -15,7 +15,6 @@ #include "storage/blocksstable/ob_sstable.h" #include "storage/ob_partition_scheduler.h" -#include "storage/ob_partition_component_factory.h" #include "storage/blocksstable/ob_macro_block_writer.h" #include "storage/ob_store_row_comparer.h" #include "storage/ob_parallel_external_sort.h" diff --git a/unittest/storage/test_compaction_policy.cpp b/unittest/storage/test_compaction_policy.cpp index d216aa33d..cf9553cd5 100644 --- a/unittest/storage/test_compaction_policy.cpp +++ b/unittest/storage/test_compaction_policy.cpp @@ -63,10 +63,10 @@ void MdsAllocator::free(void *ptr) { } } } -namespace memtable +namespace storage { - bool ObMemtable::can_be_minor_merged() + bool ObITabletMemtable::can_be_minor_merged() { return is_tablet_freeze_; } @@ -346,7 +346,7 @@ int TestCompactionPolicy::mock_memtable( } ObTabletMemtableMgr *mt_mgr = static_cast(protected_handle->memtable_mgr_handle_.get_memtable_mgr()); if (OB_FAIL(ret)) { - } else if (OB_FAIL(t3m->acquire_memtable(table_handle))) { + } else if (OB_FAIL(t3m->acquire_data_memtable(table_handle))) { LOG_WARN("failed to acquire memtable", K(ret)); } else if (OB_ISNULL(memtable = static_cast(table_handle.get_table()))) { ret = OB_ERR_UNEXPECTED; diff --git a/unittest/storage/test_multi_version_sorted_stores.cpp b/unittest/storage/test_multi_version_sorted_stores.cpp deleted file mode 100644 index 59729a5a7..000000000 --- a/unittest/storage/test_multi_version_sorted_stores.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/** - * 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. - */ - -#include -#define private public -#include "storage/ob_multi_version_sorted_stores.h" -#include "storage/ob_ss_store.h" - -namespace oceanbase -{ -using namespace common; -using namespace storage; -using namespace memtable; -namespace unittest -{ - -TEST(ObStoresHandle, simple) -{ - int ret = OB_SUCCESS; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *store = NULL; - - //Invalid argument - ret = stores_handle.add_store(NULL); - ASSERT_NE(OB_SUCCESS, ret); - - //without init - store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_EQ(1L, store->ref_cnt_); - ret = stores_handle.add_store(store); - ASSERT_NE(OB_SUCCESS, ret); - - //normal - stores_handle.init(&cp_fty); - ret = stores_handle.add_store(store); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2L, store->ref_cnt_); - ASSERT_EQ(1L, stores_handle.get_stores().count()); - - ASSERT_EQ(2L, store->ref_cnt_); - stores_handle.reset(); - //allow repeate reset - stores_handle.reset(); - ASSERT_EQ(1L, store->ref_cnt_); - - cp_fty.free(store); -} - -TEST(ObSortedStores, simple) -{ - int ret = OB_SUCCESS; - ObSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObVersion version; - bool merge; - - //invalid use without init - ret = stores.add_store(ss_store); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.remove_store(version); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_write_store(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_base_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_last_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_store(version, stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_read_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_merge_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_ssstores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - - //empty - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - ret = stores.add_store(ss_store); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.remove_store(version); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_write_store(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_base_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_last_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_store(version, stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_read_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_merge_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_ssstores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - - //repeatedly add - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - version.major_ = 1; - ss_store->set_version(version); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = stores.add_store(ss_store); - ASSERT_NE(OB_SUCCESS, ret); - ASSERT_EQ(2L, ss_store->ref_cnt_); - - //invalid handle - ret = stores.get_write_store(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_base_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_last_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_store(version, stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_read_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_merge_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_ssstores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - - //remove - ret = stores.remove_store(version); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1L, ss_store->ref_cnt_); - - cp_fty.free(ss_store); -} - -TEST(ObSortedStores, normal) -{ - int ret = OB_SUCCESS; - ObSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - if (0 == ss_store->dec_ref()) { - cp_fty.free(ss_store); - } - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 0)); - mem_store->minor_freeze(ObVersion(2, 0)); - ret = stores.add_store(mem_store); - if (0 == mem_store->dec_ref()) { - cp_fty.free(mem_store); - } - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 1)); - mem_store->major_freeze(ObVersion(2, 1)); - ret = stores.add_store(mem_store); - if (0 == mem_store->dec_ref()) { - cp_fty.free(mem_store); - } - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 0)); - ret = stores.add_store(mem_store); - if (0 == mem_store->dec_ref()) { - cp_fty.free(mem_store); - } - ASSERT_EQ(OB_SUCCESS, ret); - - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_write_store(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(3, 0), stores_handle.get_stores().at(0)->get_version()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_base_ssstore(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(1, 0), stores_handle.get_stores().at(0)->get_version()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_last_ssstore(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(1, 0), stores_handle.get_stores().at(0)->get_version()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_store(ObVersion(2, 1), stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(2, 1), stores_handle.get_stores().at(0)->get_version()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_read_stores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(4, stores_handle.get_stores().count()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_merge_stores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(3, stores_handle.get_stores().count()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - bool merge = false; - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(2, 0), stores_handle.get_stores().at(0)->get_version()); - ASSERT_EQ(true, merge); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_all_stores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(4, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(1, 0), stores_handle.get_stores().at(0)->get_version()); - - stores_handle.reset(); - stores_handle.init(&cp_fty); - ret = stores.get_all_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores().count()); - ASSERT_EQ(ObVersion(1, 0), stores_handle.get_stores().at(0)->get_version()); -} - -TEST(ObMultiVersionSortedStores, simple) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObVersion version; - bool merge; - - //invalid use without init - ret = stores.add_store(ss_store); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.remove_store(version); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_write_store(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_base_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_last_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_store(version, stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_read_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_merge_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_ssstores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_version_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - - //empty - stores.init(&cp_fty); - ret = stores.add_store(ss_store); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.remove_store(version); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_write_store(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_base_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_last_ssstore(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_store(version, stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_read_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_merge_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_version_stores(stores_handle); - ASSERT_NE(OB_SUCCESS, ret); - ret = stores.get_all_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(0, stores_handle.get_stores().count()); -} - -TEST(ObMultiVersionSortedStores, get_minor_store_major_freeze) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - ObIStore *store = NULL; - bool merge; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - - // only ssstore - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - // ssstore + major frozen memstore + active memstore - mem_store->major_freeze(ObVersion(2, 0)); - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores_count()); - ASSERT_EQ(OB_SUCCESS, stores_handle.get_last_store(store)); - ASSERT_EQ(ObVersion(2, 0), store->get_version()); - ASSERT_EQ(true, merge); -} - -TEST(ObMultiVersionSortedStores, get_minor_store) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - ObIStore *store = NULL; - bool merge; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - - // only ssstore - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(0, stores_handle.get_stores_count()); - ASSERT_EQ(false, merge); - - // ssstore + active memstore - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(0, stores_handle.get_stores_count()); - ASSERT_EQ(false, merge); - - // ssstore + minor frozen memstore + active memstore - mem_store->minor_freeze(ObVersion(2, 0)); - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores_count()); - ASSERT_EQ(OB_SUCCESS, stores_handle.get_last_store(store)); - ASSERT_EQ(ObVersion(2, 0), store->get_version()); - ASSERT_EQ(false, merge); - - // ssstore + minor frozen memstore + major frozen memstore + active memstore - mem_store->major_freeze(ObVersion(2, 1)); - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores_handle.get_stores_count()); - ASSERT_EQ(OB_SUCCESS, stores_handle.get_last_store(store)); - ASSERT_TRUE(NULL != store); - ASSERT_EQ(ObVersion(2, 1), store->get_version()); - ASSERT_EQ(true, merge); -} - -TEST(ObMultiVersionSortedStores, get_minor_store_merged) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - ObIStore *store = NULL; - bool merge; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - - // ssstore + minor merged sstore(major frozen memstore) + minor frozen memstore * 2 + active memstore - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 0)); - mem_store->minor_freeze(ObVersion(3, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 1)); - mem_store->minor_freeze(ObVersion(3, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 2)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores_handle.get_stores_count()); - ASSERT_EQ(OB_SUCCESS, stores_handle.get_last_store(store)); - ASSERT_TRUE(NULL != store); - ASSERT_EQ(ObVersion(3, 1), store->get_version()); - ASSERT_EQ(false, merge); -} - -TEST(ObMultiVersionSortedStores, get_minor_store_not_across_memstore) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - bool merge; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - - // ssstore + minor merged sstore + major frozen memstore + minor frozen memstore + active memstore - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(3, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 1)); - mem_store->major_freeze(ObVersion(3, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(4, 0)); - mem_store->minor_freeze(ObVersion(4, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(4, 1)); - mem_store->minor_freeze(ObVersion(4, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.get_minor_merge_stores(stores_handle, merge); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(0, stores_handle.get_stores_count()); - ASSERT_EQ(false, merge); -} - -TEST(ObMultiVersionSortedStores, prewarm_major_merge) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObSortedStores *new_stores = NULL; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - ASSERT_TRUE(NULL != (new_stores = cp_fty.get_sorted_stores())); - ASSERT_EQ(OB_SUCCESS, new_stores->init(&cp_fty)); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(2, 0)); - ret = new_stores->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores->add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ASSERT_EQ(1, stores.tail_ - stores.head_); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores_count()); - - ret = stores.update(new_stores, MAJOR_MERGE); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores.tail_ - stores.head_); - - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores_handle.get_stores_count()); -} - -TEST(ObMultiVersionSortedStores, prewarm_minor_merge) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObSortedStores *new_stores = NULL; - ObSortedStores *new_stores2 = NULL; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - ASSERT_TRUE(NULL != (new_stores = cp_fty.get_sorted_stores())); - ASSERT_EQ(OB_SUCCESS, new_stores->init(&cp_fty)); - ASSERT_TRUE(NULL != (new_stores2 = cp_fty.get_sorted_stores())); - ASSERT_EQ(OB_SUCCESS, new_stores2->init(&cp_fty)); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores2->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(2, 0)); - ret = new_stores->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores->add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ASSERT_EQ(1, stores.tail_ - stores.head_); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores_count()); - - ret = stores.update(new_stores, MINOR_MERGE); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores.tail_ - stores.head_); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores_handle.get_stores_count()); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(2, 1)); - ret = new_stores2->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 2)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores2->add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.update(new_stores2, MINOR_MERGE); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores.tail_ - stores.head_); - - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(3, stores_handle.get_stores_count()); -} - -TEST(ObMultiVersionSortedStores, prewarm_major_minor_merge) -{ - int ret = OB_SUCCESS; - ObMultiVersionSortedStores stores; - ObStoresHandle stores_handle; - ObSortedStores *new_stores = NULL; - ObSortedStores *new_stores2 = NULL; - ObPartitionComponentFactory cp_fty; - ObSSStore *ss_store = NULL; - ObIMemtable *mem_store = NULL; - - ASSERT_EQ(OB_SUCCESS, stores.init(&cp_fty)); - ASSERT_TRUE(NULL != (new_stores = cp_fty.get_sorted_stores())); - ASSERT_EQ(OB_SUCCESS, new_stores->init(&cp_fty)); - ASSERT_TRUE(NULL != (new_stores2 = cp_fty.get_sorted_stores())); - ASSERT_EQ(OB_SUCCESS, new_stores2->init(&cp_fty)); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(1, 0)); - ret = stores.add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores2->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(2, 0)); - ret = new_stores->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores2->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(2, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores->add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores2->add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ASSERT_EQ(1, stores.tail_ - stores.head_); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(1, stores_handle.get_stores_count()); - - ret = stores.update(new_stores, MINOR_MERGE); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores.tail_ - stores.head_); - ret = stores.get_all_version_ssstores(stores_handle); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(2, stores_handle.get_stores_count()); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 0)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ss_store = cp_fty.get_ssstore(OB_SERVER_TENANT_ID); - ASSERT_TRUE(NULL != ss_store); - ss_store->set_version(ObVersion(3, 0)); - ret = new_stores2->add_store(ss_store); - ASSERT_EQ(OB_SUCCESS, ret); - - mem_store = cp_fty.get_memtable(500); - ASSERT_TRUE(NULL != mem_store); - mem_store->set_version(ObVersion(3, 1)); - ret = stores.add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - ret = new_stores2->add_store(mem_store); - ASSERT_EQ(OB_SUCCESS, ret); - - ret = stores.update(new_stores2, MINOR_MERGE); - ASSERT_EQ(OB_SUCCESS, ret); - ASSERT_EQ(3, stores.tail_ - stores.head_); -} - -} -} - -int main(int argc, char **argv) -{ - OB_LOGGER.set_log_level("INFO"); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/unittest/storage/test_partition_range_splite.cpp b/unittest/storage/test_partition_range_splite.cpp index b82564683..9522db835 100644 --- a/unittest/storage/test_partition_range_splite.cpp +++ b/unittest/storage/test_partition_range_splite.cpp @@ -18,7 +18,6 @@ #include "lib/container/ob_array_array.h" #include "storage/compaction/ob_partition_merger.h" #include "storage/memtable/ob_memtable_interface.h" -#include "storage/ob_partition_component_factory.h" #include "blocksstable/ob_data_file_prepare.h" #include "blocksstable/ob_row_generate.h" #include "observer/ob_service.h" diff --git a/unittest/storage/test_protected_memtable_mgr_handle.cpp b/unittest/storage/test_protected_memtable_mgr_handle.cpp index b6d25d996..72fab58b0 100644 --- a/unittest/storage/test_protected_memtable_mgr_handle.cpp +++ b/unittest/storage/test_protected_memtable_mgr_handle.cpp @@ -78,8 +78,8 @@ TEST_F(TestTabletMemtableMgr, tablet_memtable_mgr) { ASSERT_EQ(0, pool->count_); // create memtable - ASSERT_EQ(OB_SUCCESS, tablet_handle.get_obj()->create_memtable(1, scn1)); - ASSERT_EQ(OB_SUCCESS, tablet_handle.get_obj()->create_memtable(2, scn2)); + ASSERT_EQ(OB_SUCCESS, tablet_handle.get_obj()->create_memtable(1, scn1, false, false)); + ASSERT_EQ(OB_SUCCESS, tablet_handle.get_obj()->create_memtable(2, scn2, false, false)); ObSEArray handles; ASSERT_EQ(OB_SUCCESS, tablet_handle.get_obj()->get_all_memtables(handles)); @@ -106,7 +106,7 @@ TEST_F(TestTabletMemtableMgr, tablet_memtable_mgr) { // remove memtable mgr reference from memtable ASSERT_EQ(1, handles.count()); for (int i = 0; i < handles.count(); i++) { - memtable::ObIMemtable *i_mt = nullptr; + ObIMemtable *i_mt = nullptr; EXPECT_EQ(OB_SUCCESS, handles[i].get_memtable(i_mt)); memtable::ObMemtable *mt = (memtable::ObMemtable *)(i_mt); mt->memtable_mgr_handle_.reset(); diff --git a/unittest/storage/tx/it/tx_node.cpp b/unittest/storage/tx/it/tx_node.cpp index 57d4601d7..512d3fad4 100644 --- a/unittest/storage/tx/it/tx_node.cpp +++ b/unittest/storage/tx/it/tx_node.cpp @@ -129,7 +129,6 @@ ObTxNode::ObTxNode(const int64_t ls_id, lock_memtable_handle.set_table(&lock_memtable_, &t3m_, ObITable::LOCK_MEMTABLE); lock_memtable_.key_.table_type_ = ObITable::LOCK_MEMTABLE; fake_ls_.ls_tablet_svr_.lock_memtable_mgr_.t3m_ = &t3m_; - fake_ls_.ls_tablet_svr_.lock_memtable_mgr_.table_type_ = ObITable::TableType::LOCK_MEMTABLE; fake_ls_.ls_tablet_svr_.lock_memtable_mgr_.add_memtable_(lock_memtable_handle); fake_lock_table_.is_inited_ = true; fake_lock_table_.parent_ = &fake_ls_; diff --git a/unittest/storage/tx_table/test_tx_ctx_table.cpp b/unittest/storage/tx_table/test_tx_ctx_table.cpp index 4fdd65096..67ca70d61 100644 --- a/unittest/storage/tx_table/test_tx_ctx_table.cpp +++ b/unittest/storage/tx_table/test_tx_ctx_table.cpp @@ -201,9 +201,7 @@ int64_t TestTxCtxTable::ref_count_; TEST_F(TestTxCtxTable, test_tx_ctx_memtable_mgr) { EXPECT_EQ(0, TestTxCtxTable::ref_count_); - EXPECT_EQ(OB_SUCCESS, mt_mgr_->create_memtable(SCN::min_scn(), /*last_replay_log_ts*/ - 0 /*schema_version*/, - SCN::min_scn())); + EXPECT_EQ(OB_SUCCESS, mt_mgr_->create_memtable(CreateMemtableArg(0, SCN::min_scn(), SCN::min_scn(), false, false))); EXPECT_EQ(1, TestTxCtxTable::ref_count_);