Skip to content

Commit a01e363

Browse files
author
Shlomi Noach
authored
Merge branch 'master' into go-mysql-ignore-pass
2 parents fcda146 + f0c3028 commit a01e363

16 files changed

Lines changed: 220 additions & 88 deletions

File tree

go/base/context.go

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

17+
"github.com/satori/go.uuid"
18+
1719
"github.com/github/gh-ost/go/mysql"
1820
"github.com/github/gh-ost/go/sql"
1921

@@ -71,6 +73,8 @@ func NewThrottleCheckResult(throttle bool, reason string, reasonHint ThrottleRea
7173
// MigrationContext has the general, global state of migration. It is used by
7274
// all components throughout the migration process.
7375
type MigrationContext struct {
76+
Uuid string
77+
7478
DatabaseName string
7579
OriginalTableName string
7680
AlterStatement string
@@ -195,8 +199,6 @@ type MigrationContext struct {
195199
ForceTmpTableName string
196200

197201
recentBinlogCoordinates mysql.BinlogCoordinates
198-
199-
CanStopStreaming func() bool
200202
}
201203

202204
type ContextConfig struct {
@@ -212,14 +214,9 @@ type ContextConfig struct {
212214
}
213215
}
214216

215-
var context *MigrationContext
216-
217-
func init() {
218-
context = newMigrationContext()
219-
}
220-
221-
func newMigrationContext() *MigrationContext {
217+
func NewMigrationContext() *MigrationContext {
222218
return &MigrationContext{
219+
Uuid: uuid.NewV4().String(),
223220
defaultNumRetries: 60,
224221
ChunkSize: 1000,
225222
InspectorConnectionConfig: mysql.NewConnectionConfig(),
@@ -239,11 +236,6 @@ func newMigrationContext() *MigrationContext {
239236
}
240237
}
241238

242-
// GetMigrationContext
243-
func GetMigrationContext() *MigrationContext {
244-
return context
245-
}
246-
247239
func getSafeTableName(baseName string, suffix string) string {
248240
name := fmt.Sprintf("_%s_%s", baseName, suffix)
249241
if len(name) <= mysql.MaxTableNameLength {

go/base/context_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,27 @@ func init() {
1919

2020
func TestGetTableNames(t *testing.T) {
2121
{
22-
context = newMigrationContext()
22+
context := NewMigrationContext()
2323
context.OriginalTableName = "some_table"
2424
test.S(t).ExpectEquals(context.GetOldTableName(), "_some_table_del")
2525
test.S(t).ExpectEquals(context.GetGhostTableName(), "_some_table_gho")
2626
test.S(t).ExpectEquals(context.GetChangelogTableName(), "_some_table_ghc")
2727
}
2828
{
29-
context = newMigrationContext()
29+
context := NewMigrationContext()
3030
context.OriginalTableName = "a123456789012345678901234567890123456789012345678901234567890"
3131
test.S(t).ExpectEquals(context.GetOldTableName(), "_a1234567890123456789012345678901234567890123456789012345678_del")
3232
test.S(t).ExpectEquals(context.GetGhostTableName(), "_a1234567890123456789012345678901234567890123456789012345678_gho")
3333
test.S(t).ExpectEquals(context.GetChangelogTableName(), "_a1234567890123456789012345678901234567890123456789012345678_ghc")
3434
}
3535
{
36-
context = newMigrationContext()
36+
context := NewMigrationContext()
3737
context.OriginalTableName = "a123456789012345678901234567890123456789012345678901234567890123"
3838
oldTableName := context.GetOldTableName()
3939
test.S(t).ExpectEquals(oldTableName, "_a1234567890123456789012345678901234567890123456789012345678_del")
4040
}
4141
{
42-
context = newMigrationContext()
42+
context := NewMigrationContext()
4343
context.OriginalTableName = "a123456789012345678901234567890123456789012345678901234567890123"
4444
context.TimestampOldTable = true
4545
longForm := "Jan 2, 2006 at 3:04pm (MST)"
@@ -48,7 +48,7 @@ func TestGetTableNames(t *testing.T) {
4848
test.S(t).ExpectEquals(oldTableName, "_a1234567890123456789012345678901234567890123_20130203195400_del")
4949
}
5050
{
51-
context = newMigrationContext()
51+
context := NewMigrationContext()
5252
context.OriginalTableName = "foo_bar_baz"
5353
context.ForceTmpTableName = "tmp"
5454
test.S(t).ExpectEquals(context.GetOldTableName(), "_tmp_del")

go/binlog/gomysql_reader.go

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,26 @@ type GoMySQLReader struct {
2626
currentCoordinates mysql.BinlogCoordinates
2727
currentCoordinatesMutex *sync.Mutex
2828
LastAppliedRowsEventHint mysql.BinlogCoordinates
29-
MigrationContext *base.MigrationContext
3029
}
3130

32-
func NewGoMySQLReader(connectionConfig *mysql.ConnectionConfig) (binlogReader *GoMySQLReader, err error) {
31+
func NewGoMySQLReader(migrationContext *base.MigrationContext) (binlogReader *GoMySQLReader, err error) {
3332
binlogReader = &GoMySQLReader{
34-
connectionConfig: connectionConfig,
33+
connectionConfig: migrationContext.InspectorConnectionConfig,
3534
currentCoordinates: mysql.BinlogCoordinates{},
3635
currentCoordinatesMutex: &sync.Mutex{},
3736
binlogSyncer: nil,
3837
binlogStreamer: nil,
39-
MigrationContext: base.GetMigrationContext(),
4038
}
4139

42-
serverId := uint32(binlogReader.MigrationContext.ReplicaServerId)
40+
serverId := uint32(migrationContext.ReplicaServerId)
4341

4442
binlogSyncerConfig := replication.BinlogSyncerConfig{
4543
ServerID: serverId,
4644
Flavor: "mysql",
47-
Host: connectionConfig.Key.Hostname,
48-
Port: uint16(connectionConfig.Key.Port),
49-
User: connectionConfig.User,
50-
Password: connectionConfig.Password,
45+
Host: binlogReader.connectionConfig.Key.Hostname,
46+
Port: uint16(binlogReader.connectionConfig.Key.Port),
47+
User: binlogReader.connectionConfig.User,
48+
Password: binlogReader.connectionConfig.Password,
5149
}
5250
binlogReader.binlogSyncer = replication.NewBinlogSyncer(binlogSyncerConfig)
5351

@@ -160,10 +158,6 @@ func (this *GoMySQLReader) StreamEvents(canStopStreaming func() bool, entriesCha
160158
}
161159

162160
func (this *GoMySQLReader) Close() error {
163-
// Historically there was a:
164-
// this.binlogSyncer.Close()
165-
// here. A new go-mysql version closes the binlog syncer connection independently.
166-
// I will go against the sacred rules of comments and just leave this here.
167-
// This is the year 2017. Let's see what year these comments get deleted.
161+
this.binlogSyncer.Close()
168162
return nil
169163
}

go/cmd/gh-ost/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func acceptSignals(migrationContext *base.MigrationContext) {
4343

4444
// main is the application's entry point. It will either spawn a CLI or HTTP interfaces.
4545
func main() {
46-
migrationContext := base.GetMigrationContext()
46+
migrationContext := base.NewMigrationContext()
4747

4848
flag.StringVar(&migrationContext.InspectorConnectionConfig.Key.Hostname, "host", "127.0.0.1", "MySQL hostname (preferably a replica, not the master)")
4949
flag.StringVar(&migrationContext.AssumeMasterHostname, "assume-master-host", "", "(optional) explicitly tell gh-ost the identity of the master. Format: some.host.com[:port] This is useful in master-master setups where you wish to pick an explicit master, or in a tungsten-replicator where gh-ost is unable to determine the master")
@@ -242,7 +242,7 @@ func main() {
242242
log.Infof("starting gh-ost %+v", AppVersion)
243243
acceptSignals(migrationContext)
244244

245-
migrator := logic.NewMigrator()
245+
migrator := logic.NewMigrator(migrationContext)
246246
err := migrator.Migrate()
247247
if err != nil {
248248
migrator.ExecOnFailureHook()

go/logic/applier.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,29 @@ func newDmlBuildResultError(err error) *dmlBuildResult {
5252
// Applier is the one to actually write row data and apply binlog events onto the ghost table.
5353
// It is where the ghost & changelog tables get created. It is where the cut-over phase happens.
5454
type Applier struct {
55-
connectionConfig *mysql.ConnectionConfig
56-
db *gosql.DB
57-
singletonDB *gosql.DB
58-
migrationContext *base.MigrationContext
55+
connectionConfig *mysql.ConnectionConfig
56+
db *gosql.DB
57+
singletonDB *gosql.DB
58+
migrationContext *base.MigrationContext
59+
finishedMigrating int64
5960
}
6061

61-
func NewApplier() *Applier {
62+
func NewApplier(migrationContext *base.MigrationContext) *Applier {
6263
return &Applier{
63-
connectionConfig: base.GetMigrationContext().ApplierConnectionConfig,
64-
migrationContext: base.GetMigrationContext(),
64+
connectionConfig: migrationContext.ApplierConnectionConfig,
65+
migrationContext: migrationContext,
66+
finishedMigrating: 0,
6567
}
6668
}
6769

6870
func (this *Applier) InitDBConnections() (err error) {
71+
6972
applierUri := this.connectionConfig.GetDBUri(this.migrationContext.DatabaseName)
70-
if this.db, _, err = sqlutils.GetDB(applierUri); err != nil {
73+
if this.db, _, err = mysql.GetDB(this.migrationContext.Uuid, applierUri); err != nil {
7174
return err
7275
}
7376
singletonApplierUri := fmt.Sprintf("%s?timeout=0", applierUri)
74-
if this.singletonDB, _, err = sqlutils.GetDB(singletonApplierUri); err != nil {
77+
if this.singletonDB, _, err = mysql.GetDB(this.migrationContext.Uuid, singletonApplierUri); err != nil {
7578
return err
7679
}
7780
this.singletonDB.SetMaxOpenConns(1)
@@ -320,6 +323,9 @@ func (this *Applier) InitiateHeartbeat() {
320323

321324
heartbeatTick := time.Tick(time.Duration(this.migrationContext.HeartbeatIntervalMilliseconds) * time.Millisecond)
322325
for range heartbeatTick {
326+
if atomic.LoadInt64(&this.finishedMigrating) > 0 {
327+
return
328+
}
323329
// Generally speaking, we would issue a goroutine, but I'd actually rather
324330
// have this block the loop rather than spam the master in the event something
325331
// goes wrong
@@ -1074,3 +1080,10 @@ func (this *Applier) ApplyDMLEventQueries(dmlEvents [](*binlog.BinlogDMLEvent))
10741080
log.Debugf("ApplyDMLEventQueries() applied %d events in one transaction", len(dmlEvents))
10751081
return nil
10761082
}
1083+
1084+
func (this *Applier) Teardown() {
1085+
log.Debugf("Tearing down...")
1086+
this.db.Close()
1087+
this.singletonDB.Close()
1088+
atomic.StoreInt64(&this.finishedMigrating, 1)
1089+
}

go/logic/hooks.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ type HooksExecutor struct {
3737
migrationContext *base.MigrationContext
3838
}
3939

40-
func NewHooksExecutor() *HooksExecutor {
40+
func NewHooksExecutor(migrationContext *base.MigrationContext) *HooksExecutor {
4141
return &HooksExecutor{
42-
migrationContext: base.GetMigrationContext(),
42+
migrationContext: migrationContext,
4343
}
4444
}
4545

go/logic/inspect.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,30 @@ 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

34-
func NewInspector() *Inspector {
35+
func NewInspector(migrationContext *base.MigrationContext) *Inspector {
3536
return &Inspector{
36-
connectionConfig: base.GetMigrationContext().InspectorConnectionConfig,
37-
migrationContext: base.GetMigrationContext(),
37+
connectionConfig: migrationContext.InspectorConnectionConfig,
38+
migrationContext: migrationContext,
3839
}
3940
}
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 = mysql.GetDB(this.migrationContext.Uuid, inspectorUri); err != nil {
4445
return err
4546
}
47+
48+
informationSchemaUri := this.connectionConfig.GetDBUri("information_schema")
49+
if this.informationSchemaDb, _, err = mysql.GetDB(this.migrationContext.Uuid, informationSchemaUri); err != nil {
50+
return err
51+
}
52+
4653
if err := this.validateConnection(); err != nil {
4754
return err
4855
}
@@ -749,7 +756,14 @@ func (this *Inspector) getMasterConnectionConfig() (applierConfig *mysql.Connect
749756

750757
func (this *Inspector) getReplicationLag() (replicationLag time.Duration, err error) {
751758
replicationLag, err = mysql.GetReplicationLag(
759+
this.informationSchemaDb,
752760
this.migrationContext.InspectorConnectionConfig,
753761
)
754762
return replicationLag, err
755763
}
764+
765+
func (this *Inspector) Teardown() {
766+
this.db.Close()
767+
this.informationSchemaDb.Close()
768+
return
769+
}

0 commit comments

Comments
 (0)