Skip to content

Commit 53508af

Browse files
author
Shlomi Noach
authored
Merge pull request #93 from github/documentation
Documentation
2 parents 67979fa + 033ee7f commit 53508af

10 files changed

+257
-44
lines changed

README.md

+50-36
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,80 @@
22

33
#### GitHub's online schema migration for MySQL
44

5-
`gh-ost` allows for online schema migrations in MySQL which are:
6-
- Triggerless
7-
- Testable
8-
- Pausable
9-
- Operations-friendly
5+
`gh-ost` is a triggerless online schema migration solution for MySQL. It is testable and provides with pausability, dynamic control/reconfiguration, auditing, and many operational perks.
6+
7+
`gh-ost` produces a light workload on the master throughout the migration, decoupled from the existing workload on the migrated table.
8+
9+
It has been designed based on years of experience with existing solutions, and changes the paradigm of table migrations.
10+
11+
![gh-ost logo](doc/images/gh-ost-logo-light-160.png)
1012

1113
## How?
1214

13-
WORK IN PROGRESS
15+
All existing online-schema-change tools operate in similar manner: they create a _ghost_ table in the likeness of your original table, migrate that table while empty, slowly and incrementally copy data from your original table to the _ghost_ table, meanwhile propagating ongoing changes (any `INSERT`, `DELETE`, `UPDATE` applied to your table) to the _ghost_ table. Finally, at the right time, they replace your original table with the _ghost_ table.
1416

15-
Please meanwhile refer to the [docs](doc) for more information. No, really, go to the [docs](doc).
17+
`gh-ost` uses the same pattern. However it differs from all existing tools by not using triggers. We have recognized the triggers to be the source of [many limitations and risks](doc/why-triggerless.md).
1618

17-
- [Why triggerless](doc/why-triggerless.md)
18-
- [Triggerless design](doc/triggerless-design.md)
19-
- [Cut over phase](doc/cut-over.md)
20-
- [Testing on replica](doc/testing-on-replica.md)
21-
- [Throttle](doc/throttle.md)
22-
- [Operational perks](doc/perks.md)
23-
- [Migrating with Statement Based Replication](doc/migrating-with-sbr.md)
24-
- [Understanding output](doc/understanding-output.md)
25-
- [Interactive commands](doc/interactive-commands.md)
26-
- [Command line flags](doc/command-line-flags.md)
19+
Instead, `gh-ost` [uses the binary log stream](doc/triggerless-design.md) to capture table changes, and asynchronously applies them onto the _ghost_ table. `gh-ost` takes upon itself some tasks that other tools leave for the database to perform. As result, `gh-ost` has greater control over the migration process; can truly suspend it; can truly decouple the migration's write load from the master's workload.
2720

28-
## Usage
21+
In addition, it offers many [operational perks](doc/perks.md) that make it safer, trustworthy and fun to use.
2922

30-
#### Where to execute
23+
![gh-ost general flow](doc/images/gh-ost-general-flow.png)
3124

32-
The recommended way of executing `gh-ost` is to have it connect to a _replica_, as opposed to having it connect to the master. `gh-ost` will crawl its way up the replication chain to figure out who the master is.
25+
## Highlights
3326

34-
By connecting to a replica, `gh-ost` sets up a self-throttling mechanism; feels more comfortable in querying `information_schema` tables; and more. Connecting `gh-ost` to a replica is also the trick to make it work even if your master is configured with `statement based replication`, as `gh-ost` is able to manipulate the replica to rewrite logs in `row based replication`. See [Migrating with Statement Based Replication](migrating-with-sbr.md).
27+
- Build your trust in `gh-ost` by testing it on replicas. `gh-ost` will issue same flow as it would have on the master, to migrate a table on a replica, without actually replacing the original table, leaving the replica with two tables you can then compare and satisfy yourself that the tool operates correctly. This is how we continuously test `gh-ost` in production.
28+
- True pause: when `gh-ost` [throttles](doc/throttle.md), it truly ceases writes on master: no row copies and no ongoing events processing. By throttling, you return your master to its original workload
29+
- Dynamic control: you can [interactively](doc/interactive-commands.md) reconfigure `gh-ost`, even as migration still runs. You may forcibly initiate throttling.
30+
- Auditing: you may query `gh-ost` for status. `gh-ost` listens on unix socket or TCP.
31+
- Control over cut-over phase: `gh-ost` can be instructed to postpone what is probably the most critical step: the swap of tables, until such time that you're comfortably available. No need to worry about ETA being outside office hours.
3532

36-
The replica would have to use binary logs and be configured with `log_slave_updates`.
33+
Please meanwhile refer to the [docs](doc) for more information. No, really, read the [docs](doc).
3734

38-
It is still OK to connect `gh-ost` directly on master; you will need to confirm this by providing `--allow-on-master`. The master would have to be using `row based replication`.
35+
## Usage
3936

40-
`gh-ost` itself may be executed from anywhere. It connects via `tcp` and it does not have to be executed from a `MySQL` box. However, do note it generates a lot of traffic, as it connects as a replica and pulls binary log data.
37+
The [cheatsheet](doc/cheatsheet.md) has it all. You may be interested in invoking `gh-ost` in various modes:
4138

42-
#### Testing on replica
39+
- a _noop_ migration (merely testing that the migration is valid and good to go)
40+
- a real migration, utilizing a replica (the migration runs on the master; `gh-ost` figures out identities of servers involved. Required mode if your master uses Statement Based Replication)
41+
- a real migration, run directly on the master (but `gh-ost` prefers the former)
42+
- a real migration on a replica (master untouched)
43+
- a test migration on a replica, the way for you to build trust with `gh-ost`'s operation.
4344

44-
Newcomer? We think you would enjoy building trust with this tool. You can ask `gh-ost` to simulate a migration on a replica -- this will not affect data on master and will not actually do a complete migration. It will operate on a replica, and end up with two tables: the original (untouched), and the migrated. You will have your chance to compare the two and verify the tool works to your satisfaction.
45+
Our tips:
4546

46-
```
47-
gh-ost --conf=.my.cnf --database=mydb --table=mytable --verbose --alter="engine=innodb" --execute --initially-drop-ghost-table --initially-drop-old-table -max-load=Threads_running=30 --switch-to-rbr --chunk-size=2500 --exact-rowcount --test-on-replica --verbose --postpone-cut-over-flag-file=/tmp/ghost.postpone.flag --throttle-flag-file=/tmp/ghost.throttle.flag
48-
```
49-
Please read more on [testing on replica](testing-on-replica.md)
47+
- [Testing above all](testing-on-replica.md), try out `--test-on-replica` first few times. Better yet, make it continuous. We have multiple replicas where we iterate our entire fleet of production tables, migrating them one by one, checksumming the results, verifying migration is good.
48+
- For each master migration, first issue a _noop_
49+
- Then issue the real thing via `--execute`.
5050

51-
#### Migrating a master table
51+
More tips:
5252

53-
```
54-
gh-ost --conf=.my.cnf --database=mydb --table=mytable --verbose --alter="engine=innodb" --initially-drop-ghost-table --initially-drop-old-table --max-load=Threads_running=30 --switch-to-rbr --chunk-size=2500 --exact-rowcount --verbose --postpone-cut-over-flag-file=/tmp/ghost.postpone.flag --throttle-flag-file=/tmp/ghost.throttle.flag [--execute]
55-
```
53+
- Use `--exact-rowcount` for accurate progress indication
54+
- Use `--postpone-cut-over-flag-file` to gain control over cut-over timing
55+
- Get familiar with the [interactive commands](doc/interactive-commands.md)
5656

57-
Note: in order to migrate a table on the master you don't need to _connect_ to the master. `gh-ost` is happy (and prefers) if you connect to a replica; it then figures out the identity of the master and makes the connection itself.
57+
Also see [requirements and limitations](doc/requirements-and-limitations.md), [what if?](doc/what-if.md)
5858

5959
## What's in a name?
6060

6161
Originally this was named `gh-osc`: GitHub Online Schema Change, in the likes of [Facebook online schema change](https://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932/) and [pt-online-schema-change](https://www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html).
6262

6363
But then a rare genetic mutation happened, and the `s` transformed into `t`. And that sent us down the path of trying to figure out a new acronym. Right now, `gh-ost` (pronounce: _Ghost_), stands for:
64-
- GitHub Online Schema Translator/Transformer/Transfigurator
64+
- GitHub Online Schema Transmogrifier/Translator/Transformer/Transfigurator
65+
66+
Pronounce: _ghost_
67+
68+
## License
69+
70+
`gh-ost` is licensed under the [MIT license](https://github.com/github/gh-ost/blob/documentation/LICENSE)
71+
72+
`gh-ost` uses 3rd party libraries, each with their own license. These are found [here](https://github.com/github/gh-ost/tree/master/vendor).
73+
74+
## Community
75+
76+
`gh-ost` is released at a stable state, but with mileage to go. We are [open to pull requests](https://github.com/github/gh-ost/blob/master/.github/CONTRIBUTING.md). Please first discuss your intentions via [Issues](https://github.com/github/gh-ost/issues).
77+
78+
We develop `gh-ost` at GitHub and for the community. We may have different priorities than others. From time to time we may suggest a contribution that is not on our immediate roadmap but which may appeal to others.
6579

6680
## Authors
6781

doc/cheatsheet.md

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Cheatsheet
2+
3+
![operation modes](images/gh-ost-operation-modes.png)
4+
5+
6+
`gh-ost` operates by connecting to potentially multiple servers, as well as imposing itself as a replica in order to streamline binary log events directly from one of those servers. There are various operation modes, which depend on your setup, configuration, and where you want to run the migration.
7+
8+
### a. Connect to replica, migrate on master
9+
10+
This is the mode `gh-ost` expects by default. `gh-ost` will investigate the replica, crawl up to find the topology's master, and will hook onto it as well. Migration will:
11+
12+
- Read and write row-data on master
13+
- Read binary logs events on the replica, apply the changes onto the master
14+
- Investigates table format, columns & keys, count rows on the replica
15+
- Read internal changelog events (such as heartbeat) from the replica
16+
- Cut-over (switch tables) on the master
17+
18+
If your master works with SBR, this is the mode to work with. The replica must be configured with binary logs enabled (`log_bin`, `log_slave_updates`) and should have `binlog_format=ROW` (`gh-ost` can apply the latter for you).
19+
20+
However even with RBR we suggest this is the least master-intrusive operation mode.
21+
22+
```shell
23+
gh-ost \
24+
--max-load=Threads_running=25 \
25+
--critical-load=Threads_running=1000 \
26+
--chunk-size=1000 \
27+
--throttle-control-replicas="myreplica.1.com,myreplica.2.com" \
28+
--max-lag-millis=1500 \
29+
--user="gh-ost" \
30+
--password="123456" \
31+
--host=replica.with.rbr.com \
32+
--database="my_schema" \
33+
--table="my_table" \
34+
--verbose \
35+
--alter="engine=innodb" \
36+
--switch-to-rbr \
37+
--allow-master-master \
38+
--cut-over=default \
39+
--exact-rowcount \
40+
--default-retries=120 \
41+
--panic-flag-file=/tmp/ghost.panic.flag \
42+
--postpone-cut-over-flag-file=/tmp/ghost.postpone.flag \
43+
[--execute]
44+
```
45+
46+
With `--execute`, migration actually copies data and flips tables. Without it this is a `noop` run.
47+
48+
49+
### b. Connect to master
50+
51+
If you don't have replicas, or do not wish to use them, you are still able to operate directly on the master. `gh-ost` will do all operations directly on the master. You may still ask it to be considerate of replication lag.
52+
53+
- Your master must produce binary logs in RBR format.
54+
- You must approve this mode via `--allow-on-master`.
55+
56+
```shell
57+
gh-ost \
58+
--max-load=Threads_running=25 \
59+
--critical-load=Threads_running=1000 \
60+
--chunk-size=1000 \
61+
--throttle-control-replicas="myreplica.1.com,myreplica.2.com" \
62+
--max-lag-millis=1500 \
63+
--user="gh-ost" \
64+
--password="123456" \
65+
--host=master.with.rbr.com \
66+
--allow-on-master \
67+
--database="my_schema" \
68+
--table="my_table" \
69+
--verbose \
70+
--alter="engine=innodb" \
71+
--switch-to-rbr \
72+
--allow-master-master \
73+
--cut-over=default \
74+
--exact-rowcount \
75+
--default-retries=120 \
76+
--panic-flag-file=/tmp/ghost.panic.flag \
77+
--postpone-cut-over-flag-file=/tmp/ghost.postpone.flag \
78+
[--execute]
79+
```
80+
81+
### c. Migrate/test on replica
82+
83+
This will perform a migration on the replica. `gh-ost` will briefly connect to the master but will thereafter perform all operations on the replica without modifying anything on the master.
84+
Throughout the operation, `gh-ost` will throttle such that the replica is up to date.
85+
86+
- `--migrate-on-replica` indicates to `gh-ost` that it must migrate the table directly on the replica. It will perform the cut-over phase even while replication is running.
87+
- `--test-on-replica` indicates the migration is for purpose of testing only. Before cut-over takes place, replication is stopped. Tables are swapped and then swapped back: your original table returns to its original place.
88+
Both tables are left with replication stopped. You may examine the two and compare data.
89+
90+
Test on replica cheatsheet:
91+
```shell
92+
gh-ost \
93+
--user="gh-ost" \
94+
--password="123456" \
95+
--host=replica.with.rbr.com \
96+
--test-on-replica \
97+
--database="my_schema" \
98+
--table="my_table" \
99+
--verbose \
100+
--alter="engine=innodb" \
101+
--initially-drop-ghost-table \
102+
--initially-drop-old-table \
103+
--max-load=Threads_running=30 \
104+
--switch-to-rbr \
105+
--chunk-size=2500 \
106+
--cut-over=default \
107+
--exact-rowcount \
108+
--serve-socket-file=/tmp/gh-ost.test.sock \
109+
--panic-flag-file=/tmp/gh-ost.panic.flag \
110+
--execute
111+
```
112+
113+
### cnf file
114+
115+
You may use a `cnf` file in the following format:
116+
117+
```
118+
[client]
119+
user=gh-ost
120+
password=123456
121+
```
122+
123+
You may then remove `--user=gh-ost --password=123456` and specify `--conf=/path/to/config/file.cnf`

doc/command-line-flags.md

+29-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@
22

33
A more in-depth discussion of various `gh-ost` command line flags: implementation, implication, use cases.
44

5-
##### conf
5+
### allow-on-master
6+
7+
By default, `gh-ost` would like you to connect to a replica, from where it figures out the master by itself. This wiring is required should your master execute using `binlog_format=STATEMENT`.
8+
9+
If, for some reason, you do not wish `gh-ost` to connect to a replica, you may connect it directly to the master and approve this via `--allow-on-master`.
10+
11+
### approve-renamed-columns
12+
13+
When your migration issues a column rename (`change column old_name new_name ...`) `gh-ost` analyzes the statement to try an associate the old column name with new column name. Otherwise the new structure may also look like some column was dropped and another was added.
14+
15+
`gh-ost` will print out what it thinks the _rename_ implied, but will not issue the migration unless you provide with `--approve-renamed-columns`.
16+
17+
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.
18+
19+
### conf
620

721
`--conf=/path/to/my.cnf`: file where credentials are specified. Should be in (or contain) the following format:
822

@@ -12,11 +26,11 @@ user=gromit
1226
password=123456
1327
```
1428

15-
##### cut-over
29+
### cut-over
1630

1731
Optional. Default is `safe`. See more discussion in [cut-over](cut-over.md)
1832

19-
##### exact-rowcount
33+
### exact-rowcount
2034

2135
A `gh-ost` execution need to copy whatever rows you have in your existing table onto the ghost table. This can, and often be, a large number. Exactly what that number is?
2236
`gh-ost` initially estimates the number of rows in your table by issuing an `explain select * from your_table`. This will use statistics on your table and return with a rough estimate. How rough? It might go as low as half or as high as double the actual number of rows in your table. This is the same method as used in [`pt-online-schema-change`](https://www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html).
@@ -29,20 +43,28 @@ A `gh-ost` execution need to copy whatever rows you have in your existing table
2943

3044
While the ongoing estimated number of rows is still heuristic, it's almost exact, such that the reported [ETA](understanding-output.md) or percentage progress is typically accurate to the second throughout a multiple-hour operation.
3145

32-
##### execute
46+
### execute
3347

3448
Without this parameter, migration is a _noop_: testing table creation and validity of migration, but not touching data.
3549

36-
##### initially-drop-ghost-table
50+
### initially-drop-ghost-table
3751

3852
`gh-ost` maintains two tables while migrating: the _ghost_ table (which is synced from your original table and finally replaces it) and a changelog table, which is used internally for bookkeeping. By default, it panics and aborts if it sees those tables upon startup. Provide `--initially-drop-ghost-table` and `--initially-drop-old-table` to let `gh-ost` know it's OK to drop them beforehand.
3953

4054
We think `gh-ost` should not take chances or make assumptions about the user's tables. Dropping tables can be a dangerous, locking operation. We let the user explicitly approve such operations.
4155

42-
##### initially-drop-old-table
56+
### initially-drop-old-table
4357

4458
See #initially-drop-ghost-table
4559

46-
##### test-on-replica
60+
### migrate-on-replica
61+
62+
Typically `gh-ost` is used to migrate tables on a master. If you wish to only perform the migration in full on a replica, connect `gh-ost` to said replica and pass `--migrate-on-replica`. `gh-ost` will briefly connect to the master but other issue no changes on the master. Migration will be fully executed on the replica, while making sure to maintain a small replication lag.
63+
64+
### skip-renamed-columns
65+
66+
See `approve-renamed-columns`
67+
68+
### test-on-replica
4769

4870
Issue the migration on a replica; do not modify data on master. Useful for validating, testing and benchmarking. See [test-on-replica](test-on-replica.md)

doc/images/gh-ost-general-flow.png

228 KB
Loading

doc/images/gh-ost-logo-dark-320.png

8.42 KB
Loading

doc/images/gh-ost-logo-light-160.png

4.19 KB
Loading

doc/images/gh-ost-operation-modes.png

112 KB
Loading

doc/requirements-and-limitations.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Requirements and limitations
2+
3+
### Requirements
4+
5+
- You will need to have one server serving Row Based Replication (RBR) format binary logs. `gh-ost` prefers to work with replicas. You may [still have your master configured with Statement Based Replication](migrating-with-sbr) (SBR).
6+
7+
- `gh-ost` requires an account with these privileges:
8+
9+
- `ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATE` on the database (schema) where your migrated table is, or of course on `*.*`
10+
- `SUPER, REPLICATION SLAVE` on `*.*`
11+
12+
### Limitations
13+
14+
- Foreign keys not supported. They may be supported in the future, to some extent.
15+
- Triggers are not supported. they may be supported in the future.
16+
- The two _before_ & _after_ tables must share some `UNIQUE KEY`. Such key would be used by `gh-ost` to iterate the table.
17+
- As an example, if your table has a single `UNIQUE KEY` and no `PRIMARY KEY`, and you wish to replace it with a `PRIMARY KEY`, you will need two migrations: one to add the `PRIMARY KEY` (this migration will use the existing `UNIQUE KEY`), another to drop the now redundant `UNIQUE KEY` (this migration will use the `PRIMARY KEY`).
18+
- The chosen migration key must not include columns with `NULL` values.
19+
- `gh-ost` will do its best to pick a migration key with non-nullable columns. It will by default refuse a migration where the only possible `UNIQUE KEY` includes nullable-columns. You may override this refusal via `--allow-nullable-unique-key` but **you must** be sure there are no actual `NULL` values in those columns. Such `NULL` values would cause a data integrity problem and potentially a corrupted migration.
20+
- It is not allowed to migrate a table where another table exists with same name and different upper/lower case.
21+
- For example, you may not migrate `MyTable` if another table called `MYtable` exists in the same schema.
22+
- Amazon `RDS` is probably not supported (due to `SUPER` requirement)
23+
- Multisource is not supported when migrating via replica. It _should_ work (but never tested) when connecting directly to master (`--allow-on-master`)

0 commit comments

Comments
 (0)