github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/txn/txnimpl/store.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 txnimpl
    16  
    17  import (
    18  	"context"
    19  	"runtime/trace"
    20  	"sync"
    21  	"sync/atomic"
    22  	"time"
    23  
    24  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    25  
    26  	"github.com/matrixorigin/matrixone/pkg/perfcounter"
    27  	"go.uber.org/zap"
    28  
    29  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    30  	"github.com/matrixorigin/matrixone/pkg/common/moprobe"
    31  	"github.com/matrixorigin/matrixone/pkg/logutil"
    32  	"github.com/matrixorigin/matrixone/pkg/objectio"
    33  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    34  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    35  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    36  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/db/dbutils"
    37  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle"
    38  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    39  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/entry"
    40  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables"
    41  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates"
    42  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    43  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal"
    44  )
    45  
    46  var (
    47  	_tracerPool = sync.Pool{
    48  		New: func() any {
    49  			return &txnTracer{}
    50  		},
    51  	}
    52  )
    53  
    54  func getTracer() *txnTracer {
    55  	return _tracerPool.Get().(*txnTracer)
    56  }
    57  
    58  func putTracer(tracer *txnTracer) {
    59  	tracer.task = nil
    60  	tracer.state = 0
    61  	_tracerPool.Put(tracer)
    62  }
    63  
    64  type txnTracer struct {
    65  	state uint8
    66  	task  *trace.Task
    67  	stamp time.Time
    68  }
    69  
    70  func (tracer *txnTracer) Trigger(state uint8) {
    71  	switch state {
    72  	case 0: // start preparing wait
    73  		_, tracer.task = trace.NewTask(context.Background(), "1-PreparingWait")
    74  		tracer.stamp = time.Now()
    75  		tracer.state = 0
    76  
    77  	case 1: // end preparing wait and start preparing
    78  		if tracer.task != nil && tracer.state == 0 {
    79  			tracer.task.End()
    80  			v2.TxnPreparingWaitDurationHistogram.Observe(time.Since(tracer.stamp).Seconds())
    81  		}
    82  		_, tracer.task = trace.NewTask(context.Background(), "2-Preparing")
    83  		tracer.stamp = time.Now()
    84  		tracer.state = 1
    85  
    86  	case 2: // end preparing and start prepare wal wait
    87  		if tracer.task != nil && tracer.state == 1 {
    88  			tracer.task.End()
    89  			v2.TxnPreparingDurationHistogram.Observe(time.Since(tracer.stamp).Seconds())
    90  		}
    91  		_, tracer.task = trace.NewTask(context.Background(), "3-PrepareWalWait")
    92  		tracer.stamp = time.Now()
    93  		tracer.state = 2
    94  
    95  	case 3: // end prepare wal wait and start prepare wal
    96  		if tracer.task != nil && tracer.state == 2 {
    97  			tracer.task.End()
    98  			v2.TxnPrepareWalWaitDurationHistogram.Observe(time.Since(tracer.stamp).Seconds())
    99  		}
   100  		_, tracer.task = trace.NewTask(context.Background(), "4-PrepareWal")
   101  		tracer.stamp = time.Now()
   102  		tracer.state = 3
   103  
   104  	case 4: // end prepare wal and start prepared wait
   105  		if tracer.task != nil && tracer.state == 3 {
   106  			tracer.task.End()
   107  			v2.TxnPrepareWalDurationHistogram.Observe(time.Since(tracer.stamp).Seconds())
   108  		}
   109  		_, tracer.task = trace.NewTask(context.Background(), "5-PreparedWait")
   110  		tracer.stamp = time.Now()
   111  		tracer.state = 4
   112  
   113  	case 5: // end prepared wait and start prepared
   114  		if tracer.task != nil && tracer.state == 4 {
   115  			tracer.task.End()
   116  			v2.TxnPreparedWaitDurationHistogram.Observe(time.Since(tracer.stamp).Seconds())
   117  		}
   118  		_, tracer.task = trace.NewTask(context.Background(), "6-Prepared")
   119  		tracer.stamp = time.Now()
   120  		tracer.state = 5
   121  	}
   122  }
   123  
   124  func (tracer *txnTracer) Stop() {
   125  	if tracer.task != nil && tracer.state == 5 {
   126  		tracer.task.End()
   127  		v2.TxnPreparedDurationHistogram.Observe(time.Since(tracer.stamp).Seconds())
   128  	}
   129  	tracer.task = nil
   130  	tracer.state = 0
   131  }
   132  
   133  type txnStore struct {
   134  	ctx context.Context
   135  	txnbase.NoopTxnStore
   136  	mu          sync.RWMutex
   137  	rt          *dbutils.Runtime
   138  	dbs         map[uint64]*txnDB
   139  	driver      wal.Driver
   140  	txn         txnif.AsyncTxn
   141  	catalog     *catalog.Catalog
   142  	cmdMgr      *commandManager
   143  	logs        []entry.Entry
   144  	warChecker  *warChecker
   145  	dataFactory *tables.DataFactory
   146  	writeOps    atomic.Uint32
   147  	tracer      *txnTracer
   148  
   149  	wg sync.WaitGroup
   150  }
   151  
   152  var TxnStoreFactory = func(
   153  	ctx context.Context,
   154  	catalog *catalog.Catalog,
   155  	driver wal.Driver,
   156  	rt *dbutils.Runtime,
   157  	dataFactory *tables.DataFactory,
   158  	maxMessageSize uint64) txnbase.TxnStoreFactory {
   159  	return func() txnif.TxnStore {
   160  		return newStore(ctx, catalog, driver, rt, dataFactory, maxMessageSize)
   161  	}
   162  }
   163  
   164  func newStore(
   165  	ctx context.Context,
   166  	catalog *catalog.Catalog,
   167  	driver wal.Driver,
   168  	rt *dbutils.Runtime,
   169  	dataFactory *tables.DataFactory,
   170  	maxMessageSize uint64) *txnStore {
   171  	return &txnStore{
   172  		ctx:         ctx,
   173  		rt:          rt,
   174  		dbs:         make(map[uint64]*txnDB),
   175  		catalog:     catalog,
   176  		cmdMgr:      newCommandManager(driver, maxMessageSize),
   177  		driver:      driver,
   178  		logs:        make([]entry.Entry, 0),
   179  		dataFactory: dataFactory,
   180  		wg:          sync.WaitGroup{},
   181  	}
   182  }
   183  
   184  func (store *txnStore) StartTrace() {
   185  	if store.IsReadonly() || store.GetTransactionType() == txnif.TxnType_Heartbeat {
   186  		return
   187  	}
   188  	store.tracer = getTracer()
   189  	store.tracer.Trigger(txnif.TraceStart)
   190  }
   191  
   192  func (store *txnStore) EndTrace() {
   193  	if store.tracer == nil {
   194  		return
   195  	}
   196  	tracer := store.tracer
   197  	store.tracer = nil
   198  	tracer.Stop()
   199  	putTracer(tracer)
   200  }
   201  
   202  func (store *txnStore) TriggerTrace(state uint8) {
   203  	if store.tracer == nil {
   204  		return
   205  	}
   206  	store.tracer.Trigger(state)
   207  }
   208  
   209  func (store *txnStore) GetContext() context.Context    { return store.ctx }
   210  func (store *txnStore) SetContext(ctx context.Context) { store.ctx = ctx }
   211  
   212  func (store *txnStore) IsReadonly() bool {
   213  	return store.writeOps.Load() == 0
   214  }
   215  
   216  func (store *txnStore) IncreateWriteCnt() int {
   217  	return int(store.writeOps.Add(1))
   218  }
   219  
   220  func (store *txnStore) LogTxnEntry(dbId uint64, tableId uint64, entry txnif.TxnEntry, readed []*common.ID) (err error) {
   221  	db, err := store.getOrSetDB(dbId)
   222  	if err != nil {
   223  		return
   224  	}
   225  	return db.LogTxnEntry(tableId, entry, readed)
   226  }
   227  
   228  func (store *txnStore) LogTxnState(sync bool) (logEntry entry.Entry, err error) {
   229  	cmd := txnbase.NewTxnStateCmd(
   230  		store.txn.GetID(),
   231  		store.txn.GetTxnState(false),
   232  		store.txn.GetCommitTS(),
   233  	)
   234  	var buf []byte
   235  	if buf, err = cmd.MarshalBinary(); err != nil {
   236  		return
   237  	}
   238  	logEntry = entry.GetBase()
   239  	logEntry.SetType(IOET_WALEntry_TxnRecord)
   240  	if err = logEntry.SetPayload(buf); err != nil {
   241  		return
   242  	}
   243  	info := &entry.Info{
   244  		Group: wal.GroupC,
   245  	}
   246  	logEntry.SetInfo(info)
   247  	var lsn uint64
   248  	lsn, err = store.driver.AppendEntry(wal.GroupC, logEntry)
   249  	if err != nil {
   250  		return
   251  	}
   252  	if sync {
   253  		err = logEntry.WaitDone()
   254  	}
   255  	logutil.Debugf("LogTxnState LSN=%d, Size=%d", lsn, len(buf))
   256  	return
   257  }
   258  
   259  func (store *txnStore) Close() error {
   260  	var err error
   261  	for _, db := range store.dbs {
   262  		if err = db.Close(); err != nil {
   263  			break
   264  		}
   265  	}
   266  	store.dbs = nil
   267  	store.cmdMgr = nil
   268  	store.logs = nil
   269  	store.warChecker = nil
   270  	return err
   271  }
   272  
   273  func (store *txnStore) BindTxn(txn txnif.AsyncTxn) {
   274  	store.txn = txn
   275  }
   276  
   277  func (store *txnStore) BatchDedup(dbId, id uint64, pk containers.Vector) (err error) {
   278  	db, err := store.getOrSetDB(dbId)
   279  	if err != nil {
   280  		return err
   281  	}
   282  	// if table.IsDeleted() {
   283  	// 	return txnbase.ErrNotFound
   284  	// }
   285  
   286  	return db.BatchDedup(id, pk)
   287  }
   288  
   289  func (store *txnStore) Append(ctx context.Context, dbId, id uint64, data *containers.Batch) error {
   290  	store.IncreateWriteCnt()
   291  	db, err := store.getOrSetDB(dbId)
   292  	if err != nil {
   293  		return err
   294  	}
   295  	// if db.IsDeleted() {
   296  	// 	return txnbase.ErrNotFound
   297  	// }
   298  	return db.Append(ctx, id, data)
   299  }
   300  
   301  func (store *txnStore) AddObjsWithMetaLoc(
   302  	ctx context.Context,
   303  	dbId, tid uint64,
   304  	stats containers.Vector,
   305  ) error {
   306  	store.IncreateWriteCnt()
   307  	db, err := store.getOrSetDB(dbId)
   308  	if err != nil {
   309  		return err
   310  	}
   311  	return db.AddObjsWithMetaLoc(ctx, tid, stats)
   312  }
   313  
   314  func (store *txnStore) RangeDelete(
   315  	id *common.ID, start, end uint32,
   316  	pkVec containers.Vector, dt handle.DeleteType,
   317  ) (err error) {
   318  	db, err := store.getOrSetDB(id.DbID)
   319  	if err != nil {
   320  		return err
   321  	}
   322  	return db.RangeDelete(id, start, end, pkVec, dt)
   323  }
   324  
   325  func (store *txnStore) TryDeleteByDeltaloc(
   326  	id *common.ID, deltaloc objectio.Location,
   327  ) (ok bool, err error) {
   328  	db, err := store.getOrSetDB(id.DbID)
   329  	if err != nil {
   330  		return
   331  	}
   332  	return db.TryDeleteByDeltaloc(id, deltaloc)
   333  }
   334  
   335  func (store *txnStore) UpdateDeltaLoc(id *common.ID, deltaLoc objectio.Location) (err error) {
   336  	store.IncreateWriteCnt()
   337  	db, err := store.getOrSetDB(id.DbID)
   338  	if err != nil {
   339  		return err
   340  	}
   341  	// if table.IsDeleted() {
   342  	// 	return txnbase.ErrNotFound
   343  	// }
   344  	return db.UpdateDeltaLoc(id, deltaLoc)
   345  }
   346  
   347  func (store *txnStore) GetByFilter(ctx context.Context, dbId, tid uint64, filter *handle.Filter) (id *common.ID, offset uint32, err error) {
   348  	db, err := store.getOrSetDB(dbId)
   349  	if err != nil {
   350  		return
   351  	}
   352  	// if table.IsDeleted() {
   353  	// 	err = txnbase.ErrNotFound
   354  	// 	return
   355  	// }
   356  	return db.GetByFilter(ctx, tid, filter)
   357  }
   358  
   359  func (store *txnStore) GetValue(id *common.ID, row uint32, colIdx uint16) (v any, isNull bool, err error) {
   360  	db, err := store.getOrSetDB(id.DbID)
   361  	if err != nil {
   362  		return
   363  	}
   364  	// if table.IsDeleted() {
   365  	// 	err = txnbase.ErrNotFound
   366  	// 	return
   367  	// }
   368  	return db.GetValue(id, row, colIdx)
   369  }
   370  
   371  func (store *txnStore) DatabaseNames() (names []string) {
   372  	it := newDBIt(store.txn, store.catalog)
   373  	for it.Valid() {
   374  		names = append(names, it.GetCurr().GetName())
   375  		it.Next()
   376  	}
   377  	return
   378  }
   379  
   380  func (store *txnStore) UseDatabase(name string) (err error) {
   381  	return err
   382  }
   383  
   384  func (store *txnStore) UnsafeGetDatabase(id uint64) (h handle.Database, err error) {
   385  	meta, err := store.catalog.GetDatabaseByID(id)
   386  	if err != nil {
   387  		return
   388  	}
   389  	var db *txnDB
   390  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   391  		return
   392  	}
   393  	h = buildDB(db)
   394  	return
   395  }
   396  
   397  func (store *txnStore) GetDatabase(name string) (h handle.Database, err error) {
   398  	defer func() {
   399  		if err == moerr.GetOkExpectedEOB() {
   400  			err = moerr.NewBadDBNoCtx(name)
   401  		}
   402  	}()
   403  	meta, err := store.catalog.TxnGetDBEntryByName(name, store.txn)
   404  	if err != nil {
   405  		return
   406  	}
   407  	var db *txnDB
   408  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   409  		return
   410  	}
   411  	h = buildDB(db)
   412  	return
   413  }
   414  
   415  func (store *txnStore) GetDatabaseByID(id uint64) (h handle.Database, err error) {
   416  	meta, err := store.catalog.TxnGetDBEntryByID(id, store.txn)
   417  	if err != nil {
   418  		return
   419  	}
   420  	var db *txnDB
   421  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   422  		return
   423  	}
   424  	h = buildDB(db)
   425  	return
   426  }
   427  
   428  func (store *txnStore) CreateDatabase(name, createSql, datTyp string) (h handle.Database, err error) {
   429  	meta, err := store.catalog.CreateDBEntry(name, createSql, datTyp, store.txn)
   430  	if err != nil {
   431  		return nil, err
   432  	}
   433  	var db *txnDB
   434  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   435  		return
   436  	}
   437  	if err = db.SetCreateEntry(meta); err != nil {
   438  		return
   439  	}
   440  	h = buildDB(db)
   441  	return
   442  }
   443  
   444  func (store *txnStore) CreateDatabaseWithID(name, createSql, datTyp string, id uint64) (h handle.Database, err error) {
   445  	meta, err := store.catalog.CreateDBEntryWithID(name, createSql, datTyp, id, store.txn)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  	var db *txnDB
   450  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   451  		return
   452  	}
   453  	if err = db.SetCreateEntry(meta); err != nil {
   454  		return
   455  	}
   456  	h = buildDB(db)
   457  	return
   458  }
   459  
   460  func (store *txnStore) DropDatabase(name string) (h handle.Database, err error) {
   461  	hasNewEntry, meta, err := store.catalog.DropDBEntryByName(name, store.txn)
   462  	if err != nil {
   463  		return
   464  	}
   465  	db, err := store.getOrSetDB(meta.GetID())
   466  	if err != nil {
   467  		return
   468  	}
   469  	if hasNewEntry {
   470  		if err = db.SetDropEntry(meta); err != nil {
   471  			return
   472  		}
   473  	}
   474  	h = buildDB(db)
   475  	return
   476  }
   477  
   478  func (store *txnStore) ObserveTxn(
   479  	visitDatabase func(db any),
   480  	visitTable func(tbl any),
   481  	rotateTable func(dbName, tblName string, dbid, tid uint64),
   482  	visitMetadata func(block any),
   483  	visitObject func(obj any),
   484  	visitAppend func(bat any),
   485  	visitDelete func(ctx context.Context, vnode txnif.DeleteNode)) {
   486  	for _, db := range store.dbs {
   487  		if db.createEntry != nil || db.dropEntry != nil {
   488  			visitDatabase(db.entry)
   489  		}
   490  		dbName := db.entry.GetName()
   491  		dbid := db.entry.ID
   492  		for _, tbl := range db.tables {
   493  			tblName := tbl.GetLocalSchema().Name
   494  			tid := tbl.entry.ID
   495  			rotateTable(dbName, tblName, dbid, tid)
   496  			if tbl.createEntry != nil || tbl.dropEntry != nil {
   497  				visitTable(tbl.entry)
   498  			}
   499  			for _, iTxnEntry := range tbl.txnEntries.entries {
   500  				switch txnEntry := iTxnEntry.(type) {
   501  				case *catalog.ObjectEntry:
   502  					visitObject(txnEntry)
   503  				case *updates.DeltalocChain:
   504  					visitMetadata(txnEntry)
   505  				case *updates.DeleteNode:
   506  					visitDelete(store.ctx, txnEntry)
   507  				case *catalog.TableEntry:
   508  					if tbl.createEntry != nil || tbl.dropEntry != nil {
   509  						continue
   510  					}
   511  					visitTable(txnEntry)
   512  				}
   513  			}
   514  			if tbl.tableSpace != nil {
   515  				for _, node := range tbl.tableSpace.nodes {
   516  					anode, ok := node.(*anode)
   517  					if ok {
   518  						schema := anode.table.GetLocalSchema()
   519  						bat := &containers.BatchWithVersion{
   520  							Version:    schema.Version,
   521  							NextSeqnum: uint16(schema.Extra.NextColSeqnum),
   522  							Seqnums:    schema.AllSeqnums(),
   523  							Batch:      anode.data,
   524  						}
   525  						visitAppend(bat)
   526  					}
   527  				}
   528  			}
   529  		}
   530  	}
   531  }
   532  func (store *txnStore) AddWaitEvent(cnt int) {
   533  	store.wg.Add(cnt)
   534  }
   535  func (store *txnStore) DoneWaitEvent(cnt int) {
   536  	store.wg.Add(-cnt)
   537  }
   538  func (store *txnStore) DropDatabaseByID(id uint64) (h handle.Database, err error) {
   539  	hasNewEntry, meta, err := store.catalog.DropDBEntryByID(id, store.txn)
   540  	if err != nil {
   541  		return
   542  	}
   543  	db, err := store.getOrSetDB(meta.GetID())
   544  	if err != nil {
   545  		return
   546  	}
   547  	if hasNewEntry {
   548  		if err = db.SetDropEntry(meta); err != nil {
   549  			return
   550  		}
   551  	}
   552  	h = buildDB(db)
   553  	return
   554  }
   555  
   556  func (store *txnStore) CreateRelation(dbId uint64, def any) (relation handle.Relation, err error) {
   557  	db, err := store.getOrSetDB(dbId)
   558  	if err != nil {
   559  		return
   560  	}
   561  	return db.CreateRelation(def)
   562  }
   563  
   564  func (store *txnStore) CreateRelationWithTableId(dbId uint64, tableId uint64, def any) (relation handle.Relation, err error) {
   565  	db, err := store.getOrSetDB(dbId)
   566  	if err != nil {
   567  		return
   568  	}
   569  	return db.CreateRelationWithTableId(tableId, def)
   570  }
   571  
   572  func (store *txnStore) DropRelationByName(dbId uint64, name string) (relation handle.Relation, err error) {
   573  	db, err := store.getOrSetDB(dbId)
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  	return db.DropRelationByName(name)
   578  }
   579  
   580  func (store *txnStore) DropRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) {
   581  	db, err := store.getOrSetDB(dbId)
   582  	if err != nil {
   583  		return nil, err
   584  	}
   585  	return db.DropRelationByID(id)
   586  }
   587  
   588  func (store *txnStore) UnsafeGetRelation(dbId, id uint64) (relation handle.Relation, err error) {
   589  	db, err := store.getOrSetDB(dbId)
   590  	if err != nil {
   591  		return nil, err
   592  	}
   593  	return db.UnsafeGetRelation(id)
   594  }
   595  
   596  func (store *txnStore) GetRelationByName(dbId uint64, name string) (relation handle.Relation, err error) {
   597  	db, err := store.getOrSetDB(dbId)
   598  	if err != nil {
   599  		return nil, err
   600  	}
   601  	return db.GetRelationByName(name)
   602  }
   603  
   604  func (store *txnStore) GetRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) {
   605  	db, err := store.getOrSetDB(dbId)
   606  	if err != nil {
   607  		return nil, err
   608  	}
   609  	return db.GetRelationByID(id)
   610  }
   611  
   612  func (store *txnStore) GetObject(id *common.ID) (obj handle.Object, err error) {
   613  	var db *txnDB
   614  	if db, err = store.getOrSetDB(id.DbID); err != nil {
   615  		return
   616  	}
   617  	return db.GetObject(id)
   618  }
   619  
   620  func (store *txnStore) CreateObject(dbId, tid uint64, is1PC bool) (obj handle.Object, err error) {
   621  	var db *txnDB
   622  	if db, err = store.getOrSetDB(dbId); err != nil {
   623  		return
   624  	}
   625  	return db.CreateObject(tid, is1PC)
   626  }
   627  
   628  func (store *txnStore) CreateNonAppendableObject(dbId, tid uint64, is1PC bool, opt *objectio.CreateObjOpt) (obj handle.Object, err error) {
   629  	var db *txnDB
   630  	if db, err = store.getOrSetDB(dbId); err != nil {
   631  		return
   632  	}
   633  	return db.CreateNonAppendableObject(tid, is1PC, opt)
   634  }
   635  
   636  func (store *txnStore) getOrSetDB(id uint64) (db *txnDB, err error) {
   637  	store.mu.RLock()
   638  	db = store.dbs[id]
   639  	store.mu.RUnlock()
   640  	if db != nil {
   641  		return
   642  	}
   643  	var entry *catalog.DBEntry
   644  	if entry, err = store.catalog.GetDatabaseByID(id); err != nil {
   645  		return
   646  	}
   647  	store.mu.Lock()
   648  	defer store.mu.Unlock()
   649  	db = store.dbs[id]
   650  	if db != nil {
   651  		return
   652  	}
   653  	db = newTxnDB(store, entry)
   654  	db.idx = len(store.dbs)
   655  	store.dbs[id] = db
   656  	return
   657  }
   658  func (store *txnStore) UpdateObjectStats(id *common.ID, stats *objectio.ObjectStats) error {
   659  	db, err := store.getOrSetDB(id.DbID)
   660  	if err != nil {
   661  		return err
   662  	}
   663  	db.UpdateObjectStats(id, stats)
   664  	return nil
   665  }
   666  
   667  func (store *txnStore) SoftDeleteObject(id *common.ID) (err error) {
   668  	var db *txnDB
   669  	if db, err = store.getOrSetDB(id.DbID); err != nil {
   670  		return
   671  	}
   672  	perfcounter.Update(store.ctx, func(counter *perfcounter.CounterSet) {
   673  		counter.TAE.Object.SoftDelete.Add(1)
   674  	})
   675  	return db.SoftDeleteObject(id)
   676  }
   677  
   678  func (store *txnStore) ApplyRollback() (err error) {
   679  	if store.cmdMgr.GetCSN() != 0 {
   680  		for _, db := range store.dbs {
   681  			if err = db.ApplyRollback(); err != nil {
   682  				break
   683  			}
   684  		}
   685  	}
   686  	store.CleanUp()
   687  	return
   688  }
   689  
   690  func (store *txnStore) WaitPrepared(ctx context.Context) (err error) {
   691  	for _, db := range store.dbs {
   692  		if err = db.WaitPrepared(); err != nil {
   693  			return
   694  		}
   695  	}
   696  	moprobe.WithRegion(ctx, moprobe.TxnStoreWaitWALFlush, func() {
   697  		for _, e := range store.logs {
   698  			if err = e.WaitDone(); err != nil {
   699  				break
   700  			}
   701  			e.Free()
   702  		}
   703  	})
   704  	store.wg.Wait()
   705  	return
   706  }
   707  
   708  func (store *txnStore) ApplyCommit() (err error) {
   709  	for _, db := range store.dbs {
   710  		if err = db.ApplyCommit(); err != nil {
   711  			break
   712  		}
   713  	}
   714  	store.CleanUp()
   715  	return
   716  }
   717  
   718  func (store *txnStore) Freeze() (err error) {
   719  	for _, db := range store.dbs {
   720  		if db.NeedRollback() {
   721  			if err = db.PrepareRollback(); err != nil {
   722  				return
   723  			}
   724  			delete(store.dbs, db.entry.GetID())
   725  		}
   726  		if err = db.Freeze(); err != nil {
   727  			return
   728  		}
   729  	}
   730  	return
   731  }
   732  
   733  func (store *txnStore) PrePrepare(ctx context.Context) (err error) {
   734  	for _, db := range store.dbs {
   735  		if err = db.PrePrepare(ctx); err != nil {
   736  			return
   737  		}
   738  	}
   739  	return
   740  }
   741  
   742  func (store *txnStore) PrepareCommit() (err error) {
   743  	if store.warChecker != nil {
   744  		if err = store.warChecker.checkAll(
   745  			store.txn.GetPrepareTS()); err != nil {
   746  			return err
   747  		}
   748  	}
   749  	for _, db := range store.dbs {
   750  		if err = db.PrepareCommit(); err != nil {
   751  			break
   752  		}
   753  	}
   754  
   755  	return
   756  }
   757  
   758  func (store *txnStore) PreApplyCommit() (err error) {
   759  	for _, db := range store.dbs {
   760  		if err = db.PreApplyCommit(); err != nil {
   761  			return
   762  		}
   763  	}
   764  	// logutil.Debugf("Txn-%X PrepareCommit Takes %s", store.txn.GetID(), time.Since(now))
   765  	return
   766  }
   767  
   768  func (store *txnStore) PrepareWAL() (err error) {
   769  	if err = store.CollectCmd(); err != nil {
   770  		return
   771  	}
   772  
   773  	if store.cmdMgr.GetCSN() == 0 {
   774  		return
   775  	}
   776  
   777  	// Apply the record from the command list.
   778  	// Split the commands by max message size.
   779  	for store.cmdMgr.cmd.MoreCmds() {
   780  		logEntry, err := store.cmdMgr.ApplyTxnRecord(store.txn)
   781  		if err != nil {
   782  			return err
   783  		}
   784  		if logEntry != nil {
   785  			store.logs = append(store.logs, logEntry)
   786  		}
   787  	}
   788  
   789  	t1 := time.Now()
   790  	for _, db := range store.dbs {
   791  		if err = db.Apply1PCCommit(); err != nil {
   792  			return
   793  		}
   794  	}
   795  	t2 := time.Now()
   796  	if t2.Sub(t1) > time.Millisecond*500 {
   797  		logutil.Warn(
   798  			"SLOW-LOG",
   799  			zap.String("txn", store.txn.String()),
   800  			zap.Duration("apply-1pc-commit-duration", t2.Sub(t1)),
   801  		)
   802  	}
   803  	return
   804  }
   805  
   806  func (store *txnStore) CollectCmd() (err error) {
   807  	dbs := make([]*txnDB, len(store.dbs))
   808  	for _, db := range store.dbs {
   809  		dbs[db.idx] = db
   810  	}
   811  	for _, db := range dbs {
   812  		if err = db.CollectCmd(store.cmdMgr); err != nil {
   813  			return
   814  		}
   815  	}
   816  	return
   817  }
   818  
   819  func (store *txnStore) AddTxnEntry(t txnif.TxnEntryType, entry txnif.TxnEntry) {
   820  	// TODO
   821  }
   822  
   823  func (store *txnStore) PrepareRollback() error {
   824  	var err error
   825  	for _, db := range store.dbs {
   826  		if err = db.PrepareRollback(); err != nil {
   827  			break
   828  		}
   829  	}
   830  
   831  	return err
   832  }
   833  
   834  func (store *txnStore) GetLSN() uint64 { return store.cmdMgr.lsn }
   835  
   836  func (store *txnStore) CleanUp() {
   837  	for _, db := range store.dbs {
   838  		db.CleanUp()
   839  	}
   840  }