summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Vasilev <[email protected]>2026-07-10 16:38:50 +0300
committerGitHub <[email protected]>2026-07-10 13:38:50 +0000
commit8aff7ccdce6bb4f326f09e88e9ebdfedb7df3de3 (patch)
tree7663e0f158dc7510eaf648a6f635ab7531170951
parentcca98fa2c4003e0c7382081a423160ae7c31cc22 (diff)
Fix INTERNAL ERROR instead of ABORTED for Snapshot Isolation (#46143)
-rw-r--r--ydb/core/kqp/session_actor/kqp_session_actor.cpp10
-rw-r--r--ydb/core/kqp/ut/tx/kqp_snapshot_isolation_ut.cpp58
2 files changed, 68 insertions, 0 deletions
diff --git a/ydb/core/kqp/session_actor/kqp_session_actor.cpp b/ydb/core/kqp/session_actor/kqp_session_actor.cpp
index 915518778a4..c4fa8627146 100644
--- a/ydb/core/kqp/session_actor/kqp_session_actor.cpp
+++ b/ydb/core/kqp/session_actor/kqp_session_actor.cpp
@@ -1710,6 +1710,16 @@ public:
return false;
}
+ if (txCtx.TxManager->BrokenLocks()) {
+ EmitVictimTliLog(
+ txCtx.TxManager->GetVictimQuerySpanId(),
+ std::nullopt,
+ txCtx.TxManager->GetBrokenLocksCount());
+ ReplyQueryError(Ydb::StatusIds::ABORTED, "transaction locks invalidated",
+ MessageFromIssues(std::vector<TIssue>{*txCtx.TxManager->GetLockIssue()}));
+ return false;
+ }
+
return true;
}
diff --git a/ydb/core/kqp/ut/tx/kqp_snapshot_isolation_ut.cpp b/ydb/core/kqp/ut/tx/kqp_snapshot_isolation_ut.cpp
index e13ccac8257..35abd67a480 100644
--- a/ydb/core/kqp/ut/tx/kqp_snapshot_isolation_ut.cpp
+++ b/ydb/core/kqp/ut/tx/kqp_snapshot_isolation_ut.cpp
@@ -989,6 +989,64 @@ Y_UNIT_TEST_SUITE(KqpSnapshotIsolation) {
tester.SetIsUpdate(IsUpdate);
tester.Execute();
}
+
+ class TBrokenLocksReadAfterUpsert : public TTableDataModificationTester {
+ protected:
+ void DoExecute() override {
+ auto client = Kikimr->GetQueryClient();
+ auto session1 = client.GetSession().GetValueSync().GetSession();
+ auto session2 = client.GetSession().GetValueSync().GetSession();
+
+ auto result = session1.ExecuteQuery(Q_(R"(
+ SELECT * FROM `/Root/Test` WHERE Name == "Paul";
+ )"), TTxControl::BeginTx(TTxSettings::SnapshotRW())).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+ auto tx1 = result.GetTransaction();
+ UNIT_ASSERT(tx1);
+ UNIT_ASSERT(tx1->IsActive());
+
+ result = session1.ExecuteQuery(Q_(R"(
+ PRAGMA kikimr.KqpForceImmediateEffectsExecution="true";
+ UPSERT INTO `/Root/Test` (Group, Name, Comment)
+ VALUES (1U, "Paul", "Changed");
+ )"), TTxControl::Tx(*tx1)).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+ result = session2.ExecuteQuery(Q_(R"(
+ UPSERT INTO `/Root/Test` (Group, Name, Comment)
+ VALUES (1U, "Paul", "Changed Other");
+ )"), TTxControl::BeginTx(TTxSettings::SnapshotRW()).CommitTx()).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+ result = session1.ExecuteQuery(Q_(R"(
+ SELECT * FROM `/Root/Test` WHERE Name == "Paul";
+ )"), TTxControl::Tx(*tx1)).ExtractValueSync();
+ if (GetIsOlap()) {
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+ } else {
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString());
+ }
+
+ if (GetIsOlap()) {
+ result = session1.ExecuteQuery(Q_(R"(
+ SELECT * FROM `/Root/Test` WHERE Name == "Paul";
+ )"), TTxControl::Tx(*tx1)).ExtractValueSync();
+ UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString());
+ }
+ }
+ };
+
+ Y_UNIT_TEST(TBrokenLocksReadAfterUpsertOltp) {
+ TBrokenLocksReadAfterUpsert tester;
+ tester.SetIsOlap(false);
+ tester.Execute();
+ }
+
+ Y_UNIT_TEST(TBrokenLocksReadAfterUpsertOlap) {
+ TBrokenLocksReadAfterUpsert tester;
+ tester.SetIsOlap(true);
+ tester.Execute();
+ }
}
} // namespace NKqp