diff options
| author | Vitaliy Filippov <[email protected]> | 2026-07-07 20:35:06 +0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-07 20:35:06 +0300 |
| commit | 4857ba293db2b6c093addbe3eaffff63fcef813d (patch) | |
| tree | 046d7af60ea38ffdac6491195f25a2361c765a27 | |
| parent | c74bc5e3de9658c03c31dadcb2e6b2c73fb66a00 (diff) | |
Skip unfinished indexes during consistent table copy (and thus export/backup) (#45746)
3 files changed, 69 insertions, 2 deletions
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp index 78f359d1abc..993d05f2bf2 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp @@ -309,11 +309,17 @@ bool CreateConsistentCopyTables( continue; } + Y_ABORT_UNLESS(srcIndexPath.Base()->PathId == pathId); + TTableIndexInfo::TPtr indexInfo = context.SS->Indexes.at(pathId); + if (indexInfo->State != NKikimrSchemeOp::EIndexState::EIndexStateReady) { + LOG_TRACE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, + "CreateConsistentCopyTables: Skipping a non-ready index " << name << " in state " << indexInfo->State); + continue; + } + LOG_TRACE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "CreateConsistentCopyTables: Creating index copy operation for: " << name); - Y_ABORT_UNLESS(srcIndexPath.Base()->PathId == pathId); - TTableIndexInfo::TPtr indexInfo = context.SS->Indexes.at(pathId); auto scheme = CreateIndexTask(indexInfo, dstIndexPath); if (!scheme) { result = {CreateReject(nextId, NKikimrScheme::EStatus::StatusInvalidParameter, diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp index f3186bf3e6f..2cdc2bc3a8f 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp @@ -1047,6 +1047,11 @@ TVector<ISubOperation::TPtr> CreateCopyTable(TOperationId nextId, const TTxTrans Y_ABORT_UNLESS(childPath.Base()->PathId == pathId); TTableIndexInfo::TPtr indexInfo = context.SS->Indexes.at(pathId); + + if (indexInfo->State != NKikimrSchemeOp::EIndexState::EIndexStateReady) { + continue; + } + { auto schema = TransactionTemplate(dstPath.PathString(), NKikimrSchemeOp::EOperationType::ESchemeOpCreateTableIndex); schema.SetFailOnExist(tx.GetFailOnExist()); diff --git a/ydb/core/tx/schemeshard/ut_consistent_copy_tables/ut_consistent_copy_tables.cpp b/ydb/core/tx/schemeshard/ut_consistent_copy_tables/ut_consistent_copy_tables.cpp index 98de0df26a8..0c8b1efcaa2 100644 --- a/ydb/core/tx/schemeshard/ut_consistent_copy_tables/ut_consistent_copy_tables.cpp +++ b/ydb/core/tx/schemeshard/ut_consistent_copy_tables/ut_consistent_copy_tables.cpp @@ -1,4 +1,7 @@ +#include <ydb/public/sdk/cpp/include/ydb-cpp-sdk/client/table/table.h> + #include <ydb/core/base/table_index.h> +#include <ydb/core/testlib/actors/block_events.h> #include <ydb/core/tx/schemeshard/ut_helpers/helpers.h> #include <ydb/core/tx/schemeshard/ut_helpers/local_indexes.h> #include <ydb/core/protos/schemeshard/operations.pb.h> @@ -698,4 +701,57 @@ Y_UNIT_TEST_SUITE(TSchemeShardConsistentCopyTablesTest) { } }); } + + Y_UNIT_TEST(SkipUnfinishedIndex) { + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + SetupLogging(runtime); + + // Create table + TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"( + TableDescription { + Name: "Table1" + Columns { Name: "key" Type: "Uint32" } + Columns { Name: "value" Type: "Utf8" } + KeyColumnNames: ["key"] + } + )"); + env.TestWaitNotification(runtime, txId); + + TBlockEvents<TEvSchemeShard::TEvModifySchemeTransaction> indexBlocker(runtime, [&](const auto& ev) { + const auto& rec = ev->Get()->Record; + return rec.GetTransaction(0).GetOperationType() == NKikimrSchemeOp::ESchemeOpApplyIndexBuild; + }); + + const ui64 buildIndexTx = ++txId; + AsyncBuildIndex(runtime, buildIndexTx, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table1", + TBuildIndexConfig{"index1", NKikimrSchemeOp::EIndexTypeGlobal, {"value"}, {}, {}}); + runtime.WaitFor("Index finalize request", [&]{ return indexBlocker.size(); }); + + // Perform consistent copy with indexes - it should skip the unfinished index + const ui64 copyTx = ++txId; + AsyncConsistentCopyTables(runtime, copyTx, "/MyRoot", R"( + CopyTableDescriptions { + SrcPath: "/MyRoot/Table1" + DstPath: "/MyRoot/TableBackup" + IsBackup: true + } + )"); + env.TestWaitNotification(runtime, copyTx); + + // Let index build finish (it shouldn't fail!) + indexBlocker.Stop().Unblock(); + env.TestWaitNotification(runtime, buildIndexTx); + + auto descr = TestGetBuildIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot", buildIndexTx); + UNIT_ASSERT_VALUES_EQUAL(descr.GetIndexBuild().GetState(), Ydb::Table::IndexBuildState::STATE_DONE); + + // Check that the unfinished index is not copied + TestDescribeResult(DescribePath(runtime, "/MyRoot/TableBackup/index1"), {NLs::PathNotExist}); + + // Check that the table is not left locked by dropping it + TestDropTable(runtime, ++txId, "/MyRoot", "Table1"); + } } |
