mysql gh ost 对比,Gh-OST 的设计和实现 | 很文博客

GitHub’s online schema migration tool for MySQL

gh-ost has been developed at GitHub in recent months to answer a problem we faced with ongoing, continuous production changes requiring modifications to MySQL tables. gh-ost changes the existing online table migration paradigm by providing a low impact, controllable, auditable, operations friendly solution.

gh-ost

gh-ost : stands for GitHub’s Online Schema

– Triggerless

– Lightweight

– Pauseable

– Dynamically controllable

– Auditable

– Testable

– Trustable

– Triggerless

60f6bdeeda7ab6d4824491dbfbe7a917.gif

Transmogrifier/Transfigurator/Transformer/Thingy

使用方式

# 执行命令

./gh-ost --help

#输出

-allow-master-master

explicitly allow running in a master-master setup

-allow-nullable-unique-key

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!

-allow-on-master

allow this migration to run directly on master. Preferably it would run on a replica

-alter string

alter statement (mandatory)

-approve-renamed-columns ALTER

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

-chunk-size int

amount of rows to handle in each iteration (allowed range: 100-100,000) (default 1000)

-conf string

Config file

-critical-load --max-load

Comma delimited status-name=threshold, same format as --max-load. When status exceeds threshold, app panics and quits

-cut-over string

choose cut-over type (default|atomic, two-step) (default "atomic")

-cut-over-lock-timeout-seconds int

Max number of seconds to hold locks on tables while attempting to cut-over (retry attempted when lock exceeds timeout) (default 3)

-database string

database name (mandatory)

-debug

debug mode (very verbose)

-default-retries int

Default number of retries for various operations before panicking (default 60)

-exact-rowcount

actually count table rows as opposed to estimate them (results in more accurate progress estimation)

-execute

actually execute the alter & migrate the table. Default is noop: do some tests and exit

-help

Display usage

-host string

MySQL hostname (preferably a replica, not the master) (default "127.0.0.1")

-initially-drop-ghost-table

Drop a possibly existing Ghost table (remains from a previous run?) before beginning operation. Default is to panic and abort if such table exists

-initially-drop-old-table

Drop a possibly existing OLD table (remains from a previous run?) before beginning operation. Default is to panic and abort if such table exists

-initially-drop-socket-file

Should gh-ost forcibly delete an existing socket file. Be careful: this might drop the socket file of a running migration!

-max-lag-millis int

replication lag at which to throttle operation (default 1500)

-max-load string

Comma delimited status-name=threshold. e.g: 'Threads_running=100,Threads_connected=500'. When status exceeds threshold, app throttles writes

-migrate-on-replica

Have the migration run on a replica, not on the master. This will do the full migration on the replica including cut-over (as opposed to --test-on-replica)

-nice-ratio float

force being 'nice', imply sleep time per chunk time; range: [0.0..100.0]. Example values: 0 is aggressive. 1.5: for every ms spend in a rowcopy chunk, spend 1.5ms sleeping immediately after

-ok-to-drop-table

Shall the tool drop the old table at end of operation. DROPping tables can be a long locking operation, which is why I'm not doing it by default. I'm an online tool, yes?

-panic-flag-file string

when this file is created, gh-ost will immediately terminate, without cleanup

-password string

MySQL password

-port int

MySQL port (preferably a replica, not the master) (default 3306)

-postpone-cut-over-flag-file string

while this file exists, migration will postpone the final stage of swapping tables, and will keep on syncing the ghost table. Cut-over/swapping would be ready to perform the moment the file is deleted.

-quiet

quiet

-replication-lag-query string

Query that detects replication lag in seconds. Result can be a floating point (by default gh-ost issues SHOW SLAVE STATUS and reads Seconds_behind_master). If you're using pt-heartbeat, query would be something like: SELECT ROUND(UNIX_TIMESTAMP() - MAX(UNIX_TIMESTAMP(ts))) AS delay FROM my_schema.heartbeat

-serve-socket-file string

Unix socket file to serve on. Default: auto-determined and advertised upon startup

-serve-tcp-port int

TCP port to serve on. Default: disabled

-skip-renamed-columns ALTER

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

-stack

add stack trace upon error

-switch-to-rbr

let this tool automatically switch binary log format to 'ROW' on the replica, if needed. The format will NOT be switched back. I'm too scared to do that, and wish to protect you if you happen to execute another migration while this one is running

-table string

table name (mandatory)

-test-on-replica

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

-throttle-additional-flag-file string

operation pauses when this file exists; hint: keep default, use for throttling multiple gh-ost operations (default "/tmp/gh-ost.throttle")

-throttle-control-replicas string

List of replicas on which to check for lag; comma delimited. Example: myhost1.com:3306,myhost2.com,myhost3.com:3307

-throttle-flag-file string

operation pauses when this file exists; hint: use a file that is specific to the table being altered

-throttle-query string

when given, issued (every second) to check if operation should throttle. Expecting to return zero for no-throttle, >0 for throttle. Query is issued on the migrated server. Make sure this query is lightweight

-user string

MySQL user

-verbose

verbose

-version

Print version & exit

example

--max-load=Threads_running=25 \

--critical-load=Threads_running=1000 \

--chunk-size=1000 \

--throttle-control-replicas="replip" \

--max-lag-millis=1500 \

--user="xxxxx" \

--password="xxxxxx" \

--host="xxx.xxx..xxx.13" \

--port=3306 \

--database="test" \

--table="big_data_check_hdfs" \

--verbose \

--alter="change file_path file_path varchar(128) " \

--switch-to-rbr \

--allow-master-master \

--cut-over=default \

--exact-rowcount \

--default-retries=120 \

--postpone-cut-over-flag-file=/data/dbbak/gh-ost/ghost.postpone.flag \

--execute

原理:

gh-ost最核心的两个模块: 行数据拷贝 ; 日志解析和应用 . 两个操作是同时并发执行的, 只要有日志就会立即在影子表执行.

行数据拷贝(row copy)

Row Copy的逻辑如下:

计算Chunk

对每个 Chunk 数据进行copy, copy的过程中 , 对原表进行加锁, 保证copy过程中没有对正在copy的数据进行修改操作.(如果是给表添加unique key,重复的数据会被ignore, 正常现象)

insert /* gh-ost %s.%s */ ignore into %s.%s (%s)

(select %s from %s.%s force index (%s)

where (%s and %s) %s  lock in share mode

将所有的 chunck都copy完成,整个copy过程完成

日志解析和应用

通过伪装为slave的方式从master获取binglog日志, 并解析拼装成为sql ,在目标库或者源库执行(这取决于在哪个库做操作, 大部分是在主库)

可行性分析

由于RowCopy的过程中是加锁的, 所以copy过程中是不存在对这部分数据的任何修改操作的, 即数据在copy过程中不可能有对应的binlog产生. 所以我们对不同类型的操作只需要分析 log before copy (b-log) 和 log after copy(a-log) , 我们假设copy过程为t0区间(可以看做一个时间点)

代码生成模板

INSTER

result = fmt.Sprintf(`

replace /* gh-ost %s.%s */ into

%s.%s

(%s)

values

(%s)

`, databaseName, tableName,

databaseName, tableName,

strings.Join(mappedSharedColumnNames, ", "),

strings.Join(preparedValues, ", "),

日志提前到达, 直接insert进来, rowcopy的时候会被忽略. 日志延迟到

#如下逻辑

if b-log > t0:

日志延迟到达, 没有关系直接replace

else:

日志提前到达, 直接insert进来, rowcopy的时候会被忽略

UPDATE

fmt.Sprintf(`

update /* gh-ost %s.%s */

%s.%s

set

%s

where

%s

`, databaseName, tableName,

databaseName, tableName,

setClause,

equalsComparison

#如下逻辑

if b-log > t0:

直接update目标表数据

else:

空update, rowcopy的时候会把new 值带过来

if a-log > t0:

空update

else:

直接update, 相当于update了两次

DELETE

result = fmt.Sprintf(`

delete /* gh-ost %s.%s */

from

%s.%s

where

%s

`, databaseName, tableName,

databaseName, tableName,

equalsComparison,

)

#如下逻辑

if b-log > t0:

空删除

else:

空删除

总结

gh-ost以一个新的思路来完成 online ddl 等操作, 避免了传统使用trigger方式来操作的很多弊端. 不过目前gh-ost尚未流行,需要进行充分的测试才可以上生产环境. 总之 , gh-ost是一个好工具。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值