Skip to content

Commit 88f2af8

Browse files
author
Shlomi Noach
committed
support for --assume-master-host, master-master/tungsten
1 parent 96f108d commit 88f2af8

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

doc/cheatsheet.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,30 @@ password=123456
124124
```
125125

126126
You may then remove `--user=gh-ost --password=123456` and specify `--conf=/path/to/config/file.cnf`
127+
128+
129+
### Special configurations
130+
131+
#### Master-master
132+
133+
Master-master setups are supported, but at this time only active-passive. An active-active setup, where both masters write to the migrated table, is not supported at this stage. `gh-ost` requires you to acknowledge master-master via:
134+
135+
```
136+
gh-ost --allow-master-master
137+
```
138+
139+
`gh-ost` will pick one of the masters to work on. You may additionally force `gh-ost` to pick a particular master of your choice:
140+
141+
```
142+
gh-ost --allow-master-master --assume-master-host=a.specific.master.com
143+
```
144+
145+
#### Tungsten
146+
147+
Topologies using _tungsten replicator_ are peculiar in that the participating servers are not actually aware they are replicating. The _tungsten replicator_ looks just like another app issuing queries on those hosts. `gh-ost` is unable to identify that a server participates in a _tungsten_ topology.
148+
149+
If you choose to migrate directly on master (see above), there's nothing special you need to do. If you choose to migrate via replica, then you must supply the identity of the master, and indicate this is a tungsten setup, as follows:
150+
151+
```
152+
gh-ost --tungsten --assume-master-host=the.topology.master.com
153+
```

doc/command-line-flags.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ When your migration issues a column rename (`change column old_name new_name ...
1616

1717
If you think `gh-ost` is mistaken and that there's actually no _rename_ involved, you may pass `--skip-renamed-columns` instead. This will cause `gh-ost` to disassociate the column values; data will not be copied between those columns.
1818

19+
### assume-master-host
20+
21+
`gh-ost` infers the identity of the master server by crawling up the replication topology. You may explicitly tell `gh-ost` the identity of the master host via `--assume-master-host=the.master.com`. This is useful in:
22+
23+
- master-master topologies (together with `--allow-master-master`), where `gh-ost` can arbitrarily pick one of the co-master and you prefer that it picks a specific one
24+
- _tungsten replicator_ topologies (together with `--tungsten`), where `gh-ost` is unable to crawl and detect the master
25+
1926
### assume-rbr
2027

2128
If you happen to _know_ your servers use RBR (Row Based Replication, i.e. `binlog_format=ROW`), you may specify `--assume-rbr`. This skips a verification step where `gh-ost` would issue a `STOP SLAVE; START SLAVE`.

go/base/context.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ type MigrationContext struct {
6969
NullableUniqueKeyAllowed bool
7070
ApproveRenamedColumns bool
7171
SkipRenamedColumns bool
72+
IsTungsten bool
7273

7374
config ContextConfig
7475
configMutex *sync.Mutex
@@ -109,7 +110,7 @@ type MigrationContext struct {
109110
CutOverType CutOver
110111

111112
Hostname string
112-
OverrideApplierHostname string
113+
AssumeMasterHostname string
113114
TableEngine string
114115
RowsEstimate int64
115116
RowsDeltaEstimate int64

go/cmd/gh-ost/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func main() {
4444
migrationContext := base.GetMigrationContext()
4545

4646
flag.StringVar(&migrationContext.InspectorConnectionConfig.Key.Hostname, "host", "127.0.0.1", "MySQL hostname (preferably a replica, not the master)")
47-
flag.StringVar(&migrationContext.OverrideApplierHostname, "override-applier-host", "", "(with -allow-master-master), optionally specify which host should have changes applied to it")
47+
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 unabel to determine the master")
4848
flag.IntVar(&migrationContext.InspectorConnectionConfig.Key.Port, "port", 3306, "MySQL port (preferably a replica, not the master)")
4949
flag.StringVar(&migrationContext.CliUser, "user", "", "MySQL user")
5050
flag.StringVar(&migrationContext.CliPassword, "password", "", "MySQL password")
@@ -60,6 +60,7 @@ func main() {
6060
flag.BoolVar(&migrationContext.NullableUniqueKeyAllowed, "allow-nullable-unique-key", false, "allow gh-ost to migrate based on a unique key with nullable columns. As long as no NULL values exist, this should be OK. If NULL values exist in chosen key, data may be corrupted. Use at your own risk!")
6161
flag.BoolVar(&migrationContext.ApproveRenamedColumns, "approve-renamed-columns", false, "in case your `ALTER` statement renames columns, gh-ost will note that and offer its interpretation of the rename. By default gh-ost does not proceed to execute. This flag approves that gh-ost's interpretation si correct")
6262
flag.BoolVar(&migrationContext.SkipRenamedColumns, "skip-renamed-columns", false, "in case your `ALTER` statement renames columns, gh-ost will note that and offer its interpretation of the rename. By default gh-ost does not proceed to execute. This flag tells gh-ost to skip the renamed columns, i.e. to treat what gh-ost thinks are renamed columns as unrelated columns. NOTE: you may lose column data")
63+
flag.BoolVar(&migrationContext.IsTungsten, "tungsten", false, "explicitly let gh-ost know that you are running on a tungsten-replication based topology (you are likely to also provide --assume-master-host)")
6364

6465
executeFlag := flag.Bool("execute", false, "actually execute the alter & migrate the table. Default is noop: do some tests and exit")
6566
flag.BoolVar(&migrationContext.TestOnReplica, "test-on-replica", false, "Have the migration run on a replica, not on the master. At the end of migration replication is stopped, and tables are swapped and immediately swap-revert. Replication remains stopped and you can compare the two tables for building trust")
@@ -162,8 +163,8 @@ func main() {
162163
}
163164
log.Warning("--test-on-replica-skip-replica-stop enabled. We will not stop replication before cut-over. Ensure you have a plugin that does this.")
164165
}
165-
if migrationContext.OverrideApplierHostname != "" && !migrationContext.AllowedMasterMaster {
166-
log.Fatalf("--override-applier-host is only for use with --allow-master-amster")
166+
if migrationContext.AssumeMasterHostname != "" && !migrationContext.AllowedMasterMaster && !migrationContext.IsTungsten {
167+
log.Fatalf("--assume-master-host requires either --allow-master-master or --tungsten")
167168
}
168169

169170
switch *cutOver {

go/logic/migrator.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/github/gh-ost/go/base"
2222
"github.com/github/gh-ost/go/binlog"
23+
"github.com/github/gh-ost/go/mysql"
2324
"github.com/github/gh-ost/go/sql"
2425

2526
"github.com/outbrain/golib/log"
@@ -761,8 +762,12 @@ func (this *Migrator) initiateInspector() (err error) {
761762
if this.migrationContext.ApplierConnectionConfig, err = this.inspector.getMasterConnectionConfig(); err != nil {
762763
return err
763764
}
764-
if this.migrationContext.OverrideApplierHostname != "" {
765-
this.migrationContext.ApplierConnectionConfig.Key.Hostname = this.migrationContext.OverrideApplierHostname
765+
if this.migrationContext.AssumeMasterHostname != "" {
766+
if key, err := mysql.ParseRawInstanceKeyLoose(this.migrationContext.AssumeMasterHostname); err != nil {
767+
return err
768+
} else {
769+
this.migrationContext.ApplierConnectionConfig.Key = *key
770+
}
766771
}
767772
if this.migrationContext.TestOnReplica || this.migrationContext.MigrateOnReplica {
768773
if this.migrationContext.InspectorIsAlsoApplier() {

0 commit comments

Comments
 (0)