GH-OSTの作品
図1において、第1のソーステーブルとして、同じ構造をゴーストテーブルを作成
ゴースト変更するalter tableコマンドを使用して、2
バイナリログオンラインモードがフルミラーを含み、変更する前に変更(ライブラリコマンドからライブラリテーブルBINLOG、3.1メインアナログの取り込みをすべてのデータの後)、およびゴーストテーブルを実行する文を解析します。
3.2、データ取得先テーブルの範囲(例えば、最大値と最小値を取得するためにマスターキーに応じて)、次いで、データを表にゴーストにおけるコピーの挿入のバッチの複数に分割されている
4、ソース表ロックは、ソーステーブルデータを変更することからユーザーを防ぎます
5、ソースがテーブルの名前を変更し、ゴーストテーブルには、ソーステーブルと改名
ツールはゴーストテーブルを作成し、クリーニング、6、表のロック解除を。
GH-OSTコントラストPT-OSC
変更データを取得する方法: GH-依存BINLOG OSTの変更ログをデータコピーの際に取得したデータに、ログ形式は、より安全に必要なROWモード、操作です。 PT-OSCアップデートを入手するためのトリガーに依存している、それはより侵襲的な操作のために、元のテーブルにはトリガを必要としません。 オペレーションスレッドが異常効果を終了: 異常終了GH-OST処理の後、メインのライブラリにのみ一時テーブルを保持、ビジネスには影響しません。 PT-OSC異常終了した後、メインライブラリ上原テーブルはまた、タイムリーなクリーンアップとして、トリガを保持し、それが業績に影響を与えます。 ツールの影響業績: PT-OSCトリガーを使用して、動作性能、非常に同時明白でインパクトに影響を与えます。 変更操作を取得するGH-OST利用BINLOG、DML操作のパフォーマンスに影響を与えません。 ツールのトラフィック負荷の影響: 低負荷のシナリオでは、PT-OSC経過時間が短い場合には、(下部GH-OSTシーンは半分の時間である) GH-高負荷のシナリオでは、PT-OSCはゆっくり行い、実行することができ、 OSCはできるだけ早く決して完全に実行させる、BINLOG BINLOG世代を解決します。 高負荷のシナリオとinnodb_autoinc_lock_mode = 1(デフォルト)で、PT-OSCは、デッドロックをトリガする可能性がある例外が発生しますが、GH-OSCは、デッドロックにはつながりません。
GH-OSTの動作モード
メインライブラリに接続する1は、直接変更します
直接一次ライブラリ
マスターライブラリゴーストテーブルに作成された
新しいテーブル(ゴーストテーブル)の上に直接変更テーブルの構造を変更し
、新しいテーブルに元のテーブルデータを移行する
バイナリログイベントを解析引っ張り、新しいテーブルに適用
カットオーバ段階、新しいテーブルと元の交換テーブル
図2に示すように、メインライブラリに適用ライブラリから間接的に接続されています。
连接从库
校验完后,在主库创建新表
迁移原表数据到新表
模拟从库的从库,拉取解析增量binlog应用到主库
cut-over阶段,用新表替换掉原表
两者不同的点就在于,通过连接从库来进行变更,对主库的性能影响最小
数据一致性问题
由于使用binlog获得的数据总是新于或者等于从源表拷贝的数据:
1、在应用binlog导出的数据时,将UPDATE和DELETE直接应用ghost表,将INSERT修改为REPLACE INTO再应用到ghost表。
2、在copy源表数据到ghost表时,使用INSERT IGNORE来忽略掉ghost表已存在的记录
3、对于在gh-ost工作期间发生的DELETE操作:
A:如果记录在从源表删除前被复制到ghost表, 则ghost表中记录会在应用binlog导出的DELETE命令时删除。
B:使用记录在从源表复制到ghost表之前被删除,则记录不会被复制到ghost表,应用binlog导出的DELETE命令也不会报错。
跨服务器操作问题
假设有一套主从复制A1-->A2,A1为主库,A2为从库,另有一台服务器B1装有gh-ost,可以在B1上执行对A1上表的修改:
1、对于数据拷贝操作,B1发送查询到A1上先获取最大值和最小值,然后在B1上进行拆分成不同批次,再从B1上发送命令给A1执行小范围数据拷贝
2、对于Binlog解析,先模拟B1到A1的搭建复制,从A1上拉取binlog到B1,在B1上解析成SQL命令,再发送到A1上执行。
对于跨服务器执行gh-ost命令,会导致大量数据在数据库服务器到命令服务器之间传输,需要考虑网络带宽和网络稳定
唯一索引问题
如果通过gh-ost来新增唯一索引,由于REPLACE INTO和INSERT IGNORE会受到ghost表上唯一索引的影响,当在唯一索引上存在数据重复时,会导致数据丢失。
重命名原理
在pt-osc或者online ddl中,最后的rename操作一般是耗时比较短,但如果表结构变更过程中,有大查询进来,那么在rename操作的时候,会触发MDL锁的等待,如果在高峰期,这就是个严重的问题。所以gh-ost是怎么做的呢?
gh-ost利用了MySQL的一个特性,就是原子性的rename请求,在所有被blocked的请求中,优先级永远是最高的。
gh-ost基于此设计了该方案:一个连接对原表加锁,另启一个连接尝试rename操作,此时会被阻塞住,当释放lock的时候,rename会首先被执行,其他被阻塞的请求会继续应用到新表。
gh-ost常用参数
-critical-load --max-load Comma delimited status-name=threshold, same format as --max-load. When status exceeds threshold, app panics and quits 改表完成之后是否删除老表。 -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? 如果执行之前发现old-table,删除还是终止?默认终止。 -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 port选项仅对应的是host吗?其他地方都需要设置全 -port int MySQL port (preferably a replica, not the master) (default 3306) 因为gh-ost没有提供recursion-method=processlist方法,因此需要通过throttle-control-replicas指定所有的需要检查的slave,并且注意上面的port仅仅对应于host选项,因此需要host:port的方式来写全称 -throttle-control-replicas string List of replicas on which to check for lag; comma delimited. Example: myhost1.com:3306,myhost2.com,myhost3.com:3307 拷贝每个chunk之后sleep的时间=nice-ratio*copy-chunk-time,默认值是0,表示不sleep -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 默认是不删除socket文件的,这样当第二次运行的时候报错,提示socket文件已经存在 -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! -exact-rowcount actually count table rows as opposed to estimate them (results in more accurate progress estimation)
gh-ost命令模板
./gh-ost \ --max-load=Threads_running=25 \ --critical-load=Threads_running=64 \ --chunk-size=1000 \ --throttle-control-replicas="test02:3306" \ --max-lag-millis=1500 \ --initially-drop-old-table \ --initially-drop-ghost-table \ --initially-drop-socket-file \ --ok-to-drop-table \ --conf="./my.cnf" \ --host="test02" \ --port=3306 \ --user="admin" \ --password="admin" \ --database="test" \ --table="test" \ --verbose \ --alter="drop index id1" \ --switch-to-rbr \ --allow-master-master \ --cut-over=default \ --default-retries=120 \ --panic-flag-file=/tmp/ghost.panic.flag \ --postpone-cut-over-flag-file=/tmp/ghost.postpone.flag \ --execute
参考
https://rj03hou.github.io/mysql/gh-ost/