55#include " datashard_locks_db.h"
66#include " probes.h"
77
8+ #include < ydb/core/base/counters.h>
89#include < ydb/core/formats/arrow/arrow_batch_builder.h>
910
1011#include < ydb/library/actors/core/monotonic_provider.h>
@@ -315,6 +316,8 @@ class TReader {
315316 , Self(self)
316317 , TableId(state.PathId.OwnerId, state.PathId.LocalPathId, state.SchemaVersion)
317318 , FirstUnprocessedQuery(State.FirstUnprocessedQuery)
319+ , LastProcessedKey(State.LastProcessedKey)
320+ , LastProcessedKeyErased(State.LastProcessedKeyErased)
318321 {
319322 GetTimeFast (&StartTime);
320323 EndTime = StartTime;
@@ -329,10 +332,10 @@ class TReader {
329332 bool toInclusive;
330333 TSerializedCellVec keyFromCells;
331334 TSerializedCellVec keyToCells;
332- if (Y_UNLIKELY (FirstUnprocessedQuery == State. FirstUnprocessedQuery && State. LastProcessedKey ) ) {
335+ if (LastProcessedKey) {
333336 if (!State.Reverse ) {
334- keyFromCells = TSerializedCellVec (State. LastProcessedKey );
335- fromInclusive = State. LastProcessedKeyErased ;
337+ keyFromCells = TSerializedCellVec (LastProcessedKey);
338+ fromInclusive = LastProcessedKeyErased;
336339
337340 keyToCells = range.To ;
338341 toInclusive = range.ToInclusive ;
@@ -341,8 +344,8 @@ class TReader {
341344 keyFromCells = range.From ;
342345 fromInclusive = range.FromInclusive ;
343346
344- keyToCells = TSerializedCellVec (State. LastProcessedKey );
345- toInclusive = State. LastProcessedKeyErased ;
347+ keyToCells = TSerializedCellVec (LastProcessedKey);
348+ toInclusive = LastProcessedKeyErased;
346349 }
347350 } else {
348351 keyFromCells = range.From ;
@@ -500,6 +503,7 @@ class TReader {
500503 while (FirstUnprocessedQuery < State.Request ->Ranges .size ()) {
501504 if (ReachedTotalRowsLimit ()) {
502505 FirstUnprocessedQuery = -1 ;
506+ LastProcessedKey.clear ();
503507 return true ;
504508 }
505509
@@ -526,6 +530,7 @@ class TReader {
526530 FirstUnprocessedQuery++;
527531 else
528532 FirstUnprocessedQuery--;
533+ LastProcessedKey.clear ();
529534 }
530535
531536 return true ;
@@ -537,6 +542,7 @@ class TReader {
537542 while (FirstUnprocessedQuery < State.Request ->Keys .size ()) {
538543 if (ReachedTotalRowsLimit ()) {
539544 FirstUnprocessedQuery = -1 ;
545+ LastProcessedKey.clear ();
540546 return true ;
541547 }
542548
@@ -562,6 +568,7 @@ class TReader {
562568 FirstUnprocessedQuery++;
563569 else
564570 FirstUnprocessedQuery--;
571+ LastProcessedKey.clear ();
565572 }
566573
567574 return true ;
@@ -727,6 +734,28 @@ class TReader {
727734 }
728735
729736 void UpdateState (TReadIteratorState& state, bool sentResult) {
737+ if (state.FirstUnprocessedQuery == FirstUnprocessedQuery &&
738+ state.LastProcessedKey && !LastProcessedKey)
739+ {
740+ LOG_CRIT_S (*TlsActivationContext, NKikimrServices::TX_DATASHARD,
741+ " DataShard " << Self->TabletID () << " detected unexpected reset of LastProcessedKey:"
742+ << " ReadId# " << State.ReadId
743+ << " LastSeqNo# " << State.SeqNo
744+ << " LastQuery# " << State.FirstUnprocessedQuery
745+ << " RowsRead# " << RowsRead
746+ << " RowsProcessed# " << RowsProcessed
747+ << " RowsSinceLastCheck# " << RowsSinceLastCheck
748+ << " BytesInResult# " << BytesInResult
749+ << " DeletedRowSkips# " << DeletedRowSkips
750+ << " InvisibleRowSkips# " << InvisibleRowSkips
751+ << " Quota.Rows# " << State.Quota .Rows
752+ << " Quota.Bytes# " << State.Quota .Bytes
753+ << " State.TotalRows# " << State.TotalRows
754+ << " State.TotalRowsLimit# " << State.TotalRowsLimit
755+ << " State.MaxRowsInResult# " << State.MaxRowsInResult );
756+ Self->IncCounterReadIteratorLastKeyReset ();
757+ }
758+
730759 state.TotalRows += RowsRead;
731760 state.FirstUnprocessedQuery = FirstUnprocessedQuery;
732761 state.LastProcessedKey = LastProcessedKey;
@@ -1632,6 +1661,7 @@ class TDataShard::TReadOperation : public TOperation, public IReadOperation {
16321661 if (Reader->HasUnreadQueries ()) {
16331662 Reader->UpdateState (state, ResultSent);
16341663 if (!state.IsExhausted ()) {
1664+ state.ReadContinuePending = true ;
16351665 ctx.Send (
16361666 Self->SelfId (),
16371667 new TEvDataShard::TEvReadContinue (ReadId.Sender , ReadId.ReadId ));
@@ -2282,6 +2312,15 @@ class TDataShard::TTxReadContinue : public NTabletFlatExecutor::TTransactionBase
22822312 Y_ASSERT (it->second );
22832313 auto & state = *it->second ;
22842314
2315+ if (state.IsExhausted ()) {
2316+ // iterator quota reduced and exhausted while ReadContinue was inflight
2317+ LOG_TRACE_S (ctx, NKikimrServices::TX_DATASHARD, Self->TabletID () << " ReadContinue for iterator# " << ReadId
2318+ << " , quota exhausted while rescheduling" );
2319+ state.ReadContinuePending = false ;
2320+ Result.reset ();
2321+ return true ;
2322+ }
2323+
22852324 LOG_TRACE_S (ctx, NKikimrServices::TX_DATASHARD, Self->TabletID () << " ReadContinue for iterator# " << ReadId
22862325 << " , firstUnprocessedQuery# " << state.FirstUnprocessedQuery );
22872326
@@ -2394,6 +2433,7 @@ class TDataShard::TTxReadContinue : public NTabletFlatExecutor::TTransactionBase
23942433 if (Reader->Read (txc, ctx)) {
23952434 // Retry later when dependencies are resolved
23962435 if (!Reader->GetVolatileReadDependencies ().empty ()) {
2436+ state.ReadContinuePending = true ;
23972437 Self->WaitVolatileDependenciesThenSend (
23982438 Reader->GetVolatileReadDependencies (),
23992439 Self->SelfId (),
@@ -2480,6 +2520,8 @@ class TDataShard::TTxReadContinue : public NTabletFlatExecutor::TTransactionBase
24802520 Y_ABORT_UNLESS (it->second );
24812521 auto & state = *it->second ;
24822522
2523+ state.ReadContinuePending = false ;
2524+
24832525 if (!Result) {
24842526 LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD, Self->TabletID () << " read iterator# " << ReadId
24852527 << " TTxReadContinue::Execute() finished without Result, aborting" );
@@ -2527,14 +2569,14 @@ class TDataShard::TTxReadContinue : public NTabletFlatExecutor::TTransactionBase
25272569 }
25282570
25292571 if (Reader->HasUnreadQueries ()) {
2530- Y_ASSERT (it->second );
2531- auto & state = *it->second ;
2572+ bool wasExhausted = state.IsExhausted ();
25322573 Reader->UpdateState (state, useful);
25332574 if (!state.IsExhausted ()) {
2575+ state.ReadContinuePending = true ;
25342576 ctx.Send (
25352577 Self->SelfId (),
25362578 new TEvDataShard::TEvReadContinue (ReadId.Sender , ReadId.ReadId ));
2537- } else {
2579+ } else if (!wasExhausted) {
25382580 Self->IncCounter (COUNTER_READ_ITERATORS_EXHAUSTED_COUNT);
25392581 LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD, Self->TabletID ()
25402582 << " read iterator# " << ReadId << " exhausted" );
@@ -2807,14 +2849,19 @@ void TDataShard::Handle(TEvDataShard::TEvReadAck::TPtr& ev, const TActorContext&
28072849 bool wasExhausted = state.IsExhausted ();
28082850 state.UpQuota (
28092851 record.GetSeqNo (),
2810- record.GetMaxRows (),
2811- record.GetMaxBytes ());
2852+ record.HasMaxRows () ? record. GetMaxRows () : Max<ui64> (),
2853+ record.HasMaxBytes () ? record. GetMaxBytes () : Max<ui64> ());
28122854
28132855 if (wasExhausted && !state.IsExhausted ()) {
28142856 DecCounter (COUNTER_READ_ITERATORS_EXHAUSTED_COUNT);
2815- ctx.Send (
2816- SelfId (),
2817- new TEvDataShard::TEvReadContinue (ev->Sender , record.GetReadId ()));
2857+ if (!state.ReadContinuePending ) {
2858+ state.ReadContinuePending = true ;
2859+ ctx.Send (
2860+ SelfId (),
2861+ new TEvDataShard::TEvReadContinue (ev->Sender , record.GetReadId ()));
2862+ }
2863+ } else if (!wasExhausted && state.IsExhausted ()) {
2864+ IncCounter (COUNTER_READ_ITERATORS_EXHAUSTED_COUNT);
28182865 }
28192866
28202867 LOG_TRACE_S (ctx, NKikimrServices::TX_DATASHARD, TabletID () << " ReadAck for read iterator# " << readId
@@ -2943,6 +2990,16 @@ void TDataShard::UnsubscribeReadIteratorSessions(const TActorContext& ctx) {
29432990 ReadIteratorSessions.clear ();
29442991}
29452992
2993+ void TDataShard::IncCounterReadIteratorLastKeyReset () {
2994+ if (!CounterReadIteratorLastKeyReset) {
2995+ CounterReadIteratorLastKeyReset = GetServiceCounters (AppData ()->Counters , " tablets" )
2996+ ->GetSubgroup (" type" , " DataShard" )
2997+ ->GetSubgroup (" category" , " app" )
2998+ ->GetCounter (" DataShard/ReadIteratorLastKeyReset" , true );
2999+ }
3000+ ++*CounterReadIteratorLastKeyReset;
3001+ }
3002+
29463003} // NKikimr::NDataShard
29473004
29483005template <>
0 commit comments