Skip to content

Commit 85116ad

Browse files
Refine wait_timeout flag to be cut-over only
Signed-off-by: Tim Vaillancourt <[email protected]>
1 parent e6c198c commit 85116ad

File tree

5 files changed

+29
-14
lines changed

5 files changed

+29
-14
lines changed

go/base/context.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ type MigrationContext struct {
135135
CriticalLoadHibernateSeconds int64
136136
PostponeCutOverFlagFile string
137137
CutOverLockTimeoutSeconds int64
138+
CutOverIdleTimeoutSeconds int64
138139
CutOverExponentialBackoff bool
139140
ExponentialBackoffMaxInterval int64
140141
ForceNamedCutOverCommand bool
@@ -164,6 +165,7 @@ type MigrationContext struct {
164165
Hostname string
165166
AssumeMasterHostname string
166167
ApplierTimeZone string
168+
ApplierWaitTimeout int64
167169
TableEngine string
168170
RowsEstimate int64
169171
RowsDeltaEstimate int64
@@ -276,6 +278,7 @@ func NewMigrationContext() *MigrationContext {
276278
ApplierConnectionConfig: mysql.NewConnectionConfig(),
277279
MaxLagMillisecondsThrottleThreshold: 1500,
278280
CutOverLockTimeoutSeconds: 3,
281+
CutOverIdleTimeoutSeconds: 6,
279282
DMLBatchSize: 10,
280283
etaNanoseonds: ETAUnknown,
281284
maxLoad: NewLoadMap(),

go/cmd/gh-ost/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ func main() {
5151
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")
5252
flag.IntVar(&migrationContext.InspectorConnectionConfig.Key.Port, "port", 3306, "MySQL port (preferably a replica, not the master)")
5353
flag.Float64Var(&migrationContext.InspectorConnectionConfig.Timeout, "mysql-timeout", 0.0, "Connect, read and write timeout for MySQL")
54-
flag.Float64Var(&migrationContext.InspectorConnectionConfig.WaitTimeout, "mysql-wait-timeout", 0.0, "wait_timeout for MySQL sessions")
5554
flag.StringVar(&migrationContext.CliUser, "user", "", "MySQL user")
5655
flag.StringVar(&migrationContext.CliPassword, "password", "", "MySQL password")
5756
flag.StringVar(&migrationContext.CliMasterUser, "master-user", "", "MySQL user on master, if different from that on replica. Requires --assume-master-host")
@@ -109,6 +108,7 @@ func main() {
109108
dmlBatchSize := flag.Int64("dml-batch-size", 10, "batch size for DML events to apply in a single transaction (range 1-100)")
110109
defaultRetries := flag.Int64("default-retries", 60, "Default number of retries for various operations before panicking")
111110
cutOverLockTimeoutSeconds := flag.Int64("cut-over-lock-timeout-seconds", 3, "Max number of seconds to hold locks on tables while attempting to cut-over (retry attempted when lock exceeds timeout)")
111+
flag.Int64Var(&migrationContext.CutOverIdleTimeoutSeconds, "cut-over-idle-timeout-seconds", *cutOverLockTimeoutSeconds*2, "the idle timeout in seconds for the cut-over operation. The MySQL session performing the cut-over uses this as a wait_timeout.")
112112
niceRatio := flag.Float64("nice-ratio", 0, "force being 'nice', imply sleep time per chunk time; range: [0.0..100.0]. Example values: 0 is aggressive. 1: for every 1ms spent copying rows, sleep additional 1ms (effectively doubling runtime); 0.7: for every 10ms spend in a rowcopy chunk, spend 7ms sleeping immediately after")
113113

114114
maxLagMillis := flag.Int64("max-lag-millis", 1500, "replication lag at which to throttle operation")

go/logic/applier.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (this *Applier) InitDBConnections() (err error) {
8989
return err
9090
}
9191
this.migrationContext.ApplierMySQLVersion = version
92-
if err := this.validateAndReadTimeZone(); err != nil {
92+
if err := this.validateAndReadGlobalVariables(); err != nil {
9393
return err
9494
}
9595
if !this.migrationContext.AliyunRDS && !this.migrationContext.GoogleCloudPlatform && !this.migrationContext.AzureMySQL {
@@ -106,10 +106,13 @@ func (this *Applier) InitDBConnections() (err error) {
106106
return nil
107107
}
108108

109-
// validateAndReadTimeZone potentially reads server time-zone
110-
func (this *Applier) validateAndReadTimeZone() error {
111-
query := `select /* gh-ost */ @@global.time_zone`
112-
if err := this.db.QueryRow(query).Scan(&this.migrationContext.ApplierTimeZone); err != nil {
109+
// validateAndReadGlobalVariables potentially reads server global variables, such as the time_zone and wait_timeout.
110+
func (this *Applier) validateAndReadGlobalVariables() error {
111+
query := `select /* gh-ost */ @@global.time_zone, @@global.wait_timeout`
112+
if err := this.db.QueryRow(query).Scan(
113+
&this.migrationContext.ApplierTimeZone,
114+
&this.migrationContext.ApplierWaitTimeout,
115+
); err != nil {
113116
return err
114117
}
115118

@@ -974,6 +977,22 @@ func (this *Applier) AtomicCutOverMagicLock(sessionIdChan chan int64, tableLocke
974977
return err
975978
}
976979

980+
this.migrationContext.Log.Infof("Setting cut-over idle timeout as %d seconds", this.migrationContext.CutOverIdleTimeoutSeconds)
981+
query = fmt.Sprintf(`set /* gh-ost */ session wait_timeout:=%d`, this.migrationContext.CutOverIdleTimeoutSeconds)
982+
if _, err := tx.Exec(query); err != nil {
983+
tableLocked <- err
984+
return err
985+
}
986+
defer func() {
987+
this.migrationContext.Log.Infof("Restoring applier idle timeout as %d seconds", this.migrationContext.ApplierWaitTimeout)
988+
query = fmt.Sprintf(`set /* gh-ost */ session wait_timeout:=%d`, this.migrationContext.ApplierWaitTimeout)
989+
if _, err := sqlutils.ExecNoPrepare(this.db, query); err != nil {
990+
this.migrationContext.Log.Errorf("Failed to restore applier wait_timeout to %d seconds: %v",
991+
this.migrationContext.ApplierWaitTimeout, err,
992+
)
993+
}
994+
}()
995+
977996
if err := this.CreateAtomicCutOverSentryTable(); err != nil {
978997
tableLocked <- err
979998
return err

go/mysql/connection.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ type ConnectionConfig struct {
3131
Timeout float64
3232
TransactionIsolation string
3333
Charset string
34-
WaitTimeout float64
3534
}
3635

3736
func NewConnectionConfig() *ConnectionConfig {
@@ -52,7 +51,6 @@ func (this *ConnectionConfig) DuplicateCredentials(key InstanceKey) *ConnectionC
5251
Timeout: this.Timeout,
5352
TransactionIsolation: this.TransactionIsolation,
5453
Charset: this.Charset,
55-
WaitTimeout: this.WaitTimeout,
5654
}
5755
config.ImpliedKey = &config.Key
5856
return config
@@ -141,9 +139,6 @@ func (this *ConnectionConfig) GetDBUri(databaseName string) string {
141139
fmt.Sprintf("readTimeout=%fs", this.Timeout),
142140
fmt.Sprintf("writeTimeout=%fs", this.Timeout),
143141
}
144-
if this.WaitTimeout > 0 {
145-
connectionParams = append(connectionParams, fmt.Sprintf("wait_timeout=%fs", this.WaitTimeout))
146-
}
147142

148143
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s", this.User, this.Password, hostname, this.Key.Port, databaseName, strings.Join(connectionParams, "&"))
149144
}

go/mysql/connection_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ func TestGetDBUri(t *testing.T) {
8282
c.User = "gromit"
8383
c.Password = "penguin"
8484
c.Timeout = 1.2345
85-
c.WaitTimeout = 0 // should be ignored
8685
c.TransactionIsolation = transactionIsolation
8786
c.Charset = "utf8mb4,utf8,latin1"
8887

@@ -96,11 +95,10 @@ func TestGetDBUriWithTLSSetup(t *testing.T) {
9695
c.User = "gromit"
9796
c.Password = "penguin"
9897
c.Timeout = 1.2345
99-
c.WaitTimeout = 60
10098
c.tlsConfig = &tls.Config{}
10199
c.TransactionIsolation = transactionIsolation
102100
c.Charset = "utf8mb4_general_ci,utf8_general_ci,latin1"
103101

104102
uri := c.GetDBUri("test")
105-
test.S(t).ExpectEquals(uri, `gromit:penguin@tcp(myhost:3306)/test?autocommit=true&interpolateParams=true&charset=utf8mb4_general_ci,utf8_general_ci,latin1&tls=ghost&transaction_isolation="REPEATABLE-READ"&timeout=1.234500s&readTimeout=1.234500s&writeTimeout=1.234500s&wait_timeout=60.000000s`)
103+
test.S(t).ExpectEquals(uri, `gromit:penguin@tcp(myhost:3306)/test?autocommit=true&interpolateParams=true&charset=utf8mb4_general_ci,utf8_general_ci,latin1&tls=ghost&transaction_isolation="REPEATABLE-READ"&timeout=1.234500s&readTimeout=1.234500s&writeTimeout=1.234500s`)
106104
}

0 commit comments

Comments
 (0)