From d5ffd35aa4e32fffa80c754fffd3028df197f578 Mon Sep 17 00:00:00 2001
From: jiangxinmeng1 <51114574+jiangxinmeng1@users.noreply.github.com>
Date: Fri, 19 Aug 2022 14:17:18 +0800
Subject: [PATCH] fix txnstore data race (#4579)

fix data race in txnstore.getOrSetDB. add dbsMu

Approved by: @XuPeng-SH
---
 pkg/vm/engine/tae/txn/txnimpl/store.go | 27 ++++++++++++++-------
 pkg/vm/engine/tae/txn/txnimpl/txndb.go | 33 +++++++++++++++++---------
 2 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/pkg/vm/engine/tae/txn/txnimpl/store.go b/pkg/vm/engine/tae/txn/txnimpl/store.go
index dde12d365..95d6da04d 100644
--- a/pkg/vm/engine/tae/txn/txnimpl/store.go
+++ b/pkg/vm/engine/tae/txn/txnimpl/store.go
@@ -15,6 +15,7 @@
 package txnimpl
 
 import (
+	"sync"
 	"sync/atomic"
 	"time"
 
@@ -34,6 +35,7 @@ import (
 type txnStore struct {
 	txnbase.NoopTxnStore
 	dbs         map[uint64]*txnDB
+	mu          sync.RWMutex
 	driver      wal.Driver
 	nodesMgr    base.INodeManager
 	txn         txnif.AsyncTxn
@@ -284,16 +286,25 @@ func (store *txnStore) CreateNonAppendableSegment(dbId, tid uint64) (seg handle.
 }
 
 func (store *txnStore) getOrSetDB(id uint64) (db *txnDB, err error) {
+	store.mu.RLock()
 	db = store.dbs[id]
-	if db == nil {
-		var entry *catalog.DBEntry
-		if entry, err = store.catalog.GetDatabaseByID(id); err != nil {
-			return
-		}
-		db = newTxnDB(store, entry)
-		db.idx = len(store.dbs)
-		store.dbs[id] = db
+	store.mu.RUnlock()
+	if db != nil {
+		return
+	}
+	var entry *catalog.DBEntry
+	if entry, err = store.catalog.GetDatabaseByID(id); err != nil {
+		return
+	}
+	store.mu.Lock()
+	defer store.mu.Unlock()
+	db = store.dbs[id]
+	if db != nil {
+		return
 	}
+	db = newTxnDB(store, entry)
+	db.idx = len(store.dbs)
+	store.dbs[id] = db
 	return
 }
 
diff --git a/pkg/vm/engine/tae/txn/txnimpl/txndb.go b/pkg/vm/engine/tae/txn/txnimpl/txndb.go
index e0b58e141..142aa60ea 100644
--- a/pkg/vm/engine/tae/txn/txnimpl/txndb.go
+++ b/pkg/vm/engine/tae/txn/txnimpl/txndb.go
@@ -15,6 +15,7 @@
 package txnimpl
 
 import (
+	"sync"
 	"time"
 
 	"github.com/matrixorigin/matrixone/pkg/logutil"
@@ -29,6 +30,7 @@ import (
 type txnDB struct {
 	store       *txnStore
 	tables      map[uint64]*txnTable
+	mu          sync.RWMutex
 	entry       *catalog.DBEntry
 	createEntry txnif.TxnEntry
 	dropEntry   txnif.TxnEntry
@@ -234,19 +236,28 @@ func (db *txnDB) CreateNonAppendableSegment(tid uint64) (seg handle.Segment, err
 }
 
 func (db *txnDB) getOrSetTable(id uint64) (table *txnTable, err error) {
+	db.mu.RLock()
 	table = db.tables[id]
-	if table == nil {
-		var entry *catalog.TableEntry
-		if entry, err = db.entry.GetTableEntryByID(id); err != nil {
-			return
-		}
-		if db.store.warChecker == nil {
-			db.store.warChecker = newWarChecker(db.store.txn, db.store.catalog)
-		}
-		table = newTxnTable(db.store, entry)
-		table.idx = len(db.tables)
-		db.tables[id] = table
+	db.mu.RUnlock()
+	if table != nil {
+		return
+	}
+	var entry *catalog.TableEntry
+	if entry, err = db.entry.GetTableEntryByID(id); err != nil {
+		return
+	}
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	table = db.tables[id]
+	if table != nil {
+		return
+	}
+	if db.store.warChecker == nil {
+		db.store.warChecker = newWarChecker(db.store.txn, db.store.catalog)
 	}
+	table = newTxnTable(db.store, entry)
+	table.idx = len(db.tables)
+	db.tables[id] = table
 	return
 }
 
-- 
GitLab