Skip to content

Commit d332eed

Browse files
authored
Fix schemeshard crashes on double vector index replace / drop table after index replace (#20501) (#20665)
1 parent e615d9b commit d332eed

File tree

10 files changed

+84
-7
lines changed

10 files changed

+84
-7
lines changed

ydb/core/grpc_services/rpc_rename_tables.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class TRenameTablesRPC : public TRpcSchemeRequestActor<TRenameTablesRPC, TEvRena
3939
auto& transaction = *record.MutableTransaction();
4040

4141
if (req->tables().empty()) {
42-
Request_->RaiseIssue(NYql::TIssue("Emply move list"));
42+
Request_->RaiseIssue(NYql::TIssue("Empty move list"));
4343
return Reply(StatusIds::BAD_REQUEST, ctx);
4444
}
4545

ydb/core/tx/schemeshard/schemeshard__operation_move_index.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,9 @@ TVector<ISubOperation::TPtr> CreateConsistentMoveIndex(TOperationId nextId, cons
597597
for(const auto& implTable : srcIndexPath.Base()->GetChildren()) {
598598
TString srcImplTableName = implTable.first;
599599
TPath srcImplTable = srcIndexPath.Child(srcImplTableName);
600+
if (srcImplTable.IsDeleted()) {
601+
continue;
602+
}
600603

601604
Y_ABORT_UNLESS(srcImplTable.Base()->PathId == implTable.second);
602605

ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ class TMoveTable: public TSubOperation {
716716

717717
if (dstParent.IsUnderOperation()) {
718718
dstPath = TPath::ResolveWithInactive(OperationId, dstPathStr, context.SS);
719+
dstParent = dstPath.Parent();
719720
}
720721

721722
{

ydb/core/tx/schemeshard/schemeshard__operation_move_table_index.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ class TMoveTableIndex: public TSubOperation {
423423

424424
if (dstParentPath.IsUnderOperation()) {
425425
dstPath = TPath::ResolveWithInactive(OperationId, dstPathStr, context.SS);
426+
dstParentPath = dstPath.Parent();
426427
} else {
427428
Y_ABORT("NONO");
428429
}

ydb/core/tx/schemeshard/ut_helpers/helpers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,11 +1924,11 @@ namespace NSchemeShardUT_Private {
19241924
}
19251925

19261926
void TestBuildVectorIndex(TTestActorRuntime& runtime, ui64 id, ui64 schemeShard, const TString &dbName,
1927-
const TString &src, const TString &name, TString column,
1927+
const TString &src, const TString &name, TVector<TString> columns,
19281928
Ydb::StatusIds::StatusCode expectedStatus)
19291929
{
19301930
TestBuildIndex(runtime, id, schemeShard, dbName, src, TBuildIndexConfig{
1931-
name, NKikimrSchemeOp::EIndexTypeGlobalVectorKmeansTree, {column}, {}
1931+
name, NKikimrSchemeOp::EIndexTypeGlobalVectorKmeansTree, columns, {}
19321932
}, expectedStatus);
19331933
}
19341934

ydb/core/tx/schemeshard/ut_helpers/helpers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ namespace NSchemeShardUT_Private {
411411
const TString &src, const TString& columnName, const Ydb::TypedValue& literal, Ydb::StatusIds::StatusCode expectedStatus);
412412
void TestBuildIndex(TTestActorRuntime& runtime, ui64 id, ui64 schemeShard, const TString &dbName, const TString &src, const TBuildIndexConfig &cfg, Ydb::StatusIds::StatusCode expectedStatus = Ydb::StatusIds::SUCCESS);
413413
void TestBuildIndex(TTestActorRuntime& runtime, ui64 id, ui64 schemeShard, const TString &dbName, const TString &src, const TString &name, TVector<TString> columns, Ydb::StatusIds::StatusCode expectedStatus = Ydb::StatusIds::SUCCESS);
414-
void TestBuildVectorIndex(TTestActorRuntime& runtime, ui64 id, ui64 schemeShard, const TString &dbName, const TString &src, const TString &name, TString column, Ydb::StatusIds::StatusCode expectedStatus = Ydb::StatusIds::SUCCESS);
414+
void TestBuildVectorIndex(TTestActorRuntime& runtime, ui64 id, ui64 schemeShard, const TString &dbName, const TString &src, const TString &name, TVector<TString> columns, Ydb::StatusIds::StatusCode expectedStatus = Ydb::StatusIds::SUCCESS);
415415
TEvIndexBuilder::TEvCancelRequest* CreateCancelBuildIndexRequest(const ui64 id, const TString& dbName, const ui64 buildIndexId);
416416
NKikimrIndexBuilder::TEvCancelResponse TestCancelBuildIndex(TTestActorRuntime& runtime, const ui64 id, const ui64 schemeShard, const TString &dbName, const ui64 buildIndexId, const TVector<Ydb::StatusIds::StatusCode>& expectedStatuses = {Ydb::StatusIds::SUCCESS});
417417
TEvIndexBuilder::TEvListRequest* ListBuildIndexRequest(const TString& dbName);

ydb/core/tx/schemeshard/ut_index_build/ut_vector_index_build.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Y_UNIT_TEST_SUITE(VectorIndexBuildTest) {
9292
{NLs::PathExist, NLs::IndexesCount(0), NLs::PathVersionEqual(3)});
9393

9494
ui64 buildIndexTx = ++txId;
95-
TestBuildVectorIndex(runtime, buildIndexTx, tenantSchemeShard, "/MyRoot/ServerLessDB", "/MyRoot/ServerLessDB/Table", "index1", "embedding");
95+
TestBuildVectorIndex(runtime, buildIndexTx, tenantSchemeShard, "/MyRoot/ServerLessDB", "/MyRoot/ServerLessDB/Table", "index1", {"embedding"});
9696
env.TestWaitNotification(runtime, buildIndexTx, tenantSchemeShard);
9797

9898
auto buildIndexOperations = TestListBuildIndex(runtime, tenantSchemeShard, "/MyRoot/ServerLessDB");
@@ -160,7 +160,7 @@ Y_UNIT_TEST_SUITE(VectorIndexBuildTest) {
160160

161161
WriteVectorTableRows(runtime, tenantSchemeShard, ++txId, "/MyRoot/ServerLessDB/Table", 0, 0, 200, {1, 5, 3, 4});
162162

163-
TestBuildVectorIndex(runtime, ++txId, tenantSchemeShard, "/MyRoot/ServerLessDB", "/MyRoot/ServerLessDB/Table", "index2", "embedding");
163+
TestBuildVectorIndex(runtime, ++txId, tenantSchemeShard, "/MyRoot/ServerLessDB", "/MyRoot/ServerLessDB/Table", "index2", {"embedding"});
164164
env.TestWaitNotification(runtime, txId, tenantSchemeShard);
165165

166166
TestDescribeResult(DescribePath(runtime, tenantSchemeShard, "/MyRoot/ServerLessDB/Table"),
@@ -422,7 +422,7 @@ Y_UNIT_TEST_SUITE(VectorIndexBuildTest) {
422422

423423
// Initiate index build:
424424
ui64 buildIndexTx = ++txId;
425-
TestBuildVectorIndex(runtime, buildIndexTx, tenantSchemeShard, "/MyRoot/CommonDB", "/MyRoot/CommonDB/Table", "index1", "embedding");
425+
TestBuildVectorIndex(runtime, buildIndexTx, tenantSchemeShard, "/MyRoot/CommonDB", "/MyRoot/CommonDB/Table", "index1", {"embedding"});
426426
{
427427
auto buildIndexOperations = TestListBuildIndex(runtime, tenantSchemeShard, "/MyRoot/CommonDB");
428428
UNIT_ASSERT_VALUES_EQUAL(buildIndexOperations.EntriesSize(), 1);

ydb/core/tx/schemeshard/ut_move/ut_move.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <ydb/core/base/table_vector_index.h>
12
#include <ydb/core/kqp/ut/common/kqp_ut_common.h>
23
#include <ydb/core/tx/datashard/change_exchange.h>
34
#include <ydb/core/tx/schemeshard/ut_helpers/helpers.h>
@@ -8,6 +9,7 @@
89
using namespace NKikimr;
910
using namespace NSchemeShard;
1011
using namespace NSchemeShardUT_Private;
12+
using namespace NKikimr::NTableIndex::NTableVectorKmeansTreeIndex;
1113

1214
void SetEnableMoveIndex(TTestActorRuntime &runtime, TTestEnv&, ui64 schemeShard, bool value) {
1315
auto request = MakeHolder<NConsole::TEvConsole::TEvConfigNotificationRequest>();
@@ -1020,6 +1022,59 @@ Y_UNIT_TEST_SUITE(TSchemeShardMoveTest) {
10201022
NLs::IndexesCount(2)});
10211023
}
10221024

1025+
Y_UNIT_TEST(ReplaceVectorIndex) {
1026+
TTestBasicRuntime runtime;
1027+
TTestEnv env(runtime);
1028+
ui64 txId = 100;
1029+
1030+
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
1031+
Name: "Table"
1032+
Columns { Name: "key" Type: "Uint32" }
1033+
Columns { Name: "embedding" Type: "String" }
1034+
Columns { Name: "prefix" Type: "Uint32" }
1035+
Columns { Name: "value" Type: "String" }
1036+
KeyColumnNames: ["key"]
1037+
)");
1038+
env.TestWaitNotification(runtime, txId);
1039+
1040+
TestBuildVectorIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table", "index1", {"embedding"});
1041+
env.TestWaitNotification(runtime, txId);
1042+
1043+
TestBuildVectorIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table", "index2", {"prefix", "embedding"});
1044+
env.TestWaitNotification(runtime, txId);
1045+
1046+
TestDescribeResult(DescribePath(runtime, "/MyRoot/Table"), {NLs::PathExist, NLs::PathVersionEqual(9), NLs::IndexesCount(2)});
1047+
1048+
TestMoveIndex(runtime, ++txId, "/MyRoot/Table", "index2", "index1", true);
1049+
env.TestWaitNotification(runtime, txId);
1050+
1051+
TestDescribeResult(DescribePath(runtime, "/MyRoot/Table/index2"), {NLs::PathNotExist});
1052+
TestDescribeResult(DescribePath(runtime, "/MyRoot/Table"), {NLs::PathExist, NLs::IndexesCount(1)});
1053+
TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/index1/indexImplPrefixTable"),
1054+
{ NLs::PathExist, NLs::CheckColumns(PrefixTable, {"prefix", IdColumn}, {}, {"prefix", IdColumn}, true) });
1055+
TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/index1/indexImplLevelTable"),
1056+
{ NLs::PathExist, NLs::CheckColumns(LevelTable, {ParentColumn, IdColumn, CentroidColumn}, {}, {ParentColumn, IdColumn}, true) });
1057+
TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/index1/indexImplPostingTable"),
1058+
{ NLs::PathExist, NLs::CheckColumns(PostingTable, {ParentColumn, "key"}, {}, {ParentColumn, "key"}, true) });
1059+
1060+
// Replace again - it previously crashed here when Dec/IncAliveChildren were incorrect
1061+
1062+
TestBuildVectorIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table", "index2", {"embedding"});
1063+
env.TestWaitNotification(runtime, txId);
1064+
1065+
TestMoveIndex(runtime, ++txId, "/MyRoot/Table", "index2", "index1", true);
1066+
env.TestWaitNotification(runtime, txId);
1067+
1068+
TestDescribeResult(DescribePath(runtime, "/MyRoot/Table/index2"), {NLs::PathNotExist});
1069+
TestDescribeResult(DescribePath(runtime, "/MyRoot/Table"), {NLs::PathExist, NLs::IndexesCount(1)});
1070+
TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/index1/indexImplPrefixTable"), {NLs::PathNotExist});
1071+
TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/index1/indexImplLevelTable"),
1072+
{ NLs::PathExist, NLs::CheckColumns(LevelTable, {ParentColumn, IdColumn, CentroidColumn}, {}, {ParentColumn, IdColumn}, true) });
1073+
TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/index1/indexImplPostingTable"),
1074+
{ NLs::PathExist, NLs::CheckColumns(PostingTable, {ParentColumn, "key"}, {}, {ParentColumn, "key"}, true) });
1075+
}
1076+
1077+
10231078
Y_UNIT_TEST(AsyncIndexWithSyncInFly) {
10241079
TTestBasicRuntime runtime;
10251080
TTestEnv env(runtime);

ydb/tests/stress/common/common.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ def drop_table(self, path_to_table):
3434
else:
3535
self.session_pool.retry_operation_sync(lambda session: session.drop_table(path_to_table))
3636

37+
def replace_index(self, table, src, dst):
38+
self.driver.table_client.alter_table(path=table, rename_indexes=[
39+
ydb.RenameIndexItem(source_name=src, destination_name=dst, replace_destination=True)
40+
])
41+
3742
def describe(self, path):
3843
try:
3944
return self.driver.scheme_client.describe_path(path)

ydb/tests/stress/oltp_workload/workload/type/vector_index.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,18 @@ def _check_loop(self, table_path, vector_type, vector_dimension, levels, cluster
207207
distance=distance,
208208
similarity=similarity,
209209
)
210+
if random.randint(0, 1) == 0:
211+
self._create_index(
212+
index_name=index_name+'Rename',
213+
table_path=table_path,
214+
vector_type=vector_type,
215+
vector_dimension=vector_dimension,
216+
levels=levels,
217+
clusters=clusters,
218+
distance=distance,
219+
similarity=similarity,
220+
)
221+
self.client.replace_index(table_path, index_name+'Rename', index_name)
210222
self._drop_index(index_name, table_path)
211223
logger.info('check was completed successfully')
212224

0 commit comments

Comments
 (0)