diff options
author | eivanov89 <eivanov89@ydb.tech> | 2023-01-25 17:42:24 +0300 |
---|---|---|
committer | eivanov89 <eivanov89@ydb.tech> | 2023-01-25 17:42:24 +0300 |
commit | f4b241dfda76e1d4664b9436cdd7a6db395aefec (patch) | |
tree | c7facec702cfa4c20e169f6aca1675059492fa3a | |
parent | 5d94d302eae60eee6caa3212044249b952be0317 (diff) | |
download | ydb-f4b241dfda76e1d4664b9436cdd7a6db395aefec.tar.gz |
fix invisible row miscalculation, which causes misdetection of broken lock
-rw-r--r-- | ydb/core/tx/datashard/datashard__read_iterator.cpp | 2 | ||||
-rw-r--r-- | ydb/core/tx/datashard/datashard_ut_read_iterator.cpp | 55 |
2 files changed, 56 insertions, 1 deletions
diff --git a/ydb/core/tx/datashard/datashard__read_iterator.cpp b/ydb/core/tx/datashard/datashard__read_iterator.cpp index e3c39b4bee..514b5371cb 100644 --- a/ydb/core/tx/datashard/datashard__read_iterator.cpp +++ b/ydb/core/tx/datashard/datashard__read_iterator.cpp @@ -659,8 +659,8 @@ private: } // last iteration to Page or Gone also might have deleted or invisible rows - RowsSinceLastCheck += ResetRowStats(iter->Stats); InvisibleRowSkips += iter->Stats.InvisibleRowSkips; + RowsSinceLastCheck += ResetRowStats(iter->Stats); // TODO: consider restart when Page and too few data read // (how much is too few, less than user's limit?) diff --git a/ydb/core/tx/datashard/datashard_ut_read_iterator.cpp b/ydb/core/tx/datashard/datashard_ut_read_iterator.cpp index 0e4df92779..11db2999f4 100644 --- a/ydb/core/tx/datashard/datashard_ut_read_iterator.cpp +++ b/ydb/core/tx/datashard/datashard_ut_read_iterator.cpp @@ -2509,6 +2509,61 @@ Y_UNIT_TEST_SUITE(DataShardReadIterator) { helper.CheckLockBroken("table-1", 10, {11, 11, 11}, lockTxId, *readResult1); } + Y_UNIT_TEST(ShouldReturnBrokenLockWhenReadRangeInvisibleRowSkips2) { + // Almost the same as ShouldReturnBrokenLockWhenReadRangeInvisibleRowSkips: + // 1. tx1: read some **non-existing** range1 + // 2. tx2: upsert into range2 > range1 range and commit. + // 3. tx1: read range2 -> lock should be broken + + TTestHelper helper; + + auto readVersion = CreateVolatileSnapshot( + helper.Server, + {"/Root/movies", "/Root/table-1"}, + TDuration::Hours(1)); + + const ui64 lockTxId = 1011121314; + + auto request1 = helper.GetBaseReadRequest("table-1", 1, NKikimrTxDataShard::ARROW, readVersion); + request1->Record.SetLockTxId(lockTxId); + AddRangeQuery<ui32>( + *request1, + {100, 0, 0}, + true, + {200, 0, 0}, + true + ); + + auto readResult1 = helper.SendRead("table-1", request1.release()); + CheckResult(helper.Tables["table-1"].UserTable, *readResult1, {}); + UNIT_ASSERT_VALUES_EQUAL(readResult1->Record.TxLocksSize(), 1); + UNIT_ASSERT_VALUES_EQUAL(readResult1->Record.BrokenTxLocksSize(), 0); + + // write new data above snapshot + ExecSQL(helper.Server, helper.Sender, R"( + SELECT * FROM `/Root/table-1` WHERE key1 == 300; + UPSERT INTO `/Root/table-1` + (key1, key2, key3, value) + VALUES + (300, 0, 0, 3000); + )"); + + auto request2 = helper.GetBaseReadRequest("table-1", 2, NKikimrTxDataShard::ARROW, readVersion); + request2->Record.SetLockTxId(lockTxId); + AddRangeQuery<ui32>( + *request2, + {300, 0, 0}, + true, + {300, 0, 0}, + true + ); + + auto readResult2 = helper.SendRead("table-1", request2.release()); + UNIT_ASSERT_VALUES_EQUAL(readResult2->Record.TxLocksSize(), 0); + UNIT_ASSERT_VALUES_EQUAL(readResult2->Record.BrokenTxLocksSize(), 1); + helper.CheckLockBroken("table-1", 10, {300, 0, 0}, lockTxId, *readResult2); + } + Y_UNIT_TEST(ShouldReturnBrokenLockWhenReadRangeLeftBorder) { TTestHelper helper; |