github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logtail/txn_handle.go (about)

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package logtail
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sort"
    21  	"time"
    22  
    23  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    24  
    25  	"github.com/RoaringBitmap/roaring"
    26  	pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog"
    27  	"github.com/matrixorigin/matrixone/pkg/container/types"
    28  	"github.com/matrixorigin/matrixone/pkg/logutil"
    29  	"github.com/matrixorigin/matrixone/pkg/objectio"
    30  	"github.com/matrixorigin/matrixone/pkg/pb/api"
    31  	"github.com/matrixorigin/matrixone/pkg/pb/logtail"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    33  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    34  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    35  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/db/dbutils"
    36  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    37  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates"
    38  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnimpl"
    39  )
    40  
    41  const (
    42  	blkMetaInsBatch int8 = iota
    43  	blkMetaDelBatch
    44  	dataInsBatch
    45  	dataDelBatch
    46  	dbInsBatch
    47  	dbDelBatch
    48  	dbSpecialDeleteBatch
    49  	tblInsBatch
    50  	tblDelBatch
    51  	tblSpecialDeleteBatch
    52  	columnInsBatch
    53  	columnDelBatch
    54  	objectInfoBatch
    55  	batchTotalNum
    56  )
    57  
    58  type TxnLogtailRespBuilder struct {
    59  	rt                        *dbutils.Runtime
    60  	currDBName, currTableName string
    61  	currDBID, currTableID     uint64
    62  	txn                       txnif.AsyncTxn
    63  
    64  	batches []*containers.Batch
    65  
    66  	logtails       *[]logtail.TableLogtail
    67  	currentLogtail *logtail.TableLogtail
    68  
    69  	batchToClose []*containers.Batch
    70  	insertBatch  *roaring.Bitmap
    71  }
    72  
    73  func NewTxnLogtailRespBuilder(rt *dbutils.Runtime) *TxnLogtailRespBuilder {
    74  	logtails := make([]logtail.TableLogtail, 0)
    75  	return &TxnLogtailRespBuilder{
    76  		rt:           rt,
    77  		batches:      make([]*containers.Batch, batchTotalNum),
    78  		logtails:     &logtails,
    79  		batchToClose: make([]*containers.Batch, 0),
    80  		insertBatch:  roaring.New(),
    81  	}
    82  }
    83  
    84  func (b *TxnLogtailRespBuilder) Close() {
    85  	for _, bat := range b.batchToClose {
    86  		bat.Close()
    87  	}
    88  }
    89  
    90  func (b *TxnLogtailRespBuilder) CollectLogtail(txn txnif.AsyncTxn) (*[]logtail.TableLogtail, func()) {
    91  	now := time.Now()
    92  	defer func() {
    93  		v2.LogTailCollectDurationHistogram.Observe(time.Since(now).Seconds())
    94  	}()
    95  
    96  	b.txn = txn
    97  	txn.GetStore().ObserveTxn(
    98  		b.visitDatabase,
    99  		b.visitTable,
   100  		b.rotateTable,
   101  		b.visitDeltaloc,
   102  		b.visitObject,
   103  		b.visitAppend,
   104  		b.visitDelete)
   105  	b.BuildResp()
   106  	logtails := b.logtails
   107  	newlogtails := make([]logtail.TableLogtail, 0)
   108  	b.logtails = &newlogtails
   109  	return logtails, b.Close
   110  }
   111  
   112  func (b *TxnLogtailRespBuilder) visitObject(iobj any) {
   113  	obj := iobj.(*catalog.ObjectEntry)
   114  	node := obj.GetLatestNodeLocked()
   115  	if obj.IsAppendable() && node.BaseNode.IsEmpty() {
   116  		return
   117  	}
   118  	if !node.DeletedAt.Equal(&txnif.UncommitTS) {
   119  		if b.batches[objectInfoBatch] == nil {
   120  			b.batches[objectInfoBatch] = makeRespBatchFromSchema(ObjectInfoSchema, common.LogtailAllocator)
   121  		}
   122  		visitObject(b.batches[objectInfoBatch], obj, node, true, b.txn.GetPrepareTS())
   123  		return
   124  	}
   125  
   126  	if b.batches[objectInfoBatch] == nil {
   127  		b.batches[objectInfoBatch] = makeRespBatchFromSchema(ObjectInfoSchema, common.LogtailAllocator)
   128  	}
   129  	visitObject(b.batches[objectInfoBatch], obj, node, true, b.txn.GetPrepareTS())
   130  }
   131  
   132  func (b *TxnLogtailRespBuilder) visitDeltaloc(ideltalocChain any) {
   133  	deltalocChain := ideltalocChain.(*updates.DeltalocChain)
   134  	node := deltalocChain.GetLatestNodeLocked()
   135  	if node.BaseNode.DeltaLoc.IsEmpty() {
   136  		return
   137  	}
   138  	if b.batches[blkMetaInsBatch] == nil {
   139  		b.batches[blkMetaInsBatch] = makeRespBatchFromSchema(BlkMetaSchema, common.LogtailAllocator)
   140  	}
   141  	commitTS := b.txn.GetPrepareTS()
   142  	createAt := node.CreatedAt
   143  	if createAt.Equal(&txnif.UncommitTS) {
   144  		createAt = b.txn.GetPrepareTS()
   145  	}
   146  	updates.VisitDeltaloc(b.batches[blkMetaInsBatch], nil, deltalocChain.GetMeta(), deltalocChain.GetBlockID(), node, commitTS, createAt)
   147  }
   148  
   149  func (b *TxnLogtailRespBuilder) visitAppend(ibat any) {
   150  	src := ibat.(*containers.BatchWithVersion)
   151  	// sort by seqnums
   152  	sort.Sort(src)
   153  	mybat := containers.NewBatchWithCapacity(int(src.NextSeqnum) + 2)
   154  	mybat.AddVector(
   155  		catalog.AttrRowID,
   156  		src.GetVectorByName(catalog.AttrRowID).CloneWindowWithPool(0, src.Length(), b.rt.VectorPool.Small),
   157  	)
   158  	tsType := types.T_TS.ToType()
   159  	commitVec := b.rt.VectorPool.Small.GetVector(&tsType)
   160  	commitVec.PreExtend(src.Length())
   161  	for i := 0; i < src.Length(); i++ {
   162  		commitVec.Append(b.txn.GetPrepareTS(), false)
   163  	}
   164  	mybat.AddVector(catalog.AttrCommitTs, commitVec)
   165  
   166  	for i, seqnum := range src.Seqnums {
   167  		if seqnum >= objectio.SEQNUM_UPPER {
   168  			continue
   169  		}
   170  		for len(mybat.Vecs) < 2+int(seqnum) {
   171  			mybat.AppendPlaceholder()
   172  		}
   173  		vec := src.Vecs[i].CloneWindowWithPool(0, src.Length(), b.rt.VectorPool.Small)
   174  		mybat.AddVector(src.Attrs[i], vec)
   175  	}
   176  
   177  	if b.batches[dataInsBatch] == nil {
   178  		b.batches[dataInsBatch] = mybat
   179  	} else {
   180  		b.batches[dataInsBatch].Extend(mybat)
   181  		mybat.Close()
   182  	}
   183  }
   184  
   185  func (b *TxnLogtailRespBuilder) visitDelete(ctx context.Context, vnode txnif.DeleteNode) {
   186  	if vnode.IsPersistedDeletedNode() {
   187  		return
   188  	}
   189  	if b.batches[dataDelBatch] == nil {
   190  		b.batches[dataDelBatch] = makeRespBatchFromSchema(DelSchema, common.LogtailAllocator)
   191  	}
   192  	node := vnode.(*updates.DeleteNode)
   193  	meta := node.GetMeta()
   194  	schema := meta.GetSchema()
   195  	pkDef := schema.GetPrimaryKey()
   196  	deletes := node.GetRowMaskRefLocked()
   197  	blkID := node.GetBlockID()
   198  
   199  	batch := b.batches[dataDelBatch]
   200  	rowIDVec := batch.GetVectorByName(catalog.AttrRowID)
   201  	commitTSVec := batch.GetVectorByName(catalog.AttrCommitTs)
   202  	var pkVec containers.Vector
   203  	if len(batch.Vecs) == 2 {
   204  		pkVec = containers.MakeVector(pkDef.Type, common.LogtailAllocator)
   205  		batch.AddVector(catalog.AttrPKVal, pkVec)
   206  	} else {
   207  		pkVec = batch.GetVectorByName(catalog.AttrPKVal)
   208  	}
   209  
   210  	it := deletes.Iterator()
   211  	rowid2PK := node.DeletedPK()
   212  	for it.HasNext() {
   213  		del := it.Next()
   214  		rowid := objectio.NewRowid(blkID, del)
   215  		rowIDVec.Append(*rowid, false)
   216  		commitTSVec.Append(b.txn.GetPrepareTS(), false)
   217  
   218  		v, ok := rowid2PK[del]
   219  		if ok {
   220  			pkVec.Extend(v)
   221  		}
   222  		//if !ok {
   223  		//	panic(fmt.Sprintf("rowid %d 's pk not found in rowid2PK.\n", del))
   224  		//}
   225  		//pkVec.Extend(v)
   226  	}
   227  
   228  	//_ = meta.GetObjectData().Foreach(
   229  	//	ctx,
   230  	//	schema,
   231  	//	pkDef.Idx,
   232  	//	func(v any, isNull bool, row int) error {
   233  	//		pkVec.Append(v, false)
   234  	//		return nil
   235  	//	},
   236  	//	&dels,
   237  	//)
   238  }
   239  
   240  func (b *TxnLogtailRespBuilder) visitTable(itbl any) {
   241  	tbl := itbl.(*catalog.TableEntry)
   242  	node := tbl.GetLatestNodeLocked()
   243  	// delete table
   244  	if node.DeletedAt.Equal(&txnif.UncommitTS) {
   245  		if b.batches[columnDelBatch] == nil {
   246  			b.batches[columnDelBatch] = makeRespBatchFromSchema(ColumnDelSchema, common.LogtailAllocator)
   247  		}
   248  		for _, usercol := range node.BaseNode.Schema.ColDefs {
   249  			b.batches[columnDelBatch].GetVectorByName(catalog.AttrRowID).Append(objectio.HackBytes2Rowid([]byte(fmt.Sprintf("%d-%s", tbl.ID, usercol.Name))), false)
   250  			b.batches[columnDelBatch].GetVectorByName(catalog.AttrCommitTs).Append(b.txn.GetPrepareTS(), false)
   251  			b.batches[columnDelBatch].GetVectorByName(pkgcatalog.SystemColAttr_UniqName).Append([]byte(fmt.Sprintf("%d-%s", tbl.GetID(), usercol.Name)), false)
   252  		}
   253  		if b.batches[tblDelBatch] == nil {
   254  			b.batches[tblDelBatch] = makeRespBatchFromSchema(TblDelSchema, common.LogtailAllocator)
   255  			b.batches[tblSpecialDeleteBatch] = makeRespBatchFromSchema(TBLSpecialDeleteSchema, common.LogtailAllocator)
   256  		}
   257  		catalogEntry2Batch(b.batches[tblDelBatch], tbl, node, TblDelSchema, txnimpl.FillTableRow, objectio.HackU64ToRowid(tbl.GetID()), b.txn.GetPrepareTS())
   258  		catalogEntry2Batch(b.batches[tblSpecialDeleteBatch], tbl, node, TBLSpecialDeleteSchema, txnimpl.FillTableRow, objectio.HackU64ToRowid(tbl.GetID()), b.txn.GetPrepareTS())
   259  	}
   260  	// create table
   261  	if node.CreatedAt.Equal(&txnif.UncommitTS) {
   262  		if b.batches[columnInsBatch] == nil {
   263  			b.batches[columnInsBatch] = makeRespBatchFromSchema(catalog.SystemColumnSchema, common.LogtailAllocator)
   264  		}
   265  		for _, syscol := range catalog.SystemColumnSchema.ColDefs {
   266  			txnimpl.FillColumnRow(tbl, node, syscol.Name, b.batches[columnInsBatch].GetVectorByName(syscol.Name))
   267  		}
   268  		for _, usercol := range node.BaseNode.Schema.ColDefs {
   269  			b.batches[columnInsBatch].GetVectorByName(catalog.AttrRowID).Append(objectio.HackBytes2Rowid([]byte(fmt.Sprintf("%d-%s", tbl.ID, usercol.Name))), false)
   270  			b.batches[columnInsBatch].GetVectorByName(catalog.AttrCommitTs).Append(b.txn.GetPrepareTS(), false)
   271  		}
   272  		if b.batches[tblInsBatch] == nil {
   273  			b.batches[tblInsBatch] = makeRespBatchFromSchema(catalog.SystemTableSchema, common.LogtailAllocator)
   274  		}
   275  		catalogEntry2Batch(b.batches[tblInsBatch], tbl, node, catalog.SystemTableSchema, txnimpl.FillTableRow, objectio.HackU64ToRowid(tbl.GetID()), b.txn.GetPrepareTS())
   276  	}
   277  	// alter table
   278  	if !node.CreatedAt.Equal(&txnif.UncommitTS) && !node.DeletedAt.Equal(&txnif.UncommitTS) {
   279  		if b.batches[columnInsBatch] == nil {
   280  			b.batches[columnInsBatch] = makeRespBatchFromSchema(catalog.SystemColumnSchema, common.LogtailAllocator)
   281  		}
   282  		if b.batches[columnDelBatch] == nil {
   283  			b.batches[columnDelBatch] = makeRespBatchFromSchema(ColumnDelSchema, common.LogtailAllocator)
   284  		}
   285  		for _, syscol := range catalog.SystemColumnSchema.ColDefs {
   286  			txnimpl.FillColumnRow(tbl, node, syscol.Name, b.batches[columnInsBatch].GetVectorByName(syscol.Name))
   287  		}
   288  		for _, usercol := range node.BaseNode.Schema.ColDefs {
   289  			b.batches[columnInsBatch].GetVectorByName(catalog.AttrRowID).Append(objectio.HackBytes2Rowid([]byte(fmt.Sprintf("%d-%s", tbl.ID, usercol.Name))), false)
   290  			b.batches[columnInsBatch].GetVectorByName(catalog.AttrCommitTs).Append(b.txn.GetPrepareTS(), false)
   291  		}
   292  		for _, name := range node.BaseNode.Schema.Extra.DroppedAttrs {
   293  			b.batches[columnDelBatch].GetVectorByName(catalog.AttrRowID).Append(objectio.HackBytes2Rowid([]byte(fmt.Sprintf("%d-%s", tbl.ID, name))), false)
   294  			b.batches[columnDelBatch].GetVectorByName(catalog.AttrCommitTs).Append(b.txn.GetPrepareTS(), false)
   295  			b.batches[columnDelBatch].GetVectorByName(pkgcatalog.SystemColAttr_UniqName).Append([]byte(fmt.Sprintf("%d-%s", tbl.GetID(), name)), false)
   296  		}
   297  		if b.batches[tblInsBatch] == nil {
   298  			b.batches[tblInsBatch] = makeRespBatchFromSchema(catalog.SystemTableSchema, common.LogtailAllocator)
   299  		}
   300  		catalogEntry2Batch(b.batches[tblInsBatch], tbl, node, catalog.SystemTableSchema, txnimpl.FillTableRow, objectio.HackU64ToRowid(tbl.GetID()), b.txn.GetPrepareTS())
   301  	}
   302  }
   303  func (b *TxnLogtailRespBuilder) visitDatabase(idb any) {
   304  	db := idb.(*catalog.DBEntry)
   305  	node := db.GetLatestNodeLocked()
   306  	if node.DeletedAt.Equal(&txnif.UncommitTS) {
   307  		if b.batches[dbDelBatch] == nil {
   308  			b.batches[dbDelBatch] = makeRespBatchFromSchema(DBDelSchema, common.LogtailAllocator)
   309  			b.batches[dbSpecialDeleteBatch] = makeRespBatchFromSchema(DBSpecialDeleteSchema, common.LogtailAllocator)
   310  		}
   311  		catalogEntry2Batch(b.batches[dbDelBatch], db, node, DBDelSchema, txnimpl.FillDBRow, objectio.HackU64ToRowid(db.GetID()), b.txn.GetPrepareTS())
   312  		catalogEntry2Batch(b.batches[dbSpecialDeleteBatch], db, node, DBSpecialDeleteSchema, txnimpl.FillDBRow, objectio.HackU64ToRowid(db.GetID()), b.txn.GetPrepareTS())
   313  	}
   314  	if node.CreatedAt.Equal(&txnif.UncommitTS) {
   315  		if b.batches[dbInsBatch] == nil {
   316  			b.batches[dbInsBatch] = makeRespBatchFromSchema(catalog.SystemDBSchema, common.LogtailAllocator)
   317  		}
   318  		catalogEntry2Batch(
   319  			b.batches[dbInsBatch],
   320  			db,
   321  			node,
   322  			catalog.SystemDBSchema,
   323  			txnimpl.FillDBRow,
   324  			objectio.HackU64ToRowid(db.GetID()),
   325  			b.txn.GetPrepareTS(),
   326  		)
   327  	}
   328  }
   329  
   330  func (b *TxnLogtailRespBuilder) buildLogtailEntry(tid, dbid uint64, tableName, dbName string, batchIdx int8, delete bool) {
   331  	bat := b.batches[batchIdx]
   332  	if bat == nil || bat.Length() == 0 {
   333  		return
   334  	}
   335  	apiBat, err := containersBatchToProtoBatch(bat)
   336  	common.DoIfDebugEnabled(func() {
   337  		logutil.Debugf(
   338  			"[logtail] from table %d-%s, delete %v, batch length %d @%s",
   339  			tid, tableName, delete, bat.Length(), b.txn.GetPrepareTS().ToString(),
   340  		)
   341  	})
   342  	if err != nil {
   343  		panic(err)
   344  	}
   345  	entryType := api.Entry_Insert
   346  	if delete {
   347  		entryType = api.Entry_Delete
   348  	}
   349  	if batchIdx == dbSpecialDeleteBatch || batchIdx == tblSpecialDeleteBatch {
   350  		entryType = api.Entry_SpecialDelete
   351  	}
   352  	entry := &api.Entry{
   353  		EntryType:    entryType,
   354  		TableId:      tid,
   355  		TableName:    tableName,
   356  		DatabaseId:   dbid,
   357  		DatabaseName: dbName,
   358  		Bat:          apiBat,
   359  	}
   360  	ts := b.txn.GetPrepareTS().ToTimestamp()
   361  	tableID := &api.TableID{
   362  		DbId: dbid,
   363  		TbId: tid,
   364  	}
   365  	if b.currentLogtail == nil {
   366  		b.currentLogtail = &logtail.TableLogtail{
   367  			Ts:       &ts,
   368  			Table:    tableID,
   369  			Commands: make([]api.Entry, 0),
   370  		}
   371  	} else {
   372  		if tid != b.currentLogtail.Table.TbId {
   373  			*b.logtails = append(*b.logtails, *b.currentLogtail)
   374  			b.currentLogtail = &logtail.TableLogtail{
   375  				Ts:       &ts,
   376  				Table:    tableID,
   377  				Commands: make([]api.Entry, 0),
   378  			}
   379  		}
   380  	}
   381  	b.currentLogtail.Commands = append(b.currentLogtail.Commands, *entry)
   382  	// specail delete batch and delete batch should be in the same TableLogtail
   383  	if batchIdx == dbDelBatch || batchIdx == tblDelBatch {
   384  		var bat2 *containers.Batch
   385  		if batchIdx == dbDelBatch {
   386  			bat2 = b.batches[dbSpecialDeleteBatch]
   387  		}
   388  		if batchIdx == tblDelBatch {
   389  			bat2 = b.batches[tblSpecialDeleteBatch]
   390  		}
   391  		apiBat2, err := containersBatchToProtoBatch(bat2)
   392  		if err != nil {
   393  			panic(err)
   394  		}
   395  		entry2 := &api.Entry{
   396  			EntryType:    api.Entry_SpecialDelete,
   397  			TableId:      tid,
   398  			TableName:    tableName,
   399  			DatabaseId:   dbid,
   400  			DatabaseName: dbName,
   401  			Bat:          apiBat2,
   402  		}
   403  		b.currentLogtail.Commands = append(b.currentLogtail.Commands, *entry2)
   404  	}
   405  }
   406  
   407  func (b *TxnLogtailRespBuilder) rotateTable(dbName, tableName string, dbid, tid uint64) {
   408  	b.buildLogtailEntry(b.currTableID, b.currDBID, fmt.Sprintf("_%d_meta", b.currTableID), b.currDBName, blkMetaInsBatch, false)
   409  	if b.batches[blkMetaInsBatch] != nil {
   410  		b.batchToClose = append(b.batchToClose, b.batches[blkMetaInsBatch])
   411  		b.batches[blkMetaInsBatch] = nil
   412  	}
   413  	b.buildLogtailEntry(b.currTableID, b.currDBID, fmt.Sprintf("_%d_meta", b.currTableID), b.currDBName, blkMetaDelBatch, true)
   414  	if b.batches[blkMetaDelBatch] != nil {
   415  		b.batchToClose = append(b.batchToClose, b.batches[blkMetaDelBatch])
   416  		b.batches[blkMetaDelBatch] = nil
   417  	}
   418  
   419  	b.buildLogtailEntry(b.currTableID, b.currDBID, fmt.Sprintf("_%d_obj", b.currTableID), b.currDBName, objectInfoBatch, false)
   420  	if b.batches[objectInfoBatch] != nil {
   421  		b.batchToClose = append(b.batchToClose, b.batches[objectInfoBatch])
   422  		b.batches[objectInfoBatch] = nil
   423  	}
   424  	b.buildLogtailEntry(b.currTableID, b.currDBID, b.currTableName, b.currDBName, dataDelBatch, true)
   425  	if b.batches[dataDelBatch] != nil {
   426  		b.batchToClose = append(b.batchToClose, b.batches[dataDelBatch])
   427  		b.batches[dataDelBatch] = nil
   428  	}
   429  	b.buildLogtailEntry(b.currTableID, b.currDBID, b.currTableName, b.currDBName, dataInsBatch, false)
   430  	if b.batches[dataInsBatch] != nil {
   431  		b.insertBatch.Add(uint32(len(b.batchToClose)))
   432  		b.batchToClose = append(b.batchToClose, b.batches[dataInsBatch])
   433  		b.batches[dataInsBatch] = nil
   434  	}
   435  	b.currTableID = tid
   436  	b.currDBID = dbid
   437  	b.currTableName = tableName
   438  	b.currDBName = dbName
   439  }
   440  
   441  func (b *TxnLogtailRespBuilder) BuildResp() {
   442  	b.buildLogtailEntry(b.currTableID, b.currDBID, fmt.Sprintf("_%d_meta", b.currTableID), b.currDBName, blkMetaInsBatch, false)
   443  	b.buildLogtailEntry(b.currTableID, b.currDBID, fmt.Sprintf("_%d_meta", b.currTableID), b.currDBName, blkMetaDelBatch, true)
   444  	b.buildLogtailEntry(b.currTableID, b.currDBID, fmt.Sprintf("_%d_obj", b.currTableID), b.currDBName, objectInfoBatch, false)
   445  	b.buildLogtailEntry(b.currTableID, b.currDBID, b.currTableName, b.currDBName, dataDelBatch, true)
   446  	b.buildLogtailEntry(b.currTableID, b.currDBID, b.currTableName, b.currDBName, dataInsBatch, false)
   447  
   448  	b.buildLogtailEntry(pkgcatalog.MO_TABLES_ID, pkgcatalog.MO_CATALOG_ID, pkgcatalog.MO_TABLES, pkgcatalog.MO_CATALOG, tblInsBatch, false)
   449  	b.buildLogtailEntry(pkgcatalog.MO_TABLES_ID, pkgcatalog.MO_CATALOG_ID, pkgcatalog.MO_TABLES, pkgcatalog.MO_CATALOG, tblDelBatch, true)
   450  	b.buildLogtailEntry(pkgcatalog.MO_COLUMNS_ID, pkgcatalog.MO_CATALOG_ID, pkgcatalog.MO_COLUMNS, pkgcatalog.MO_CATALOG, columnInsBatch, false)
   451  	b.buildLogtailEntry(pkgcatalog.MO_COLUMNS_ID, pkgcatalog.MO_CATALOG_ID, pkgcatalog.MO_COLUMNS, pkgcatalog.MO_CATALOG, columnDelBatch, true)
   452  	b.buildLogtailEntry(pkgcatalog.MO_DATABASE_ID, pkgcatalog.MO_CATALOG_ID, pkgcatalog.MO_DATABASE, pkgcatalog.MO_CATALOG, dbInsBatch, false)
   453  	b.buildLogtailEntry(pkgcatalog.MO_DATABASE_ID, pkgcatalog.MO_CATALOG_ID, pkgcatalog.MO_DATABASE, pkgcatalog.MO_CATALOG, dbDelBatch, true)
   454  	for i := range b.batches {
   455  		if b.batches[i] != nil {
   456  			if int8(i) == dataInsBatch {
   457  				b.insertBatch.Add(uint32(len(b.batchToClose)))
   458  			}
   459  			b.batchToClose = append(b.batchToClose, b.batches[i])
   460  			b.batches[i] = nil
   461  		}
   462  	}
   463  	if b.currentLogtail != nil {
   464  		*b.logtails = append(*b.logtails, *b.currentLogtail)
   465  		b.currentLogtail = nil
   466  	}
   467  }