@@ -869,8 +869,10 @@ void TDataShard::PersistChangeRecord(NIceDb::TNiceDb& db, const TChangeRecord& r
869869 Y_VERIFY_S (it != ChangesQueue.end (), " Cannot find change record: " << order);
870870
871871 if (it->second .SchemaSnapshotAcquired ) {
872- SchemaSnapshotManager.ReleaseReference (
873- TSchemaSnapshotKey (it->second .TableId , it->second .SchemaVersion ));
872+ const auto snapshotKey = TSchemaSnapshotKey (it->second .TableId , it->second .SchemaVersion );
873+ if (const auto last = SchemaSnapshotManager.ReleaseReference (snapshotKey)) {
874+ ScheduleRemoveSchemaSnapshot (snapshotKey);
875+ }
874876 }
875877
876878 ChangesQueue.erase (it);
@@ -998,8 +1000,10 @@ void TDataShard::CommitLockChangeRecords(NIceDb::TNiceDb& db, ui64 lockId, ui64
9981000 Y_VERIFY_S (cIt != ChangesQueue.end (), " Cannot find change record: " << order);
9991001
10001002 if (cIt->second .SchemaSnapshotAcquired ) {
1001- SchemaSnapshotManager.ReleaseReference (
1002- TSchemaSnapshotKey (cIt->second .TableId , cIt->second .SchemaVersion ));
1003+ const auto snapshotKey = TSchemaSnapshotKey (cIt->second .TableId , cIt->second .SchemaVersion );
1004+ if (const auto last = SchemaSnapshotManager.ReleaseReference (snapshotKey)) {
1005+ ScheduleRemoveSchemaSnapshot (snapshotKey);
1006+ }
10031007 }
10041008
10051009 ChangesQueue.erase (cIt);
@@ -1067,23 +1071,9 @@ void TDataShard::RemoveChangeRecord(NIceDb::TNiceDb& db, ui64 order) {
10671071 ChangesQueueBytes -= record.BodySize ;
10681072
10691073 if (record.SchemaSnapshotAcquired ) {
1070- Y_ABORT_UNLESS (record.TableId );
1071- auto tableIt = TableInfos.find (record.TableId .LocalPathId );
1072-
1073- if (tableIt != TableInfos.end ()) {
1074- const auto snapshotKey = TSchemaSnapshotKey (record.TableId , record.SchemaVersion );
1075- const bool last = SchemaSnapshotManager.ReleaseReference (snapshotKey);
1076-
1077- if (last) {
1078- const auto * snapshot = SchemaSnapshotManager.FindSnapshot (snapshotKey);
1079- Y_ABORT_UNLESS (snapshot);
1080-
1081- if (snapshot->Schema ->GetTableSchemaVersion () < tableIt->second ->GetTableSchemaVersion ()) {
1082- SchemaSnapshotManager.RemoveShapshot (db, snapshotKey);
1083- }
1084- }
1085- } else {
1086- Y_DEBUG_ABORT_UNLESS (State == TShardState::PreOffline);
1074+ const auto snapshotKey = TSchemaSnapshotKey (record.TableId , record.SchemaVersion );
1075+ if (const bool last = SchemaSnapshotManager.ReleaseReference (snapshotKey)) {
1076+ ScheduleRemoveSchemaSnapshot (snapshotKey);
10871077 }
10881078 }
10891079
@@ -1303,6 +1293,14 @@ bool TDataShard::LoadChangeRecords(NIceDb::TNiceDb& db, TVector<IDataShardChange
13031293 .SchemaVersion = schemaVersion,
13041294 });
13051295
1296+ auto res = ChangesQueue.emplace (records.back ().Order , records.back ());
1297+ Y_VERIFY_S (res.second , " Duplicate change record: " << records.back ().Order );
1298+
1299+ if (res.first ->second .SchemaVersion ) {
1300+ res.first ->second .SchemaSnapshotAcquired = SchemaSnapshotManager.AcquireReference (
1301+ TSchemaSnapshotKey (res.first ->second .TableId , res.first ->second .SchemaVersion ));
1302+ }
1303+
13061304 if (!rowset.Next ()) {
13071305 return false ;
13081306 }
@@ -1401,6 +1399,14 @@ bool TDataShard::LoadChangeRecordCommits(NIceDb::TNiceDb& db, TVector<IDataShard
14011399 });
14021400 entry.Count ++;
14031401 needSort = true ;
1402+
1403+ auto res = ChangesQueue.emplace (records.back ().Order , records.back ());
1404+ Y_VERIFY_S (res.second , " Duplicate change record: " << records.back ().Order );
1405+
1406+ if (res.first ->second .SchemaVersion ) {
1407+ res.first ->second .SchemaSnapshotAcquired = SchemaSnapshotManager.AcquireReference (
1408+ TSchemaSnapshotKey (res.first ->second .TableId , res.first ->second .SchemaVersion ));
1409+ }
14041410 }
14051411
14061412 LockChangeRecords.erase (lockId);
@@ -1459,6 +1465,46 @@ void TDataShard::ScheduleRemoveAbandonedLockChanges() {
14591465 }
14601466}
14611467
1468+ void TDataShard::ScheduleRemoveSchemaSnapshot (const TSchemaSnapshotKey& key) {
1469+ Y_ABORT_UNLESS (!SchemaSnapshotManager.HasReference (key));
1470+
1471+ const auto * snapshot = SchemaSnapshotManager.FindSnapshot (key);
1472+ Y_ABORT_UNLESS (snapshot);
1473+
1474+ auto it = TableInfos.find (key.PathId );
1475+ if (it == TableInfos.end ()) {
1476+ Y_DEBUG_ABORT_UNLESS (State == TShardState::PreOffline);
1477+ return ;
1478+ }
1479+
1480+ if (snapshot->Schema ->GetTableSchemaVersion () < it->second ->GetTableSchemaVersion ()) {
1481+ bool wasEmpty = PendingSchemaSnapshotsToRemove.empty ();
1482+ PendingSchemaSnapshotsToRemove.push_back (key);
1483+ if (wasEmpty) {
1484+ Send (SelfId (), new TEvPrivate::TEvRemoveSchemaSnapshots);
1485+ }
1486+ }
1487+ }
1488+
1489+ void TDataShard::ScheduleRemoveAbandonedSchemaSnapshots () {
1490+ bool wasEmpty = PendingSchemaSnapshotsToRemove.empty ();
1491+
1492+ for (const auto & [key, snapshot] : SchemaSnapshotManager.GetSnapshots ()) {
1493+ auto it = TableInfos.find (key.PathId );
1494+ if (it == TableInfos.end ()) {
1495+ Y_DEBUG_ABORT_UNLESS (State == TShardState::PreOffline);
1496+ break ;
1497+ }
1498+ if (snapshot.Schema ->GetTableSchemaVersion () < it->second ->GetTableSchemaVersion ()) {
1499+ PendingSchemaSnapshotsToRemove.push_back (key);
1500+ }
1501+ }
1502+
1503+ if (wasEmpty && !PendingSchemaSnapshotsToRemove.empty ()) {
1504+ Send (SelfId (), new TEvPrivate::TEvRemoveSchemaSnapshots);
1505+ }
1506+ }
1507+
14621508void TDataShard::PersistSchemeTxResult (NIceDb::TNiceDb &db, const TSchemaOperation &op) {
14631509 db.Table <Schema::SchemaOperations>().Key (op.TxId ).Update (
14641510 NIceDb::TUpdate<Schema::SchemaOperations::Success>(op.Success ),
0 commit comments