Skip to content

Commit 8fb382c

Browse files
authored
Add missing precharges in datashard init tx (#11516)
1 parent 691458b commit 8fb382c

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

ydb/core/tablet_flat/flat_database.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ bool TDatabase::TChangeCounter::operator<(const TChangeCounter& rhs) const {
4040

4141
TDatabase::TDatabase(TDatabaseImpl *databaseImpl) noexcept
4242
: DatabaseImpl(databaseImpl ? databaseImpl : new TDatabaseImpl(0, new TScheme, nullptr))
43-
, NoMoreReadsFlag(true)
4443
{
4544

4645
}
@@ -59,7 +58,7 @@ TIntrusiveConstPtr<TRowScheme> TDatabase::GetRowScheme(ui32 table) const noexcep
5958

6059
TAutoPtr<TTableIter> TDatabase::Iterate(ui32 table, TRawVals key, TTagsRef tags, ELookup mode) const noexcept
6160
{
62-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
61+
CheckReadAllowed(table);
6362

6463
const auto seekBy = [](TRawVals key, ELookup mode) {
6564
if (!key && mode != ELookup::ExactMatch) {
@@ -92,7 +91,7 @@ TAutoPtr<TTableIter> TDatabase::IterateExact(ui32 table, TRawVals key, TTagsRef
9291
const ITransactionMapPtr& visible,
9392
const ITransactionObserverPtr& observer) const noexcept
9493
{
95-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
94+
CheckReadAllowed(table);
9695

9796
auto iter = Require(table)->Iterate(key, tags, Env, ESeek::Exact, snapshot, visible, observer);
9897

@@ -144,7 +143,7 @@ TAutoPtr<TTableIter> TDatabase::IterateRange(ui32 table, const TKeyRange& range,
144143
const ITransactionMapPtr& visible,
145144
const ITransactionObserverPtr& observer) const noexcept
146145
{
147-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
146+
CheckReadAllowed(table);
148147

149148
Y_DEBUG_ABORT_UNLESS(!IsAmbiguousRange(range, Require(table)->GetScheme()->Keys->Size()),
150149
"%s", IsAmbiguousRangeReason(range, Require(table)->GetScheme()->Keys->Size()));
@@ -171,7 +170,7 @@ TAutoPtr<TTableReverseIter> TDatabase::IterateRangeReverse(ui32 table, const TKe
171170
const ITransactionMapPtr& visible,
172171
const ITransactionObserverPtr& observer) const noexcept
173172
{
174-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
173+
CheckReadAllowed(table);
175174

176175
Y_DEBUG_ABORT_UNLESS(!IsAmbiguousRange(range, Require(table)->GetScheme()->Keys->Size()),
177176
"%s", IsAmbiguousRangeReason(range, Require(table)->GetScheme()->Keys->Size()));
@@ -226,7 +225,7 @@ EReady TDatabase::Select(ui32 table, TRawVals key, TTagsRef tags, TRowState &row
226225
const ITransactionObserverPtr& observer) const noexcept
227226
{
228227
TempIterators.clear();
229-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
228+
CheckReadAllowed(table);
230229

231230
auto prevSieved = stats.Sieved;
232231
auto prevWeeded = stats.Weeded;
@@ -268,7 +267,8 @@ void TDatabase::CalculateReadSize(TSizeEnv& env, ui32 table, TRawVals minKey, TR
268267
TTagsRef tags, ui64 flg, ui64 items, ui64 bytes,
269268
EDirection direction, TRowVersion snapshot)
270269
{
271-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to do precharge after reads prohibited, table %u", table);
270+
CheckReadAllowed(table);
271+
272272
TSelectStats stats;
273273
Require(table)->Precharge(minKey, maxKey, tags, &env, flg, items, bytes, direction, snapshot, stats);
274274
}
@@ -277,7 +277,8 @@ bool TDatabase::Precharge(ui32 table, TRawVals minKey, TRawVals maxKey,
277277
TTagsRef tags, ui64 flg, ui64 items, ui64 bytes,
278278
EDirection direction, TRowVersion snapshot)
279279
{
280-
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to do precharge after reads prohibited, table %u", table);
280+
CheckPrechargeAllowed(table, minKey, maxKey);
281+
281282
TSelectStats stats;
282283
auto ready = Require(table)->Precharge(minKey, maxKey, tags, Env, flg, items, bytes, direction, snapshot, stats);
283284
Change->Stats.ChargeSieved += stats.Sieved;
@@ -428,6 +429,10 @@ void TDatabase::NoMoreReadsForTx() {
428429
NoMoreReadsFlag = true;
429430
}
430431

432+
void TDatabase::NoMoreUnprechargedReadsForTx() {
433+
NoMoreUnprechargedReadsFlag = true;
434+
}
435+
431436
void TDatabase::Begin(TTxStamp stamp, IPages& env)
432437
{
433438
Y_ABORT_UNLESS(!Redo, "Transaction already in progress");
@@ -438,6 +443,8 @@ void TDatabase::Begin(TTxStamp stamp, IPages& env)
438443
Change = MakeHolder<TChange>(stamp, DatabaseImpl->Serial());
439444
Env = &env;
440445
NoMoreReadsFlag = false;
446+
NoMoreUnprechargedReadsFlag = false;
447+
PrechargedTables.clear();
441448
}
442449

443450
void TDatabase::RollbackChanges()
@@ -802,6 +809,30 @@ TTable* TDatabase::RequireForUpdate(ui32 table) const noexcept
802809
return DatabaseImpl->GetForUpdate(table).Self.Get();
803810
}
804811

812+
void TDatabase::CheckReadAllowed(ui32 table) const noexcept
813+
{
814+
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table);
815+
if (NoMoreUnprechargedReadsFlag) [[unlikely]] {
816+
Y_DEBUG_ABORT_UNLESS(
817+
std::find(PrechargedTables.begin(), PrechargedTables.end(), table) != PrechargedTables.end(),
818+
"Trying to read a previously unprecharged table %u", table);
819+
}
820+
}
821+
822+
void TDatabase::CheckPrechargeAllowed(ui32 table, TRawVals minKey, TRawVals maxKey) const noexcept
823+
{
824+
Y_ABORT_UNLESS(!NoMoreReadsFlag, "Trying to precharge after reads prohibited, table %u", table);
825+
if (NoMoreUnprechargedReadsFlag) [[unlikely]] {
826+
Y_DEBUG_ABORT_UNLESS(
827+
std::find(PrechargedTables.begin(), PrechargedTables.end(), table) != PrechargedTables.end(),
828+
"Trying to precharge a previously unprecharged table %u", table);
829+
} else if (!minKey && !maxKey) {
830+
// Note: tables are usually fully precharged only in init transcations
831+
// This vector is small or empty most of the time and not worth using a hash table
832+
PrechargedTables.push_back(table);
833+
}
834+
}
835+
805836
TGarbage TDatabase::RollUp(TTxStamp stamp, TArrayRef<const char> delta, TArrayRef<const char> redo,
806837
TMemGlobs annex)
807838
{

ydb/core/tablet_flat/flat_database.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ class TDatabase {
193193

194194
void NoMoreReadsForTx();
195195

196+
/**
197+
* Will debug assert when current transaction attempts to read tables that
198+
* have not been precharged up to this point. Useful to detect missing
199+
* precharges that avoid multiple transaction restarts.
200+
*/
201+
void NoMoreUnprechargedReadsForTx();
202+
196203
TAlter& Alter(); /* Begin DDL ALTER script */
197204

198205
TEpoch TxSnapTable(ui32 table);
@@ -291,10 +298,14 @@ class TDatabase {
291298
TTable* Require(ui32 tableId) const noexcept;
292299
TTable* RequireForUpdate(ui32 tableId) const noexcept;
293300

301+
void CheckReadAllowed(ui32 table) const noexcept;
302+
void CheckPrechargeAllowed(ui32 table, TRawVals minKey, TRawVals maxKey) const noexcept;
303+
294304
private:
295305
const THolder<TDatabaseImpl> DatabaseImpl;
296306

297-
bool NoMoreReadsFlag;
307+
bool NoMoreReadsFlag = false;
308+
bool NoMoreUnprechargedReadsFlag = false;
298309
IPages* Env = nullptr;
299310
THolder<TChange> Change;
300311
TAutoPtr<TAlter> Alter_;
@@ -305,6 +316,7 @@ class TDatabase {
305316
TVector<TUpdateOp> ModifiedOps;
306317

307318
mutable TDeque<TPartIter> TempIterators; // Keeps the last result of Select() valid
319+
mutable TVector<ui32> PrechargedTables;
308320

309321
TVector<std::function<void()>> OnCommit_;
310322
TVector<std::function<void()>> OnRollback_;

ydb/core/tx/datashard/datashard__init.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ bool TDataShard::TTxInit::ReadEverything(TTransactionContext &txc) {
156156
PRECHARGE_SYS_TABLE(Schema::PlanQueue);
157157
PRECHARGE_SYS_TABLE(Schema::DeadlineQueue);
158158
PRECHARGE_SYS_TABLE(Schema::SchemaOperations);
159+
PRECHARGE_SYS_TABLE(Schema::ScanProgress);
159160
PRECHARGE_SYS_TABLE(Schema::SplitSrcSnapshots);
160161
PRECHARGE_SYS_TABLE(Schema::SplitDstReceivedSnapshots);
161162
PRECHARGE_SYS_TABLE(Schema::Snapshots);
@@ -173,6 +174,9 @@ bool TDataShard::TTxInit::ReadEverything(TTransactionContext &txc) {
173174
PRECHARGE_SYS_TABLE(Schema::Locks);
174175
PRECHARGE_SYS_TABLE(Schema::LockRanges);
175176
PRECHARGE_SYS_TABLE(Schema::LockConflicts);
177+
PRECHARGE_SYS_TABLE(Schema::LockVolatileDependencies);
178+
PRECHARGE_SYS_TABLE(Schema::LockChangeRecords);
179+
PRECHARGE_SYS_TABLE(Schema::ChangeRecordCommits);
176180
PRECHARGE_SYS_TABLE(Schema::TxVolatileDetails);
177181
PRECHARGE_SYS_TABLE(Schema::TxVolatileParticipants);
178182
PRECHARGE_SYS_TABLE(Schema::CdcStreamScans);
@@ -184,6 +188,8 @@ bool TDataShard::TTxInit::ReadEverything(TTransactionContext &txc) {
184188
#undef PRECHARGE_SYS_TABLE
185189
}
186190

191+
txc.DB.NoMoreUnprechargedReadsForTx();
192+
187193
// Reads from Sys table
188194
LOAD_SYS_UI64(db, Schema::Sys_State, Self->State);
189195
LOAD_SYS_UI64(db, Schema::Sys_LastLocalTid, Self->LastLocalTid);

0 commit comments

Comments
 (0)