test-on-replica to invoke cut-over swap

This commit is contained in:
Shlomi Noach 2016-06-10 11:15:11 +02:00
parent 29aead6212
commit b8c7e046a1
4 changed files with 43 additions and 7 deletions

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# #
# #
RELEASE_VERSION="0.8.8" RELEASE_VERSION="0.8.9"
buildpath=/tmp/gh-ost buildpath=/tmp/gh-ost
target=gh-ost target=gh-ost

View File

@ -31,9 +31,9 @@ const (
type CutOver int type CutOver int
const ( const (
CutOverTwoStep CutOver = 1 CutOverTwoStep CutOver = iota
CutOverVoluntaryLock CutOverVoluntaryLock = iota
CutOverUdfWait CutOverUdfWait = iota
) )
const ( const (

View File

@ -536,6 +536,31 @@ func (this *Applier) SwapTablesAtomic(sessionIdChan chan int64) error {
return nil 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. // 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, // 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 // and have them written to the binary log, so that we can then read them via streamer

View File

@ -389,14 +389,25 @@ func (this *Migrator) stopWritesAndCompleteMigration() (err error) {
) )
if this.migrationContext.TestOnReplica { 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 { if this.migrationContext.CutOverType == base.CutOverTwoStep {
return this.stopWritesAndCompleteMigrationOnMasterQuickAndBumpy() return this.stopWritesAndCompleteMigrationOnMasterQuickAndBumpy()
} }
{ if this.migrationContext.CutOverType == base.CutOverVoluntaryLock {
// Lock-based solution: we use low timeout and multiple attempts. But for // Lock-based solution: we use low timeout and multiple attempts. But for
// each failed attempt, we throttle until replication lag is back to normal // each failed attempt, we throttle until replication lag is back to normal
if err := this.retryOperation( if err := this.retryOperation(