@@ -18,6 +18,7 @@ import (
1818 "github.com/cockroachdb/cockroach/pkg/roachpb"
1919 "github.com/cockroachdb/cockroach/pkg/security/username"
2020 "github.com/cockroachdb/cockroach/pkg/server/telemetry"
21+ "github.com/cockroachdb/cockroach/pkg/settings"
2122 "github.com/cockroachdb/cockroach/pkg/settings/cluster"
2223 "github.com/cockroachdb/cockroach/pkg/sql/catalog"
2324 "github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkeys"
@@ -35,6 +36,17 @@ import (
3536 "github.com/cockroachdb/errors"
3637)
3738
39+ // batchFlushThresholdSize is the size of the metadata batch that,
40+ // when exceeded, causes the schema changer to flush the batch to the KV store.
41+ var batchFlushThresholdSize = settings .RegisterByteSizeSetting (
42+ settings .ApplicationLevel ,
43+ "sql.schema_changer.batch_flush_threshold_size" ,
44+ "maximum size in bytes of the schema changer's metadata batch before it's flushed to the KV store. " +
45+ "This setting should be smaller or equal to kv.raft.command.max_size" ,
46+ 32 * 1024 * 1024 ,
47+ settings .IntInRange (1024 * 1024 , 512 * 1024 * 1024 ),
48+ )
49+
3850// JobRegistry implements the methods the schema changer needs from the
3951// job registry. Outside of tests this should always be backed by *job.Registry.
4052type JobRegistry interface {
@@ -206,22 +218,38 @@ func (d *txnDeps) MustReadMutableDescriptor(
206218func (d * txnDeps ) CreateOrUpdateDescriptor (
207219 ctx context.Context , desc catalog.MutableDescriptor ,
208220) error {
209- return d .descsCollection .WriteDescToBatch (ctx , d .kvTrace , desc , d .getOrCreateBatch ())
221+ b , err := d .getOrCreateBatch (ctx )
222+ if err != nil {
223+ return err
224+ }
225+ return d .descsCollection .WriteDescToBatch (ctx , d .kvTrace , desc , b )
210226}
211227
212228// DeleteName implements the scexec.Catalog interface.
213229func (d * txnDeps ) DeleteName (ctx context.Context , nameInfo descpb.NameInfo , id descpb.ID ) error {
214- return d .descsCollection .DeleteNamespaceEntryToBatch (ctx , d .kvTrace , & nameInfo , d .getOrCreateBatch ())
230+ b , err := d .getOrCreateBatch (ctx )
231+ if err != nil {
232+ return err
233+ }
234+ return d .descsCollection .DeleteNamespaceEntryToBatch (ctx , d .kvTrace , & nameInfo , b )
215235}
216236
217237// AddName implements the scexec.Catalog interface.
218238func (d * txnDeps ) AddName (ctx context.Context , nameInfo descpb.NameInfo , id descpb.ID ) error {
219- return d .descsCollection .InsertNamespaceEntryToBatch (ctx , d .kvTrace , & nameEntry {nameInfo , id }, d .getOrCreateBatch ())
239+ b , err := d .getOrCreateBatch (ctx )
240+ if err != nil {
241+ return err
242+ }
243+ return d .descsCollection .InsertNamespaceEntryToBatch (ctx , d .kvTrace , & nameEntry {nameInfo , id }, b )
220244}
221245
222246// DeleteDescriptor implements the scexec.Catalog interface.
223247func (d * txnDeps ) DeleteDescriptor (ctx context.Context , id descpb.ID ) error {
224- return d .descsCollection .DeleteDescToBatch (ctx , d .kvTrace , id , d .getOrCreateBatch ())
248+ b , err := d .getOrCreateBatch (ctx )
249+ if err != nil {
250+ return err
251+ }
252+ return d .descsCollection .DeleteDescToBatch (ctx , d .kvTrace , id , b )
225253}
226254
227255// GetZoneConfig implements the scexec.Catalog interface.
@@ -237,7 +265,11 @@ func (d *txnDeps) GetZoneConfig(ctx context.Context, id descpb.ID) (catalog.Zone
237265func (d * txnDeps ) WriteZoneConfigToBatch (
238266 ctx context.Context , id descpb.ID , zc catalog.ZoneConfig ,
239267) error {
240- err := d .descsCollection .WriteZoneConfigToBatch (ctx , d .kvTrace , d .getOrCreateBatch (), id , zc )
268+ b , err := d .getOrCreateBatch (ctx )
269+ if err != nil {
270+ return err
271+ }
272+ err = d .descsCollection .WriteZoneConfigToBatch (ctx , d .kvTrace , b , id , zc )
241273 if err != nil {
242274 return err
243275 }
@@ -260,7 +292,11 @@ func (d *txnDeps) UpdateZoneConfig(ctx context.Context, id descpb.ID, zc *zonepb
260292 rawBytes = oldZc .GetRawBytesInStorage ()
261293 }
262294 newZc = zone .NewZoneConfigWithRawBytes (zc , rawBytes )
263- return d .descsCollection .WriteZoneConfigToBatch (ctx , d .kvTrace , d .getOrCreateBatch (), id , newZc )
295+ b , err := d .getOrCreateBatch (ctx )
296+ if err != nil {
297+ return err
298+ }
299+ return d .descsCollection .WriteZoneConfigToBatch (ctx , d .kvTrace , b , id , newZc )
264300}
265301
266302// UpdateSubzoneConfig implements the scexec.Catalog interface. Note that this
@@ -310,7 +346,11 @@ func (d *txnDeps) UpdateSubzoneConfig(
310346
311347// DeleteZoneConfig implements the scexec.Catalog interface.
312348func (d * txnDeps ) DeleteZoneConfig (ctx context.Context , id descpb.ID ) error {
313- return d .descsCollection .DeleteZoneConfigInBatch (ctx , d .kvTrace , d .getOrCreateBatch (), id )
349+ b , err := d .getOrCreateBatch (ctx )
350+ if err != nil {
351+ return err
352+ }
353+ return d .descsCollection .DeleteZoneConfigInBatch (ctx , d .kvTrace , b , id )
314354}
315355
316356// DeleteSubzoneConfig implements the scexec.Catalog interface.
@@ -344,7 +384,11 @@ func (d *txnDeps) DeleteSubzoneConfig(
344384 zc .DeleteSubzoneSpans (subzoneSpans )
345385
346386 newZc = zone .NewZoneConfigWithRawBytes (zc , rawBytes )
347- return d .descsCollection .WriteZoneConfigToBatch (ctx , d .kvTrace , d .getOrCreateBatch (),
387+ b , err := d .getOrCreateBatch (ctx )
388+ if err != nil {
389+ return err
390+ }
391+ return d .descsCollection .WriteZoneConfigToBatch (ctx , d .kvTrace , b ,
348392 tableID , newZc )
349393}
350394
@@ -369,10 +413,14 @@ func (d *txnDeps) Run(ctx context.Context) error {
369413}
370414
371415// InitializeSequence implements the scexec.Caatalog interface.
372- func (d * txnDeps ) InitializeSequence (id descpb.ID , startVal int64 ) {
373- batch := d .getOrCreateBatch ()
416+ func (d * txnDeps ) InitializeSequence (ctx context.Context , id descpb.ID , startVal int64 ) error {
417+ batch , err := d .getOrCreateBatch (ctx )
418+ if err != nil {
419+ return err
420+ }
374421 sequenceKey := d .codec .SequenceKey (uint32 (id ))
375422 batch .Inc (sequenceKey , startVal )
423+ return nil
376424}
377425
378426// CheckMaxSchemaObjects implements the scexec.Catalog interface.
@@ -394,21 +442,45 @@ func (d *txnDeps) Reset(ctx context.Context) error {
394442 return nil
395443}
396444
397- func (d * txnDeps ) getOrCreateBatch () * kv.Batch {
445+ // maybeFlushBatch flushes the current batch if it exceeds the maximum size.
446+ func (d * txnDeps ) maybeFlushBatch (ctx context.Context ) error {
447+ if int64 (d .batch .ApproximateMutationBytes ()) > batchFlushThresholdSize .Get (& d .settings .SV ) {
448+ if err := d .Run (ctx ); err != nil {
449+ return err
450+ }
451+ d .batch = d .txn .KV ().NewBatch ()
452+ }
453+ return nil
454+ }
455+
456+ func (d * txnDeps ) getOrCreateBatch (ctx context.Context ) (* kv.Batch , error ) {
398457 if d .batch == nil {
399458 d .batch = d .txn .KV ().NewBatch ()
459+ } else {
460+ // Otherwise, flush the batch if its too big.
461+ if err := d .maybeFlushBatch (ctx ); err != nil {
462+ return nil , err
463+ }
400464 }
401- return d .batch
465+ return d .batch , nil
402466}
403467
404468// UpdateComment implements the scexec.Catalog interface.
405469func (d * txnDeps ) UpdateComment (ctx context.Context , key catalogkeys.CommentKey , cmt string ) error {
406- return d .descsCollection .WriteCommentToBatch (ctx , d .kvTrace , d .getOrCreateBatch (), key , cmt )
470+ b , err := d .getOrCreateBatch (ctx )
471+ if err != nil {
472+ return err
473+ }
474+ return d .descsCollection .WriteCommentToBatch (ctx , d .kvTrace , b , key , cmt )
407475}
408476
409477// DeleteComment implements the scexec.Catalog interface.
410478func (d * txnDeps ) DeleteComment (ctx context.Context , key catalogkeys.CommentKey ) error {
411- return d .descsCollection .DeleteCommentInBatch (ctx , d .kvTrace , d .getOrCreateBatch (), key )
479+ b , err := d .getOrCreateBatch (ctx )
480+ if err != nil {
481+ return err
482+ }
483+ return d .descsCollection .DeleteCommentInBatch (ctx , d .kvTrace , b , key )
412484}
413485
414486var _ scexec.TransactionalJobRegistry = (* txnDeps )(nil )
0 commit comments