diff options
author | ilnaz <ilnaz@ydb.tech> | 2022-08-18 22:10:48 +0300 |
---|---|---|
committer | ilnaz <ilnaz@ydb.tech> | 2022-08-18 22:10:48 +0300 |
commit | 3c53778e01c3bd4a75198c93b4b005fbae4b9bf5 (patch) | |
tree | 45190ecd99eff487d35e0d6f6879d0b11c05936e | |
parent | 83b688fff15469399dba5db3790ceef6ab8399ef (diff) | |
download | ydb-3c53778e01c3bd4a75198c93b4b005fbae4b9bf5.tar.gz |
Ignore backup tables when calculating quotas
13 files changed, 196 insertions, 38 deletions
diff --git a/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp b/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp index d5c39e7d7b..5e45475c9f 100644 --- a/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp @@ -126,7 +126,7 @@ struct TSchemeShard::TTxDeleteTabletReply : public TSchemeShard::TRwTxBase { path->DecShardsInside(); auto domain = Self->ResolveDomainInfo(path); - domain->RemoveInternalShard(ShardIdx); + domain->RemoveInternalShard(ShardIdx, Self->IsBackupTable(pathId)); switch (tabletType) { case ETabletType::SequenceShard: domain->RemoveSequenceShard(ShardIdx); diff --git a/ydb/core/tx/schemeshard/schemeshard__init.cpp b/ydb/core/tx/schemeshard/schemeshard__init.cpp index 4622e908fd..f66a3875e6 100644 --- a/ydb/core/tx/schemeshard/schemeshard__init.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__init.cpp @@ -3680,7 +3680,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> { path->IncShardsInside(); auto domainInfo = Self->ResolveDomainInfo(pathId); //domain should't be dropeed? - domainInfo->AddInternalShard(shardIdx); + domainInfo->AddInternalShard(shardIdx, Self->IsBackupTable(pathId)); switch (si.second.TabletType) { case ETabletType::DataShard: @@ -3776,8 +3776,9 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> { } if (!path->IsRoot()) { - parent->IncAliveChildren(); - inclusivedomainInfo->IncPathsInside(); + const bool isBackupTable = Self->IsBackupTable(item.first); + parent->IncAliveChildren(1, isBackupTable); + inclusivedomainInfo->IncPathsInside(1, isBackupTable); } Self->TabletCounters->Simple()[COUNTER_USER_ATTRIBUTES_COUNT].Add(path->UserAttrs->Size()); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp index 4ef28ff926..cdb777eaed 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp @@ -394,7 +394,7 @@ void NTableState::UpdatePartitioningForCopyTable(TOperationId operationId, TTxSt dstTableInfo->PerShardPartitionConfig.erase(shard.Idx); context.SS->PersistShardDeleted(db, shard.Idx, context.SS->ShardInfos[shard.Idx].BindedChannels); context.SS->ShardInfos.erase(shard.Idx); - domainInfo->RemoveInternalShard(shard.Idx); + domainInfo->RemoveInternalShard(shard.Idx, context.SS->IsBackupTable(pathId)); context.SS->DecrementPathDbRefCount(pathId, "remove shard from txState"); context.SS->ShardRemoved(shard.Idx); } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp index 3f41a88f4e..3d636dd02e 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp @@ -398,6 +398,9 @@ public: const ui32 maxShardsToCreate = srcPath.Shards(); const TString acl = Transaction.GetModifyACL().GetDiffACL(); + auto schema = Transaction.GetCreateTable(); + const bool isBackup = schema.GetIsBackup(); + TPath dstPath = parent.Child(name); { TPath::TChecker checks = dstPath.Check(); @@ -420,13 +423,17 @@ public: checks .IsValidLeafName() .IsTheSameDomain(srcPath) - .PathsLimit() - .DirChildrenLimit() - .ShardsLimit(maxShardsToCreate) .PathShardsLimit(maxShardsToCreate) .IsValidACL(acl); } + if (checks && !isBackup) { + checks + .PathsLimit() + .DirChildrenLimit() + .ShardsLimit(maxShardsToCreate); + } + if (!checks) { TString explain = TStringBuilder() << "path fail checks" << ", path: " << dstPath.PathString(); @@ -479,9 +486,7 @@ public: } } - auto schema = Transaction.GetCreateTable(); const bool omitFollowers = schema.GetOmitFollowers(); - const bool isBackup = schema.GetIsBackup(); PrepareScheme(&schema, name, srcTableInfo, context); schema.SetIsBackup(isBackup); @@ -633,10 +638,10 @@ public: const ui32 shardsToCreate = tableInfo->GetPartitions().size(); Y_VERIFY_S(shardsToCreate <= maxShardsToCreate, "shardsToCreate: " << shardsToCreate << " maxShardsToCreate: " << maxShardsToCreate); - dstPath.DomainInfo()->IncPathsInside(); - dstPath.DomainInfo()->AddInternalShards(txState); + dstPath.DomainInfo()->IncPathsInside(1, isBackup); + dstPath.DomainInfo()->AddInternalShards(txState, isBackup); dstPath.Base()->IncShardsInside(shardsToCreate); - parent.Base()->IncAliveChildren(); + parent.Base()->IncAliveChildren(1, isBackup); State = NextState(); SetState(SelectStateFunc(State)); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp index 2d9e55d2ca..edc660084b 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp @@ -35,11 +35,13 @@ void DropPath(NIceDb::TNiceDb& db, context.SS->TabletCounters->Simple()[COUNTER_USER_ATTRIBUTES_COUNT].Sub(path->UserAttrs->Size()); context.SS->PersistUserAttributes(db, path->PathId, path->UserAttrs, nullptr); + const auto isBackupTable = context.SS->IsBackupTable(path->PathId); + auto domainInfo = context.SS->ResolveDomainInfo(path->PathId); - domainInfo->DecPathsInside(); + domainInfo->DecPathsInside(1, isBackupTable); auto parentDir = path.Parent(); - parentDir->DecAliveChildren(); + parentDir->DecAliveChildren(1, isBackupTable); ++parentDir->DirAlterVersion; context.SS->PersistPathDirAlterVersion(db, parentDir.Base()); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp index 0a6c643789..0a274a19d2 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp @@ -143,15 +143,16 @@ void MarkSrcDropped(NIceDb::TNiceDb& db, const TTxState& txState, TPath& srcPath) { + const auto isBackupTable = context.SS->IsBackupTable(srcPath->PathId); + srcPath.Parent()->DecAliveChildren(1, isBackupTable); + srcPath.DomainInfo()->DecPathsInside(1, isBackupTable); + srcPath->SetDropped(txState.PlanStep, operationId.GetTxId()); context.SS->PersistDropStep(db, srcPath->PathId, txState.PlanStep, operationId); context.SS->Tables.at(srcPath->PathId)->DetachShardsStats(); context.SS->PersistRemoveTable(db, srcPath->PathId, context.Ctx); context.SS->PersistUserAttributes(db, srcPath->PathId, srcPath->UserAttrs, nullptr); - srcPath.Parent()->DecAliveChildren(); - srcPath.DomainInfo()->DecPathsInside(); - IncParentDirAlterVersionWithRepublish(operationId, srcPath, context); } diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp index 49c45cf3ab..d4da387937 100644 --- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp @@ -1234,6 +1234,16 @@ const TTableInfo* TSchemeShard::GetMainTableForIndex(TPathId indexTableId) const return Tables.FindPtr(grandParentId)->Get(); } +bool TSchemeShard::IsBackupTable(TPathId pathId) const { + auto it = Tables.find(pathId); + if (it == Tables.end()) { + return false; + } + + Y_VERIFY(it->second); + return it->second->IsBackup; +} + TPathElement::EPathState TSchemeShard::CalcPathState(TTxState::ETxType txType, TPathElement::EPathState oldState) { // Do not change state if PathId is dropped. It can't become alive. switch (oldState) { @@ -4316,12 +4326,14 @@ void TSchemeShard::MarkAsDroping(TPathElement::TPtr node, TTxId txId, const TAct } void TSchemeShard::UncountNode(TPathElement::TPtr node) { + const auto isBackupTable = IsBackupTable(node->PathId); + if (node->IsDomainRoot()) { - ResolveDomainInfo(node->ParentPathId)->DecPathsInside(); + ResolveDomainInfo(node->ParentPathId)->DecPathsInside(1, isBackupTable); } else { - ResolveDomainInfo(node)->DecPathsInside(); + ResolveDomainInfo(node)->DecPathsInside(1, isBackupTable); } - PathsById.at(node->ParentPathId)->DecAliveChildren(); + PathsById.at(node->ParentPathId)->DecAliveChildren(1, isBackupTable); TabletCounters->Simple()[COUNTER_USER_ATTRIBUTES_COUNT].Sub(node->UserAttrs->Size()); diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h index 6c6be75b96..fe2ab6c568 100644 --- a/ydb/core/tx/schemeshard/schemeshard_impl.h +++ b/ydb/core/tx/schemeshard/schemeshard_impl.h @@ -476,6 +476,7 @@ public: ui64 GetAliveChildren(TPathElement::TPtr pathEl, const std::optional<TPathElement::EPathType>& type = std::nullopt) const; const TTableInfo* GetMainTableForIndex(TPathId indexTableId) const; + bool IsBackupTable(TPathId pathId) const; TPathId ResolvePathIdForDomain(TPathId pathId) const; TPathId ResolvePathIdForDomain(TPathElement::TPtr pathEl) const; diff --git a/ydb/core/tx/schemeshard/schemeshard_info_types.h b/ydb/core/tx/schemeshard/schemeshard_info_types.h index 2b076dbf2d..c094e1540a 100644 --- a/ydb/core/tx/schemeshard/schemeshard_info_types.h +++ b/ydb/core/tx/schemeshard/schemeshard_info_types.h @@ -1369,14 +1369,28 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> { PathsInsideCount = val; } - void IncPathsInside(ui64 delta = 1) { + ui64 GetBackupPaths() const { + return BackupPathsCount; + } + + void IncPathsInside(ui64 delta = 1, bool isBackup = false) { Y_VERIFY(Max<ui64>() - PathsInsideCount >= delta); PathsInsideCount += delta; + + if (isBackup) { + Y_VERIFY(Max<ui64>() - BackupPathsCount >= delta); + BackupPathsCount += delta; + } } - void DecPathsInside(ui64 delta = 1) { + void DecPathsInside(ui64 delta = 1, bool isBackup = false) { Y_VERIFY_S(PathsInsideCount >= delta, "PathsInsideCount: " << PathsInsideCount << " delta: " << delta); PathsInsideCount -= delta; + + if (isBackup) { + Y_VERIFY_S(BackupPathsCount >= delta, "BackupPathsCount: " << BackupPathsCount << " delta: " << delta); + BackupPathsCount -= delta; + } } ui64 GetPQPartitionsInside() const { @@ -1426,6 +1440,10 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> { return InternalShards.size(); } + ui64 GetBackupShards() const { + return BackupShards.size(); + } + void ActualizeAlterData(const THashMap<TShardIdx, TShardInfo>& allShards, TInstant now, bool isExternal, IQuotaCounters* counters) { Y_VERIFY(AlterData); @@ -1600,27 +1618,34 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> { return PrivateShards; } - void AddInternalShard(TShardIdx shardId) { + void AddInternalShard(TShardIdx shardId, bool isBackup = false) { InternalShards.insert(shardId); + if (isBackup) { + BackupShards.insert(shardId); + } } const THashSet<TShardIdx>& GetInternalShards() const { return InternalShards; } - void AddInternalShards(const TTxState& txState) { + void AddInternalShards(const TTxState& txState, bool isBackup = false) { for (auto txShard: txState.Shards) { if (txShard.Operation != TTxState::CreateParts) { continue; } - AddInternalShard(txShard.Idx); + AddInternalShard(txShard.Idx, isBackup); } } - void RemoveInternalShard(TShardIdx shardIdx) { + void RemoveInternalShard(TShardIdx shardIdx, bool isBackup = false) { auto it = InternalShards.find(shardIdx); Y_VERIFY_S(it != InternalShards.end(), "shardIdx: " << shardIdx); InternalShards.erase(it); + + if (isBackup) { + BackupShards.erase(shardIdx); + } } const THashSet<TShardIdx>& GetSequenceShards() const { @@ -1883,9 +1908,11 @@ private: TSchemeQuotas SchemeQuotas; ui64 PathsInsideCount = 0; + ui64 BackupPathsCount = 0; TDiskSpaceUsage DiskSpaceUsage; THashSet<TShardIdx> InternalShards; + THashSet<TShardIdx> BackupShards; THashSet<TShardIdx> SequenceShards; THashSet<TShardIdx> ReplicationControllers; diff --git a/ydb/core/tx/schemeshard/schemeshard_path.cpp b/ydb/core/tx/schemeshard/schemeshard_path.cpp index 3fc23bee5f..d2c908c92e 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_path.cpp @@ -796,8 +796,15 @@ const TPath::TChecker& TPath::TChecker::PathsLimit(ui64 delta, TPath::TChecker:: } TSubDomainInfo::TPtr domainInfo = Path.DomainInfo(); + const auto pathsTotal = domainInfo->GetPathsInside(); + const auto backupPaths = domainInfo->GetBackupPaths(); - if (!delta || domainInfo->GetPathsInside() + delta <= domainInfo->GetSchemeLimits().MaxPaths) { + Y_VERIFY_S(pathsTotal >= backupPaths, "Constraint violation" + << ": path: " << Path.PathString() + << ", paths total: " << pathsTotal + << ", backup paths: " << backupPaths); + + if (!delta || (pathsTotal - backupPaths) + delta <= domainInfo->GetSchemeLimits().MaxPaths) { return *this; } @@ -805,7 +812,8 @@ const TPath::TChecker& TPath::TChecker::PathsLimit(ui64 delta, TPath::TChecker:: Status = status; Explain << "paths count has reached maximum value in the domain" << ", paths limit for domain: " << domainInfo->GetSchemeLimits().MaxPaths - << ", paths count inside domain: " << domainInfo->GetPathsInside() + << ", paths count inside domain: " << pathsTotal + << ", backup paths: " << backupPaths << ", intention to create new paths: " << delta; return *this; } @@ -816,11 +824,16 @@ const TPath::TChecker& TPath::TChecker::DirChildrenLimit(ui64 delta, TPath::TChe } TSubDomainInfo::TPtr domainInfo = Path.DomainInfo(); - auto parent = Path.Parent(); - ui64 aliveChildren = parent.Base()->GetAliveChildren(); + const auto aliveChildren = parent.Base()->GetAliveChildren(); + const auto backupChildren = parent.Base()->GetBackupChildren(); - if (!delta || aliveChildren + delta <= domainInfo->GetSchemeLimits().MaxChildrenInDir) { + Y_VERIFY_S(aliveChildren >= backupChildren, "Constraint violation" + << ": path: " << parent.PathString() + << ", alive children: " << aliveChildren + << ", backup children: " << backupChildren); + + if (!delta || (aliveChildren - backupChildren) + delta <= domainInfo->GetSchemeLimits().MaxChildrenInDir) { return *this; } @@ -829,6 +842,7 @@ const TPath::TChecker& TPath::TChecker::DirChildrenLimit(ui64 delta, TPath::TChe Explain << "children count has reached maximum value in the dir" << ", children limit for domain dir: " << domainInfo->GetSchemeLimits().MaxChildrenInDir << ", children count inside dir: " << aliveChildren + << ", backup children: " << backupChildren << ", intention to create new children: " << delta; return *this; } @@ -839,8 +853,15 @@ const TPath::TChecker& TPath::TChecker::ShardsLimit(ui64 delta, TPath::TChecker: } TSubDomainInfo::TPtr domainInfo = Path.DomainInfo(); + const auto shardsTotal = domainInfo->GetShardsInside(); + const auto backupShards = domainInfo->GetBackupShards(); + + Y_VERIFY_S(shardsTotal >= backupShards, "Constraint violation" + << ": path: " << Path.PathString() + << ", shards total: " << shardsTotal + << ", backup shards: " << backupShards); - if (!delta || domainInfo->GetShardsInside() + delta <= domainInfo->GetSchemeLimits().MaxShards) { + if (!delta || (shardsTotal - backupShards) + delta <= domainInfo->GetSchemeLimits().MaxShards) { return *this; } @@ -848,7 +869,8 @@ const TPath::TChecker& TPath::TChecker::ShardsLimit(ui64 delta, TPath::TChecker: Status = status; Explain << "shards count has reached maximum value in the domain" << ", shards limit for domain: " << domainInfo->GetSchemeLimits().MaxShards - << ", shards count inside domain: " << domainInfo->GetShardsInside() + << ", shards count inside domain: " << shardsTotal + << ", backup shards: " << backupShards << ", intention to create new shards: " << delta; return *this; } diff --git a/ydb/core/tx/schemeshard/schemeshard_path_element.cpp b/ydb/core/tx/schemeshard/schemeshard_path_element.cpp index 09c225372c..a317287412 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path_element.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_path_element.cpp @@ -20,14 +20,28 @@ void TPathElement::SetAliveChildren(ui64 val) { AliveChildrenCount = val; } -void TPathElement::IncAliveChildren(ui64 delta) { +ui64 TPathElement::GetBackupChildren() const { + return BackupChildrenCount; +} + +void TPathElement::IncAliveChildren(ui64 delta, bool isBackup) { Y_VERIFY(Max<ui64>() - AliveChildrenCount >= delta); AliveChildrenCount += delta; + + if (isBackup) { + Y_VERIFY(Max<ui64>() - BackupChildrenCount >= delta); + BackupChildrenCount += delta; + } } -void TPathElement::DecAliveChildren(ui64 delta) { +void TPathElement::DecAliveChildren(ui64 delta, bool isBackup) { Y_VERIFY(AliveChildrenCount >= delta); AliveChildrenCount -= delta; + + if (isBackup) { + Y_VERIFY(BackupChildrenCount >= delta); + BackupChildrenCount -= delta; + } } ui64 TPathElement::GetShardsInside() const { diff --git a/ydb/core/tx/schemeshard/schemeshard_path_element.h b/ydb/core/tx/schemeshard/schemeshard_path_element.h index 499f661130..9844676d02 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path_element.h +++ b/ydb/core/tx/schemeshard/schemeshard_path_element.h @@ -341,14 +341,16 @@ struct TPathElement : TSimpleRefCount<TPathElement> { private: ui64 AliveChildrenCount = 0; + ui64 BackupChildrenCount = 0; ui64 ShardsInsideCount = 0; TChildrenCont Children; public: TPathElement(TPathId pathId, TPathId parentPathId, TPathId domainPathId, const TString& name, const TString& owner); ui64 GetAliveChildren() const; void SetAliveChildren(ui64 val); - void IncAliveChildren(ui64 delta = 1); - void DecAliveChildren(ui64 delta = 1); + ui64 GetBackupChildren() const; + void IncAliveChildren(ui64 delta = 1, bool isBackup = false); + void DecAliveChildren(ui64 delta = 1, bool isBackup = false); ui64 GetShardsInside() const; void SetShardsInside(ui64 val); void IncShardsInside(ui64 delta = 1); diff --git a/ydb/core/tx/schemeshard/ut_base.cpp b/ydb/core/tx/schemeshard/ut_base.cpp index 092492d316..e883604f18 100644 --- a/ydb/core/tx/schemeshard/ut_base.cpp +++ b/ydb/core/tx/schemeshard/ut_base.cpp @@ -3488,6 +3488,13 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { TTestEnv env(runtime); ui64 txId = 100; + // these limits should have no effect on backup tables + TSchemeLimits limits; + limits.MaxPaths = 4; + limits.MaxShards = 4; + limits.MaxChildrenInDir = 3; + SetSchemeshardSchemaLimits(runtime, limits); + // create src table TestCreateTable(runtime, ++txId, "/MyRoot", R"( Name: "Table" @@ -3527,6 +3534,70 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { NLs::IsBackupTable(true), }); + // negative tests + + // shards limit + TestCreateTable(runtime, ++txId, "/MyRoot", R"( + Name: "Table2" + Columns { Name: "key" Type: "Uint32"} + Columns { Name: "value" Type: "Utf8"} + KeyColumnNames: ["key"] + UniformPartitionsCount: 4 + )", {NKikimrScheme::StatusResourceExhausted}); + + // ok + TestCreateTable(runtime, ++txId, "/MyRoot", R"( + Name: "Table2" + Columns { Name: "key" Type: "Uint32"} + Columns { Name: "value" Type: "Utf8"} + KeyColumnNames: ["key"] + )"); + env.TestWaitNotification(runtime, txId); + + TestMkDir(runtime, ++txId, "/MyRoot", "Dir"); + env.TestWaitNotification(runtime, txId); + + // children limit + TestCreateTable(runtime, ++txId, "/MyRoot", R"( + Name: "Table3" + Columns { Name: "key" Type: "Uint32"} + Columns { Name: "value" Type: "Utf8"} + KeyColumnNames: ["key"] + )", {NKikimrScheme::StatusResourceExhausted}); + + // ok + TestCreateTable(runtime, ++txId, "/MyRoot/Dir", R"( + Name: "Table3" + Columns { Name: "key" Type: "Uint32"} + Columns { Name: "value" Type: "Utf8"} + KeyColumnNames: ["key"] + )"); + env.TestWaitNotification(runtime, txId); + + // paths limit + TestCreateTable(runtime, ++txId, "/MyRoot/Dir", R"( + Name: "Table4" + Columns { Name: "key" Type: "Uint32"} + Columns { Name: "value" Type: "Utf8"} + KeyColumnNames: ["key"] + )", {NKikimrScheme::StatusResourceExhausted}); + + // free quota + TestDropTable(runtime, ++txId, "/MyRoot", "Table2"); + env.TestWaitNotification(runtime, txId); + + // ok + TestCreateTable(runtime, ++txId, "/MyRoot/Dir", R"( + Name: "Table4" + Columns { Name: "key" Type: "Uint32"} + Columns { Name: "value" Type: "Utf8"} + KeyColumnNames: ["key"] + )"); + env.TestWaitNotification(runtime, txId); + + // reset limits to default + SetSchemeshardSchemaLimits(runtime, TSchemeLimits()); + // cannot create new table with 'IsBackup' TestCreateTable(runtime, ++txId, "/MyRoot", R"( Name: "TableForBackup" |