Skip to content

Commit 84bdfdb

Browse files
committed
Cache DB connection pools on the migrationContext where applicable
1 parent 5788ab5 commit 84bdfdb

8 files changed

Lines changed: 54 additions & 50 deletions

File tree

go/base/context.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ import (
1414
"sync/atomic"
1515
"time"
1616

17+
gosql "database/sql"
1718
"github.com/github/gh-ost/go/mysql"
1819
"github.com/github/gh-ost/go/sql"
1920

21+
"github.com/outbrain/golib/sqlutils"
22+
2023
"gopkg.in/gcfg.v1"
2124
gcfgscanner "gopkg.in/gcfg.v1/scanner"
2225
)
@@ -197,6 +200,9 @@ type MigrationContext struct {
197200
recentBinlogCoordinates mysql.BinlogCoordinates
198201

199202
CanStopStreaming func() bool
203+
204+
knownDBs map[string]*gosql.DB
205+
knownDBsMutex *sync.Mutex
200206
}
201207

202208
type ContextConfig struct {
@@ -230,6 +236,8 @@ func NewMigrationContext() *MigrationContext {
230236
pointOfInterestTimeMutex: &sync.Mutex{},
231237
ColumnRenameMap: make(map[string]string),
232238
PanicAbort: make(chan error),
239+
knownDBsMutex: &sync.Mutex{},
240+
knownDBs: make(map[string]*gosql.DB),
233241
}
234242
}
235243

@@ -242,6 +250,23 @@ func getSafeTableName(baseName string, suffix string) string {
242250
return fmt.Sprintf("_%s_%s", baseName[0:len(baseName)-extraCharacters], suffix)
243251
}
244252

253+
// GetDB returns a DB instance based on uri.
254+
// bool result indicates whether the DB was returned from cache; err
255+
func (this *MigrationContext) GetDB(mysql_uri string) (*gosql.DB, bool, error) {
256+
this.knownDBsMutex.Lock()
257+
defer this.knownDBsMutex.Unlock()
258+
259+
var exists bool
260+
if _, exists = this.knownDBs[mysql_uri]; !exists {
261+
if db, err := sqlutils.GetDB(mysql_uri); err == nil {
262+
this.knownDBs[mysql_uri] = db
263+
} else {
264+
return db, exists, err
265+
}
266+
}
267+
return this.knownDBs[mysql_uri], exists, nil
268+
}
269+
245270
// GetGhostTableName generates the name of ghost table, based on original table name
246271
// or a given table name
247272
func (this *MigrationContext) GetGhostTableName() string {

go/logic/applier.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ func NewApplier(migrationContext *base.MigrationContext) *Applier {
4747

4848
func (this *Applier) InitDBConnections() (err error) {
4949
applierUri := this.connectionConfig.GetDBUri(this.migrationContext.DatabaseName)
50-
if this.db, _, err = sqlutils.GetDB(applierUri); err != nil {
50+
if this.db, _, err = this.migrationContext.GetDB(applierUri); err != nil {
5151
return err
5252
}
5353
singletonApplierUri := fmt.Sprintf("%s?timeout=0", applierUri)
54-
if this.singletonDB, _, err = sqlutils.GetDB(singletonApplierUri); err != nil {
54+
if this.singletonDB, _, err = this.migrationContext.GetDB(singletonApplierUri); err != nil {
5555
return err
5656
}
5757
this.singletonDB.SetMaxOpenConns(1)

go/logic/inspect.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ const startSlavePostWaitMilliseconds = 500 * time.Millisecond
2626
// Inspector reads data from the read-MySQL-server (typically a replica, but can be the master)
2727
// It is used for gaining initial status and structure, and later also follow up on progress and changelog
2828
type Inspector struct {
29-
connectionConfig *mysql.ConnectionConfig
30-
db *gosql.DB
31-
migrationContext *base.MigrationContext
29+
connectionConfig *mysql.ConnectionConfig
30+
db *gosql.DB
31+
informationSchemaDb *gosql.DB
32+
migrationContext *base.MigrationContext
3233
}
3334

3435
func NewInspector(migrationContext *base.MigrationContext) *Inspector {
@@ -40,9 +41,15 @@ func NewInspector(migrationContext *base.MigrationContext) *Inspector {
4041

4142
func (this *Inspector) InitDBConnections() (err error) {
4243
inspectorUri := this.connectionConfig.GetDBUri(this.migrationContext.DatabaseName)
43-
if this.db, _, err = sqlutils.GetDB(inspectorUri); err != nil {
44+
if this.db, _, err = this.migrationContext.GetDB(inspectorUri); err != nil {
4445
return err
4546
}
47+
48+
informationSchemaUri := this.connectionConfig.GetDBUri("information_schema")
49+
if this.informationSchemaDb, _, err = this.migrationContext.GetDB(informationSchemaUri); err != nil {
50+
return err
51+
}
52+
4653
if err := this.validateConnection(); err != nil {
4754
return err
4855
}
@@ -755,12 +762,14 @@ func (this *Inspector) getMasterConnectionConfig() (applierConfig *mysql.Connect
755762

756763
func (this *Inspector) getReplicationLag() (replicationLag time.Duration, err error) {
757764
replicationLag, err = mysql.GetReplicationLag(
765+
this.informationSchemaDb,
758766
this.migrationContext.InspectorConnectionConfig,
759767
)
760768
return replicationLag, err
761769
}
762770

763771
func (this *Inspector) Teardown() {
764772
this.db.Close()
773+
this.informationSchemaDb.Close()
765774
return
766775
}

go/logic/migrator.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"github.com/github/gh-ost/go/sql"
2121

2222
"github.com/outbrain/golib/log"
23-
"github.com/outbrain/golib/sqlutils"
2423
)
2524

2625
type ChangelogState string
@@ -1248,6 +1247,4 @@ func (this *Migrator) teardown() {
12481247
log.Infof("Tearing down streamer")
12491248
this.eventsStreamer.Teardown()
12501249
}
1251-
1252-
sqlutils.ResetDBCache()
12531250
}

go/logic/streamer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (this *EventsStreamer) notifyListeners(binlogEvent *binlog.BinlogDMLEvent)
104104

105105
func (this *EventsStreamer) InitDBConnections() (err error) {
106106
EventsStreamerUri := this.connectionConfig.GetDBUri(this.migrationContext.DatabaseName)
107-
if this.db, _, err = sqlutils.GetDB(EventsStreamerUri); err != nil {
107+
if this.db, _, err = this.migrationContext.GetDB(EventsStreamerUri); err != nil {
108108
return err
109109
}
110110
if err := this.validateConnection(); err != nil {

go/logic/throttler.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/github/gh-ost/go/mysql"
1717
"github.com/github/gh-ost/go/sql"
1818
"github.com/outbrain/golib/log"
19-
"github.com/outbrain/golib/sqlutils"
2019
)
2120

2221
var (
@@ -140,7 +139,7 @@ func (this *Throttler) collectReplicationLag(firstThrottlingCollected chan<- boo
140139
// when running on replica, the heartbeat injection is also done on the replica.
141140
// This means we will always get a good heartbeat value.
142141
// When runnign on replica, we should instead check the `SHOW SLAVE STATUS` output.
143-
if lag, err := mysql.GetReplicationLag(this.inspector.connectionConfig); err != nil {
142+
if lag, err := mysql.GetReplicationLag(this.inspector.informationSchemaDb, this.inspector.connectionConfig); err != nil {
144143
return log.Errore(err)
145144
} else {
146145
atomic.StoreInt64(&this.migrationContext.CurrentLag, int64(lag))
@@ -182,7 +181,7 @@ func (this *Throttler) collectControlReplicasLag() {
182181
dbUri := connectionConfig.GetDBUri("information_schema")
183182

184183
var heartbeatValue string
185-
if db, _, err := sqlutils.GetDB(dbUri); err != nil {
184+
if db, _, err := this.migrationContext.GetDB(dbUri); err != nil {
186185
return lag, err
187186
} else if err = db.QueryRow(replicationLagQuery).Scan(&heartbeatValue); err != nil {
188187
return lag, err

go/mysql/utils.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,8 @@ func (this *ReplicationLagResult) HasLag() bool {
3535

3636
// GetReplicationLag returns replication lag for a given connection config; either by explicit query
3737
// or via SHOW SLAVE STATUS
38-
func GetReplicationLag(connectionConfig *ConnectionConfig) (replicationLag time.Duration, err error) {
39-
dbUri := connectionConfig.GetDBUri("information_schema")
40-
var db *gosql.DB
41-
if db, _, err = sqlutils.GetDB(dbUri); err != nil {
42-
return replicationLag, err
43-
}
44-
defer db.Close()
45-
46-
err = sqlutils.QueryRowsMap(db, `show slave status`, func(m sqlutils.RowMap) error {
38+
func GetReplicationLag(informationSchemaDb *gosql.DB, connectionConfig *ConnectionConfig) (replicationLag time.Duration, err error) {
39+
err = sqlutils.QueryRowsMap(informationSchemaDb, `show slave status`, func(m sqlutils.RowMap) error {
4740
slaveIORunning := m.GetString("Slave_IO_Running")
4841
slaveSQLRunning := m.GetString("Slave_SQL_Running")
4942
secondsBehindMaster := m.GetNullInt64("Seconds_Behind_Master")
@@ -59,7 +52,10 @@ func GetReplicationLag(connectionConfig *ConnectionConfig) (replicationLag time.
5952

6053
func GetMasterKeyFromSlaveStatus(connectionConfig *ConnectionConfig) (masterKey *InstanceKey, err error) {
6154
currentUri := connectionConfig.GetDBUri("information_schema")
62-
db, _, err := sqlutils.GetDB(currentUri)
55+
// This function is only called once, okay to not have a cached connection pool
56+
db, err := sqlutils.GetDB(currentUri)
57+
defer db.Close()
58+
6359
if err != nil {
6460
return nil, err
6561
}

vendor/github.com/outbrain/golib/sqlutils/sqlutils.go

Lines changed: 5 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)