From b8c7e046a1def10afc962b4213949a9ad74c8f95 Mon Sep 17 00:00:00 2001 From: Shlomi Noach Date: Fri, 10 Jun 2016 11:15:11 +0200 Subject: [PATCH] test-on-replica to invoke cut-over swap --- build.sh | 2 +- go/base/context.go | 6 +++--- go/logic/applier.go | 25 +++++++++++++++++++++++++ go/logic/migrator.go | 17 ++++++++++++++--- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/build.sh b/build.sh index c18f3e8..7d0b748 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/bash # # -RELEASE_VERSION="0.8.8" +RELEASE_VERSION="0.8.9" buildpath=/tmp/gh-ost target=gh-ost diff --git a/go/base/context.go b/go/base/context.go index ba0e025..ae3bade 100644 --- a/go/base/context.go +++ b/go/base/context.go @@ -31,9 +31,9 @@ const ( type CutOver int const ( - CutOverTwoStep CutOver = 1 - CutOverVoluntaryLock - CutOverUdfWait + CutOverTwoStep CutOver = iota + CutOverVoluntaryLock = iota + CutOverUdfWait = iota ) const ( diff --git a/go/logic/applier.go b/go/logic/applier.go index dcf2539..b55662e 100644 --- a/go/logic/applier.go +++ b/go/logic/applier.go @@ -536,6 +536,31 @@ func (this *Applier) SwapTablesAtomic(sessionIdChan chan int64) error { return nil } +func (this *Applier) RenameTablesRollback() (renameError error) { + + query := fmt.Sprintf(`rename /* gh-ost */ table %s.%s to %s.%s`, + sql.EscapeName(this.migrationContext.DatabaseName), + sql.EscapeName(this.migrationContext.OriginalTableName), + sql.EscapeName(this.migrationContext.DatabaseName), + sql.EscapeName(this.migrationContext.GetGhostTableName()), + ) + log.Infof("Renaming back to ghost table") + if _, err := sqlutils.ExecNoPrepare(this.db, query); err != nil { + renameError = err + } + query = fmt.Sprintf(`rename /* gh-ost */ table %s.%s to %s.%s`, + sql.EscapeName(this.migrationContext.DatabaseName), + sql.EscapeName(this.migrationContext.GetOldTableName()), + sql.EscapeName(this.migrationContext.DatabaseName), + sql.EscapeName(this.migrationContext.OriginalTableName), + ) + log.Infof("Renaming back to original table") + if _, err := sqlutils.ExecNoPrepare(this.db, query); err != nil { + renameError = err + } + return log.Errore(renameError) +} + // StopSlaveIOThread is applicable with --test-on-replica; it stops the IO thread, duh. // We need to keep the SQL thread active so as to complete processing received events, // and have them written to the binary log, so that we can then read them via streamer diff --git a/go/logic/migrator.go b/go/logic/migrator.go index 86169c3..5dda2fa 100644 --- a/go/logic/migrator.go +++ b/go/logic/migrator.go @@ -389,14 +389,25 @@ func (this *Migrator) stopWritesAndCompleteMigration() (err error) { ) if this.migrationContext.TestOnReplica { - return this.stopWritesAndCompleteMigrationOnReplica() + // return this.stopWritesAndCompleteMigrationOnReplica() + + // With `--test-on-replica` we stop replication thread, and then proceed to use + // the same cut-over phase as the master would use. That means we take locks + // and swap the tables. + // The difference is that we will later swap the tables back. + log.Debugf("testing on replica. Stopping replication IO thread") + if err := this.retryOperation(this.applier.StopSlaveNicely); err != nil { + return err + } + // We're merly testing, we don't want to keep this state. Rollback the renames as possible + defer this.applier.RenameTablesRollback() } - // Running on master + if this.migrationContext.CutOverType == base.CutOverTwoStep { return this.stopWritesAndCompleteMigrationOnMasterQuickAndBumpy() } - { + if this.migrationContext.CutOverType == base.CutOverVoluntaryLock { // Lock-based solution: we use low timeout and multiple attempts. But for // each failed attempt, we throttle until replication lag is back to normal if err := this.retryOperation(