背景: DBA として、大規模なテーブルの DDL 変更のほとんどは、Percona の pt-online-schema-change を使用して行われます。この記事では、別のツールである gh-ost の使用について説明します。このツールは、スレーブをシミュレートし、行の binlog で増分変更を取得し、それをゴースト テーブルに非同期的に適用するため、トリガーに依存しません。 gh-ost を使用する前に、まず GitHub オープンソース MySQL オンライン スキーマ変更ツール [transfer] の記事または公式 Web サイトを読んで、その機能と原理を理解してください。この記事では使用方法のみを説明します。 例: 1) ダウンロードしてインストールします: https://github.com/github/gh-ost/tags 2) パラメータの説明: gh-ost --help gh-ost の使用法: --aliyun-rds: Alibaba Cloud Database で実行するかどうか。真実 --allow-master-master: gh-ost をデュアルマスター レプリケーション アーキテクチャで実行できるようにするかどうか。通常は、-assume-master-host パラメータと一緒に使用します。--allow-nullable-unique-key: gh-ost がデータ移行が依存する一意のキーを NULL にすることを許可します。デフォルトでは、NULL 一意のキーは許可されません。データ移行の対象となる一意のキーが NULL 値を許可する場合、不正確なデータが生成される可能性があります。注意して使用してください。 --allow-on-master: gh-ost がマスター上で直接実行できるようにします。 gh-ost が接続するデフォルトのスレーブ。 --alter 文字列:DDL ステートメント --approve-renamed-columns ALTER: 列の名前を変更すると、gh-ost はこれを認識し、列名の変更理由を尋ねます。デフォルトでは、--approve-renamed-columns ALTER を指定しない限り、gh-ost は続行しません。 --ask-pass:MySQL パスワード --assume-master-host 文字列:「ip:port」または「hostname:port」の形式で、gh-ost のマスター データベースを指定します。これは、マスター-マスター アーキテクチャの場合、または gh-ost がマスターを見つけられない場合に役立ちます。 --assume-rbr: gh-ost が接続されているデータベース インスタンスに binlog_format=ROW が設定されている場合は、-assume-rbr を指定できます。これにより、スレーブ上で stop slave と start slave が実行されなくなり、gh-ost ユーザーは実行に SUPER 権限を必要としなくなります。 --チェックフラグ --chunk-size int: 各反復で処理する行数 (許容範囲: 100-100000)、デフォルト値は 1000 です。 --concurrent-rowcount: このパラメータが True (デフォルト) の場合、行のコピー後、gh-ost は (explain select count(*) を使用して) 行数を推定し、ETA を調整します。それ以外の場合、gh-ost は最初に行数を推定してから行のコピーを開始します。 --conf 文字列: gh-ost 構成ファイルのパス。 --critical-load string: カンマで区切られた status-name=values のリスト。MySQL ステータスが対応する値を超えると、gh-ost は終了します。 -critical-load Threads_connected=20,Connections=1500 は、MySQL のステータス値が Threads_connected>20,Connections>1500 の場合、データベースの重大な負荷により gh-ost が停止して終了することを意味します。 カンマ区切りの status-name=threshold、--max-load と同じ形式。ステータスがしきい値を超えると、アプリはパニックを起こして終了します。 --critical-load-hibernate-seconds int : 臨界負荷に達すると、gh-ost は指定された時間休止状態になります。 どのサーバーからも何も読み書きしません。 --critical-load-interval-millis int: 値が 0 の場合、gh-ost は臨界負荷に達するとすぐに終了します。値が 0 でない場合、gh-ost は -critical-load に達したときに -critical-load-interval-millis 秒後に再度チェックします。2 回目のチェック後も -critical-load に達した場合、gh-ost は終了します。 --cut-over 文字列: カットオーバー タイプ (アトミック/ツーステップ) を選択します。アトミック (デフォルト) タイプのカットオーバーでは github アルゴリズムが使用され、ツーステップ タイプでは facebook-OSC アルゴリズムが使用されます。 --カットオーバー指数バックオフ --cut-over-lock-timeout-seconds int: gh-ost のカットオーバー フェーズ中の最大ロック待機時間。ロックがタイムアウトすると、gh-ost はカットオーバーを再試行します。 (デフォルト: 3) --database 文字列: データベース名。 --debug: デバッグモード。 --default-retries int: パニックが発生する前にさまざまな操作を再試行する回数。 (デフォルトは60) --discard-foreign-keys: このパラメータは、外部キーを持つテーブル用です。gh-ost がゴースト テーブルを作成する場合、ゴースト テーブルの外部キーは作成されません。このパラメータは外部キーを削除する場合に便利ですが、それ以外の場合は注意して使用してください。 --dml-batch-size int: 単一トランザクションで DML イベントを適用するためのバッチ サイズ (範囲 1 ~ 100) (デフォルト 10) --exact-rowcount: テーブルの行数を正確にカウントし (select count(*) を使用)、より正確な時間を推定します。 --execute: 実際にテーブルの変更と移行を実行します。デフォルトは noop で、実行しないことを意味します。テストして終了するだけです。ALTER TABLE ステートメントを実際にデータベースに実装したい場合は、-execute を明示的に指定する必要があります。 --指数バックオフ最大間隔 int --force-named-cut-over: true の場合、'unpostpone | cut-over' 対話型コマンドは移行されたテーブルに名前を付ける必要があります --force-table-names 文字列: 一時テーブルで使用するテーブル名のプレフィックス --heartbeat-interval-millis int: gh-ost ハートビートの頻度の値、デフォルトは 500 - ヘルプ --hooks-hint 文字列: GH_OST_HOOKS_HINT を介してフックに挿入される任意のメッセージ --hooks-path 文字列: フック ファイルが保存されるディレクトリ (デフォルトは空、つまりフックは無効)。フックは、このディレクトリ内で同じ命名規則を持つフック ファイルを検索して実行します。 --host 文字列:MySQL IP/ホスト名 --initially-drop-ghost-table: gh-ost 操作の前に既存のゴースト テーブルをチェックして削除します。このパラメータは推奨されません。既存のゴースト テーブルを手動で処理してください。デフォルトでは、このパラメータは有効になっていないため、gh-ost は操作を終了します。 --initially-drop-old-table: gh-ost 操作の前に、既存の古いテーブルをチェックして削除します。このパラメータは推奨されません。既存のゴースト テーブルを手動で処理してください。デフォルトでは、このパラメータは有効になっていないため、gh-ost は操作を終了します。 --initially-drop-socket-file:gh-ost は既存のソケット ファイルを強制的に削除します。このパラメータは推奨されません。実行中の gh-ost プログラムが削除され、DDL 障害が発生する可能性があります。 --master-password string:MySQL マスター パスワード --master-user string:MySQL マスター アカウント --max-lag-millis int:マスター スレーブ レプリケーションの最大遅延時間。マスター スレーブ レプリケーションの遅延時間がこの値を超えると、gh-ost はスロットル対策を講じます。デフォルト値: 1500 秒。 --max-load 文字列: カンマ区切りのステータス名 = しきい値、例: 'Threads_running=100,Threads_connected=500'。ステータスがしきい値を超えると、アプリは書き込みを制限します。 --migrate-on-replica: gh-ost はマスターではなくレプリカ上で移行を実行します。 --nice-ratio float: 各チャンク期間のスリープ時間(範囲は [0.0…100.0])。 0: 各チャンク期間でスリープなし。つまり、1 つのチャンクが次々に実行されます。1: 行コピーごとにさらに 1 ミリ秒スリープします。0.7: 行コピーごとに 10 ミリ秒スリープします。 --ok-to-drop-table: gh-ost 操作が完了すると、古いテーブルが削除されます。デフォルトでは、古いテーブルは削除されず、_tablename_del テーブルが存在します。 --panic-flag-file 文字列: このファイルが作成されると、gh-ost は直ちに終了します。 --password string : MySQL パスワード --port int : MySQL ポート (スレーブが望ましい) --postpone-cut-over-flag-file string : このファイルが存在する場合、gh-ost のカットオーバー フェーズは延期され、ファイルが削除されるまでデータは引き続き複製されます。 --quiet: 静音モード。 --replica-server-id uint : gh-ost の server_id --replication-lag-query 文字列: 非推奨 --serve-socket-file 文字列: gh-ost のソケット ファイルへの絶対パス。 --serve-tcp-port int: gh-ost に使用するポート。デフォルトは閉じたポートです。 --skip-foreign-key-checks: テーブルに外部キーがないことを確認して、gh-ost 検証をスキップする場合は、「true」に設定します。 --skip-renamed-columns ALTER: 列の名前を変更すると (例: 列の変更)、gh-ost はこれを認識し、列名の変更理由を尋ねます。デフォルトでは、gh-ost はコマンドを続行しません。このパラメータは、gh-ost に列の移行をスキップし、名前が変更された列を don’t care 列として扱うように指示します。この操作は危険です。列内のすべての値が失われます。 --stack: エラー スタック トレースを追加します。 --switch-to-rbr: gh-ost に、スレーブ リポジトリの binlog_format を ROW 形式に自動的に切り替えるように指示します。 --table 文字列: テーブル名 --test-on-replica: スレーブでのデータ移行を含め、スレーブで gh-ost をテストします。データ移行が完了したら、スレーブを停止し、すぐに元のテーブルをゴースト テーブルと交換し、すぐに元に戻します。 2 つのテーブルを比較できるように、スレーブを停止し続けます。 --test-on-replica-skip-replica-stop: -test-on-replica を実行する場合、このパラメータはプロセス中にスレーブを停止する必要がないことを意味します。 --throttle-additional-flag-file 文字列: このファイルが作成されると、gh-ost 操作は直ちに停止します。このパラメータは、複数の gh-ost 操作が同時に実行されている場合に、ファイルを作成してすべての gh-ost 操作を停止したり、ファイルを削除してすべての gh-ost 操作を再開したりするために使用できます。 --throttle-control-replicas 文字列: マスター-スレーブ レプリケーションの遅延を確認する必要があるすべてのスレーブ ライブラリを一覧表示します。 --throttle-flag-file 文字列: このファイルが作成されると、gh-ost 操作は直ちに停止します。このパラメータは、単一の gh-ost 操作を制御するのに適しています。 -throttle-additional-flag-file 文字列は、複数の gh-ost 操作を制御するのに適しています。 --throttle-http 文字列 --throttle-query 文字列: スロットルクエリ。 1 秒ごとに 1 回実行されます。戻り値が 0 の場合、スロットルは必要ありません。戻り値 > 0 の場合、スロットルを実行する必要があります。このクエリは移行されたサーバー上で実行されるため、軽量であることを確認してください。 --timestamp-old-table: 古いテーブル名にタイムスタンプを使用します。 これにより、古いテーブル名の相互移行が一意になり、競合がなくなります --tungsten: gh-ost に、tungsten レプリケーション トポロジを実行していることを伝えます。 --user 文字列 :MYSQL ユーザー --verbose --バージョン 3) 使用手順: 前提条件として、MySQL 操作に必要な binlog モードが ROW であることが必要です。スレーブでテストする場合は、ROW モードも使用し、log_slave_updates を有効にする必要があります。上記の説明に従って、必要に応じてパラメータを調整します。 環境: マスター ライブラリ: 192.168.163.131; スレーブ ライブラリ: 192.168.163.130 DDL プロセス: ① 外部キーとトリガーがあるか確認します。 ②テーブルの主キー情報を確認します。 ③ マスターデータベースかスレーブデータベースか、log_slave_updates が有効かどうか、および binlog 情報を確認します ④ gho と del で終わる一時テーブルが存在するかどうかを確認します ⑤ データ移行情報や binlog 情報などを格納するために ghc で終わるテーブルを作成します --- 上記の検証段階 ⑥ ストリーム接続を初期化し、binlog リスニングを追加します --- 次の移行段階 ⑥ gho で終わる一時テーブルを作成し、gho で終わる一時テーブルに対して DDL を実行します ⑦ トランザクションを開始し、プライマリキー ID に従って gho で終わるテーブルにソーステーブルデータを書き込み、送信し、binlog を適用します。 ---次の切り替え段階⑧ ソーステーブルをロックし、テーブルの名前を変更します。ソーステーブルの名前をsource_delテーブルに変更し、ghoテーブルの名前をソーステーブルに変更します。 ⑨ ghcテーブルをクリーンアップします。 1. 単一インスタンスでの DDL: 単一インスタンスはマスター データベースと同等であり、--allow-on-master パラメータと ROW モードを有効にする必要があります。 gh-ost --user="root" --password="root" --host=192.168.163.131 --database="test" --table="t1" --alter="ADD COLUMN cc2 varchar(10),add column cc3 int not null default 0 comment 'test' " --allow-on-master --execute 2. マスターとスレーブでの DDL: オプションは 2 つあります。1 つは、手順 1 に従ってマスターからスレーブにデータを直接同期することです。もう 1 つは、スレーブに接続してマスターからデータを移行することです (マスターではなくスレーブの binlog が ROW であることを確認してください)。 gh-ost --user="root" --password="root" --host=192.168.163.130 --database="test" --table="t" --initially-drop-old-table --alter="ADD COLUMN y1 varchar(10),add column y2 int not null default 0 comment 'test' " --execute このときの操作は、おおよそ次のようになります。
DDL を実行すると、スレーブ データベースはスレーブの停止/開始コマンドを実行します。スレーブの binlog が ROW であることが確実な場合は、パラメータ --assume-rbr を追加できます。スレーブのバイナリログがROWでない場合は、パラメータ--switch-to-rbrを使用してROWに変換できます。このとき、実行後にバイナリログモードが元の値に変換されないことに注意してください。 --assume-rbr パラメータと --switch-to-rbr パラメータを一緒に使用することはできません。 3. スレーブで DDL テストを実行します。 gh-ost --user="root" --password="root" --host=192.168.163.130 --database="test" --table="t" --alter="ADD COLUMN abc1 varchar(10),add column abc2 int not null default 0 comment 'test' " --test-on-replica --switch-to-rbr --execute パラメータ --test-on-replica: スレーブでのデータ移行、データ移行完了後のスレーブの停止、元のテーブルとゴーストテーブルの即時スワップ、その後即時スワップバックなど、スレーブで gh-ost をテストします。 2 つのテーブルを比較できるように、スレーブを停止し続けます。スレーブを停止したくない場合は、パラメータを追加できます: --test-on-replica-skip-replica-stop 上記の 3 つは gh-ost 操作モードです。上記の操作では、一時テーブルは最後にクリーンアップされないため、手動でクリーンアップする必要があります。次の実行前に一時テーブルがまだ存在する場合、実行は失敗します。パラメータを使用して削除できます。 --initially-drop-ghost-table: gh-ost 操作の前に既存のゴースト テーブルをチェックして削除します。このパラメータは推奨されません。既存のゴースト テーブルを手動で処理してください。デフォルトでは、このパラメータは有効になっていないため、gh-ost は操作を終了します。 --initially-drop-old-table: gh-ost 操作の前に、既存の古いテーブルをチェックして削除します。このパラメータは推奨されません。既存のゴースト テーブルを手動で処理してください。デフォルトでは、このパラメータは有効になっていないため、gh-ost は操作を終了します。 --initially-drop-socket-file:gh-ost は既存のソケット ファイルを強制的に削除します。このパラメータは推奨されません。実行中の gh-ost プログラムが削除され、DDL 障害が発生する可能性があります。 --ok-to-drop-table: gh-ost 操作が完了すると、古いテーブルが削除されます。デフォルトでは、古いテーブルは削除されず、_tablename_del テーブルが存在します。 他にも、--exact-rowcount、--max-lag-millis、--max-load などのパラメータがあります。上記の手順を参照してください。よく使用されるパラメータ コマンドのほとんどは次のようになります。 gh-osc --user= --password= --host= --database= --table= --max-load=Threads_running=30、--chunk-size=1000 --serve-socket-file=/tmp/gh-ost.test.sock --exact-rowcount --allow-on-master/--test-on-replica --initially-drop-ghost-table/--initially-drop-old-table/--initially-drop-socket-file --max-lag-millis= --max-load='Threads_running=100、Threads_connected=500' --ok-to-drop-table 4) 追加指示: 終了、停止、速度制限 gh-ost --user="root" --password="root" --host=192.168.163.131 --database="test" --table="t1" --alter="ADD COLUMN o2 varchar(10),add column o1 int not null default 0 comment 'test' " --exact-rowcount --serve-socket-file=/tmp/gh-ost.t1.sock --panic-flag-file=/tmp/gh-ost.panic.t1.flag --postpone-cut-over-flag-file=/tmp/ghost.postpone.t1.flag --allow-on-master --execute ① 操作を終了するためのフラグファイル: --panic-flag-file 操作を終了するためのファイルを作成します。この例では、実行中の gh-ost を終了するために /tmp/gh-ost.panic.t1.flag ファイルが作成されます。一時ファイルのクリーンアップは手動で行う必要があります。 ② 当該ファイルのカットオーバー禁止、つまりテーブル名の切り替えが禁止され、データレプリケーションが正常に行われていることを示します。 --カットオーバーフラグファイルの延期 カットオーバーを遅延する、つまり切り替え操作を延期するためのファイルを作成します。この例では、/tmp/ghost.postpone.t1.flag ファイルが作成されます。gh-ost は行のレプリケーションを完了しますが、テーブルは切り替えません。元のテーブルから一時テーブルへのデータ更新の同期を継続します。 ③ソケットを使用してリクエストをリッスンし、オペレーターはコマンドの実行後に対応するパラメータを変更できます。 --serve-socket-file、--serve-tcp-port(デフォルトでは無効) リスニング用のソケット ファイルを作成し、インターフェイスを介してパラメータを調整します。操作中に負荷と遅延が増加した場合は、操作を終了し、チャンク サイズなどのパラメータを再設定する必要があります。その後、操作コマンドを再実行できます。動的な調整は、ソケット インターフェイスを介して行うことができます。のように: 一時停止操作: # エコースロットルを一時停止 | socat - /tmp/gh-ost.test.t1.sock #再開エコー スロットルなし | socat - /tmp/gh-ost.test.t1.sock 速度制限パラメータを変更します。 echo チャンクサイズ=100 | socat - /tmp/gh-ost.t1.sock エコー最大ラグミリ=200 | socat - /tmp/gh-ost.t1.sock エコー最大負荷=Thread_running=3 | socat - /tmp/gh-ost.t1.sock 4) pt-online-schema-changeとの比較テスト 1. テーブルが書き込まれておらず、パラメータがデフォルトの場合、2 つの DDL 操作時間はほぼ同じです。結局のところ、どちらも行のコピー操作です。 2. テーブルへの書き込みが多い場合 (sysbench)、pt-osc はマルチスレッドで高速に実行できますが、gh-ost はシングルスレッド アプリケーションをシミュレートします。極端な場合、DDL 操作を完了するのは非常に困難です。 結論: pt-osc はトリガーを必要とせず、メイン データベースの負荷とパフォーマンスへの影響ははるかに少ないですが、高同時実行シナリオでの DDL の効率は依然として pt-osc よりも低いため、ピーク時以外の営業時間中に処理する必要があります。関連するテストについては、gh-ost と pt-osc のパフォーマンス比較を参照してください。 5) カプセル化スクリプト: 環境: M: 192.168.163.131 (ROW)、S: 192.168.163.130/132 ラッパースクリプト: gh-ost.py #!/bin/env python # -*- エンコーディング: utf-8 -*- #---------------------------------------------- # 目的: gh-ost # 作成日: 2018-06-16 #---------------------------------------------- MySQLdbをインポートする 輸入再 インポートシステム インポート時間 サブプロセスのインポート インポートOS optparse から OptionParser をインポートする calc_time() を定義します。 def _deco(*args, **kwargs): begin_time = 時間.時間() 関数(*引数、**キーワード) cost_time = time.time() - begin_time 'コスト時間: %ss' を出力 % round(cost_time,2) _decoを返す def get_table_count(conn,dbname,tbname): クエリ = ''' SELECT count(*) FROM %s.%s ''' %(dbname,tbname) カーソル = conn.cursor() カーソル.execute(クエリ) row_nums = カーソル.fetchone() カーソルを閉じる() 接続を閉じる() row_numsを返す def online_ddl(conn,ddl_cmd): カーソル = conn.cursor() カーソル.execute(ddl_cmd) conn.commit() カーソルを閉じる() 接続を閉じる() #@計算時間 def run_cmd(cmd): p = サブプロセス.Popen(cmd, シェル=True) p,p.pidを返す def drop_ghost_table(conn, ゴースト名リスト): 試す: カーソル = conn.cursor() クエリ = ''' %s が存在する場合はテーブルを削除してください。''' %(ghost_name_list) カーソル.execute(クエリ) conn.commit() カーソルを閉じる() 接続を閉じる() 例外を除く、e: 印刷e __name__ == "__main__" の場合: パーサー = OptionParser() parser.add_option("-P", "--Port", help="検索用のポート", dest="ポート") parser.add_option("-D", "--Dbname", help="使用するDbname", dest="dbname") parser.add_option("-T", "--Table", help="使用するテーブル", dest="テーブル名") (オプション、引数) = parser.parse_args() そうでない場合、options.port: 'params port need to apply' を印刷します 出口() そうでない場合、options.dbname: 'params dbname need to apply' を印刷します 出口() そうでない場合、options.tablename: 'params tablename need to apply' を印刷します 出口() gh_ost_socket = '/tmp/gh-ost.%s.%s.sock' %(options.dbname,options.tablename) #終了フラグ panic_flag = '/tmp/gh-ost.panic.%s.%s.flag' %(options.dbname,options.tablename) # postpone_flag = '/tmp/gh-ost.postpone.%s.%s.flag' %(options.dbname,options.tablename) #スロットルフラグ throttle_flag = '/tmp/gh-ost.throttle.%s.%s' %(options.dbname,options.tablename) # ソケット = '/data/%s/tmp/mysql.sock' %(options.port) ソケット = '/var/run/mysqld/mysqld.sock' get_conn = MySQLdb.connect(ホスト='192.168.163.131'、ポート=int(options.port)、ユーザー='root'、パスワード='root'、db=options.dbname、unix_socket=socket、文字セット='utf8') conn = MySQLdb.connect(ホスト='192.168.163.131'、ポート=int(options.port)、ユーザー='root'、パスワード='root'、db=options.dbname、unix_socket=socket、文字セット='utf8') (テーブル数、) = get_table_count(get_conn、オプション.dbname、オプション.tablename) print ("\033[0;32m%s\033[0m" % "テーブル数: %s" %table_count) DDL_CMD = raw_input('DDL CMDを入力してください: ').replace('`','') gh_command_list = re.split('[ ]+',DDL_CMD) gh_command_list[0].upper() == 'CHANGE' かつ gh_command_list[1] != gh_command_list[2] の場合: print ("\033[0;31m%s\033[0m" % "名前が変更された列のデータは失われます。pt-osc は終了します...") 出口() table_count <= 10000の場合: ddl = ''' ALTER TABLE %s %s ''' %(options.tablename,DDL_CMD) 印刷 ("\033[0;36m%s\033[0m" %ddl) print ("\033[0;32m%s\033[0m" % "オンライン DDL ...") online_ddl(接続、ddl) print ("\033[0;32m%s\033[0m" % "実行が完了しました...") 出口() それ以外: MAX_LOAD = raw_input('最大実行スレッド数【25】を入力してください: ') MAX_LOADでない場合: 実行中のスレッド数 = 25 それ以外: 試す: 実行中のスレッド数 = int(MAX_LOAD) ValueErrorを除く: print ("\033[0;31m%s\033[0m" % "入力タイプエラー、終了...") 出口() CHUNK_SIZE = raw_input('最大チャンクサイズ【1000】を入力してください: ') CHUNK_SIZEでない場合: チャンクサイズ = 1000 それ以外: 試す: チャンクサイズ = int(CHUNK_SIZE) ValueErrorを除く: print ("\033[0;31m%s\033[0m" % "入力タイプエラー、終了...") 出口() 印刷 ("\033[0;32m%s\033[0m" % "gh-ost ddl ...") #--カットオーバーフラグファイルを延期する=%s gh_command = '''/usr/bin/gh-ost --user="root" --password="root" --host=192.168.163.131 --port=%s --database="%s" --table="%s" --allow-on-master --max-load='Threads_running=%d' --chunk-size=%d --serve-socket-file=%s --panic-flag-file=%s --throttle-additional-flag-file=%s --alter="%s" --execute ''' %(options.port,options.dbname,options.tablename,Threads_running,chunk_size,gh_ost_socket,panic_flag,throttle_flag,DDL_CMD) 印刷 ("\033[0;36m%s\033[0m" %gh_command) 子、pid = run_cmd(gh_command) print ("\033[0;31mgh-ost の PID: %s\033[0m" %pid) print ("\033[0;33mCreate: [touch %s] ファイル、DDL を一時停止 ...\033[0m" %throttle_flag) 試す: 子.wait() を除外する: 子.終了() #クリーン ghost_name_list = '_%s_ghc,_%s_gho' %(options.tablename,options.tablename) drop_ghost_table(接続、ゴースト名リスト) os.path.exists(gh_ost_socket) が存在する場合: os.system('rm -r %s' %gh_ost_socket) print ("\033[0;32m%s\033[0m" % "クリーニングが完了しました...") 出口() print ("\033[0;32m%s\033[0m" % "クリーニングが完了しました...") 出口() ついに : 合格 走る: ルート@test2:~# python gh-ost.py -P3306 -Dtest -Tzjy テーブル数: 1310720 DDL CMDを入力してください: ADD COLUMN q1 varchar(10), ADD COLUMN q2 varchar(10) 最大スレッド数【25】を入力してください: 10 最大チャンクサイズ【1000】を入力してください: 200 gh-ost ddl ... /usr/bin/gh-ost --user="root" --password="root" --host=192.168.163.131 --port=3306 --database="test" --table="zjy" --allow-on-master --max-load='Threads_running=10' --chunk-size=200 --serve-socket-file=/tmp/gh-ost.test.zjy.sock --panic-flag-file=/tmp/gh-ost.panic.test.zjy.flag --throttle-additional-flag-file=/tmp/gh-ost.throttle.test.zjy --alter="ADD COLUMN q1 varchar(10),ADD COLUMN q2 varchar(10)" --execute gh-ost の PID: 2105 作成: [touch /tmp/gh-ost.throttle.test.zjy] ファイル、DDL を一時停止... 2018/06/17 14:37:37 binlogsyncer.go:79: [info] 設定 {99999 mysql 192.168.163.131 3306 root false false <nil>} で BinlogSyncer を作成 2018/06/17 14:37:37 binlogsyncer.go:246: [info] 位置 (mysql-bin.000013, 31197930) から binlog の同期を開始します 2018/06/17 14:37:37 binlogsyncer.go:139: [info] マスターサーバー 192.168.163.131:3306 のスレーブを登録 2018/06/17 14:37:37 binlogsyncer.go:573: [情報] (mysql-bin.000013, 31197930) に回転 # `test`.`zjy` を移行しています。ゴースト テーブルは `test`.`_zjy_gho` です。 # test2:3306 を移行中; test2:3306 を検査中; test2 で実行中 # 移行は 2018 年 6 月 17 日日曜日 14:37:37 +0800 に開始されました # チャンクサイズ: 200; 最大ラグミリ秒: 1500ms; dml バッチサイズ: 10; 最大負荷: Threads_running=10; クリティカル負荷: ; ナイス比: 0.000000 # スロットル追加フラグファイル: /tmp/gh-ost.throttle.test.zjy # パニックフラグファイル: /tmp/gh-ost.panic.test.zjy.flag # Unix ソケットで提供: /tmp/gh-ost.test.zjy.sock コピー: 0/1305600 0.0%; 適用済み: 0; バックログ: 0/1000; 時間: 0 秒 (合計)、0 秒 (コピー); ストリーマー: mysql-bin.000013:31199542; 状態: 移行中; ETA: N/A コピー: 0/1305600 0.0%; 適用済み: 0; バックログ: 0/1000; 時間: 1 秒 (合計)、1 秒 (コピー); ストリーマー: mysql-bin.000013:31202866; 状態: 移行中; ETA: N/A コピー: 44400/1305600 3.4%; 適用済み: 0; バックログ: 0/1000; 時間: 2 秒 (合計)、2 秒 (コピー); ストリーマー: mysql-bin.000013:33352548; 状態: 移行中; ETA: 56 秒 コピー: 91200/1305600 7.0%; 適用済み: 0; バックログ: 0/1000; 時間: 3 秒 (合計)、3 秒 (コピー); ストリーマー: mysql-bin.000013:35598132; 状態: 移行中; ETA: 39 秒 コピー: 135200/1305600 10.4%; 適用済み: 0; バックログ: 0/1000; 時間: 4 秒 (合計)、4 秒 (コピー); ストリーマー: mysql-bin.000013:37727925; 状態: 移行中; ETA: 34 秒 コピー: 174000/1305600 13.3%; 適用済み: 0; バックログ: 0/1000; 時間: 5 秒 (合計)、5 秒 (コピー); ストリーマー: mysql-bin.000013:39588956; 状態: 移行中; ETA: 32 秒 コピー: 212200/1305600 16.3%; 適用済み: 0; バックログ: 0/1000; 時間: 6 秒 (合計)、6 秒 (コピー); ストリーマー: mysql-bin.000013:41430090; 状態: 移行中; ETA: 30 秒 コピー: 254800/1305600 19.5%; 適用済み: 0; バックログ: 0/1000; 時間: 7 秒 (合計)、7 秒 (コピー); ストリーマー: mysql-bin.000013:43483555; 状態: 移行中; ETA: 28 秒 コピー: 303600/1305600 23.3%; 適用済み: 0; バックログ: 0/1000; 時間: 8 秒 (合計)、8 秒 (コピー); ストリーマー: mysql-bin.000013:45834978; 状態: 移行中; ETA: 26 秒 コピー: 351200/1305600 26.9%; 適用済み: 0; バックログ: 0/1000; 時間: 9 秒 (合計)、9 秒 (コピー); ストリーマー: mysql-bin.000013:48128675; 状態: 移行中; ETA: 24 秒 コピー: 401400/1305600 30.7%; 適用済み: 0; バックログ: 0/1000; 時間: 10 秒 (合計)、10 秒 (コピー); ストリーマー: mysql-bin.000013:50547454; 状態: 移行中; ETA: 22 秒 コピー: 451200/1305600 34.6%; 適用済み: 0; バックログ: 0/1000; 時間: 11 秒 (合計)、11 秒 (コピー); ストリーマー: mysql-bin.000013:52946991; 状態: 移行中; ETA: 20 秒 コピー: 490000/1305600 37.5%; 適用済み: 0; バックログ: 0/1000; 時間: 12 秒 (合計)、12 秒 (コピー); ストリーマー: mysql-bin.000013:54817320; 状態: 移行中; ETA: 19 秒 コピー: 529600/1305600 40.6%; 適用済み: 0; バックログ: 0/1000; 時間: 13 秒 (合計)、13 秒 (コピー); ストリーマー: mysql-bin.000013:56735431; 状態: 移行中; ETA: 19 秒 コピー: 589200/1305600 45.1%; 適用済み: 0; バックログ: 0/1000; 時間: 14 秒 (合計)、14 秒 (コピー); ストリーマー: mysql-bin.000013:59606450; 状態: 移行中; ETA: 17 秒 コピー: 639400/1305600 49.0%; 適用済み: 0; バックログ: 0/1000; 時間: 15 秒 (合計)、15 秒 (コピー); ストリーマー: mysql-bin.000013:62025561; 状態: 移行中; ETA: 15 秒 コピー: 695200/1305600 53.2%; 適用済み: 0; バックログ: 0/1000; 時間: 16 秒 (合計)、16 秒 (コピー); ストリーマー: mysql-bin.000013:64704138; 状態: 移行中; ETA: 14 秒 コピー: 751200/1305600 57.5%; 適用済み: 0; バックログ: 0/1000; 時間: 17 秒 (合計)、17 秒 (コピー); ストリーマー: mysql-bin.000013:67401961; 状態: 移行中; ETA: 12 秒 コピー: 803800/1305600 61.6%; 適用済み: 0; バックログ: 0/1000; 時間: 18 秒 (合計)、18 秒 (コピー); ストリーマー: mysql-bin.000013:69935884; 状態: 移行中; ETA: 11 秒 コピー: 856400/1305600 65.6%; 適用済み: 0; バックログ: 0/1000; 時間: 19 秒 (合計)、19 秒 (コピー); ストリーマー: mysql-bin.000013:72470455; 状態: 移行中; ETA: 9 秒 コピー: 907400/1305600 69.5%; 適用済み: 0; バックログ: 0/1000; 時間: 20 秒 (合計)、20 秒 (コピー); ストリーマー: mysql-bin.000013:74927401; 状態: 移行中; ETA: 8 秒 コピー: 958800/1305600 73.4%; 適用済み: 0; バックログ: 0/1000; 時間: 21 秒 (合計)、21 秒 (コピー); ストリーマー: mysql-bin.000013:77404243; 状態: 移行中; ETA: 7 秒 コピー: 999200/1305600 76.5%; 適用済み: 0; バックログ: 0/1000; 時間: 22 秒 (合計)、22 秒 (コピー); ストリーマー: mysql-bin.000013:79351223; 状態: 移行中; ETA: 6 秒 コピー: 1009600/1305600 77.3%; 適用済み: 0; バックログ: 0/1000; 時間: 23 秒 (合計)、23 秒 (コピー); ストリーマー: mysql-bin.000013:79855229; 状態: 移行中; ETA: 6 秒 コピー: 1059600/1305600 81.2%; 適用済み: 0; バックログ: 0/1000; 時間: 24 秒 (合計)、24 秒 (コピー); ストリーマー: mysql-bin.000013:82264712; 状態: 移行中; ETA: 5 秒 コピー: 1107200/1305600 84.8%; 適用済み: 0; バックログ: 0/1000; 時間: 25 秒 (合計)、25 秒 (コピー); ストリーマー: mysql-bin.000013:84558411; 状態: 移行中; ETA: 4 秒 コピー: 1147000/1305600 87.9%; 適用済み: 0; バックログ: 0/1000; 時間: 26 秒 (合計)、26 秒 (コピー); ストリーマー: mysql-bin.000013:86486148; 状態: 移行中; ETA: 3 秒 コピー: 1198000/1305600 91.8%; 適用済み: 0; バックログ: 0/1000; 時間: 27 秒 (合計)、27 秒 (コピー); ストリーマー: mysql-bin.000013:88943747; 状態: 移行中; ETA: 2 秒 コピー: 1245400/1305600 95.4%; 適用済み: 0; バックログ: 0/1000; 時間: 28 秒 (合計)、28 秒 (コピー); ストリーマー: mysql-bin.000013:91218202; 状態: 移行中; ETA: 1 秒 コピー: 1286600/1305600 98.5%; 適用済み: 0; バックログ: 0/1000; 時間: 29 秒 (合計)、29 秒 (コピー); ストリーマー: mysql-bin.000013:93203991; 状態: 移行中; ETA: 0 秒 コピー: 1310720/1310720 100.0%; 適用済み: 0; バックログ: 0/1000; 時間: 29 秒 (合計)、29 秒 (コピー); ストリーマー: mysql-bin.000013:94366846; 状態: 移行中; ETA: 予定 コピー: 1310720/1310720 100.0%; 適用済み: 0; バックログ: 1/1000; 時間: 30 秒 (合計)、29 秒 (コピー); ストリーマー: mysql-bin.000013:94369042; 状態: 移行中; ETA: 予定 # `test`.`zjy` を移行しています。ゴースト テーブルは `test`.`_zjy_gho` です。 # test2:3306 を移行中; test2:3306 を検査中; test2 で実行中 # 移行は 2018 年 6 月 17 日日曜日 14:37:37 +0800 に開始されました # チャンクサイズ: 200; 最大ラグミリ秒: 1500ms; dml バッチサイズ: 10; 最大負荷: Threads_running=10; クリティカル負荷: ; ナイス比: 0.000000 # スロットル追加フラグファイル: /tmp/gh-ost.throttle.test.zjy # パニックフラグファイル: /tmp/gh-ost.panic.test.zjy.flag # Unix ソケットで提供: /tmp/gh-ost.test.zjy.sock コピー: 1310720/1310720 100.0%; 適用済み: 0; バックログ: 0/1000; 時間: 30 秒 (合計)、29 秒 (コピー); ストリーマー: mysql-bin.000013:94371928; 状態: 移行中; ETA: 予定 2018/06/17 14:38:08 binlogsyncer.go:107: [info] syncer を終了しています... 2018/06/17 14:38:08 binlogstreamer.go:47: [エラー] 同期を終了しました。エラー: 同期が終了しています... (ここでのエラーは使用には影響しません。同期は繰り返し終了しており、作者が修正するのを待っています) 2018/06/17 14:38:08 binlogsyncer.go:122: [情報] syncer は閉じられています # 終わり 要約: gh-ost はトリガーを放棄し、同期に binlog を使用します。偽のスレーブ データベースとして、gh-ost はマスター/スレーブ データベースからバイナリ ログを取得し、フィルター処理して、マスター データベースに再適用できます。これは、バイナリ ログを介してマスター データベースの増分操作をマスター データベース自体に適用することと同じですが、ゴースト テーブルに適用されます。 gh-ost は最初にマスターに接続し、alter ステートメントに基づいてゴースト テーブルを作成し、次に実際のスレーブの 1 つに「スレーブ」として接続し、マスター上の既存のデータをゴースト テーブルにコピーし、スレーブから増分データの binlog を取得して、binlog をマスターに継続的に適用します。図のカットオーバーは最後のステップで、マスター データベースのソース テーブルをロックし、binlog が適用されるまで待機してから、gh-ost テーブルをソース テーブルに置き換えます。実行中、gh-ost は、プロセス全体の進行を制御したり、ステータスを検出したりするために、次のヒントとハートビート パケットを元の binlog イベントに追加します。このアーキテクチャには、次のような多くの利点があります。
以下もご興味があるかもしれません:
|
<<: CentOS8 jdk8 / java8 のインストールチュートリアル(推奨)
>>: React 高階コンポーネント HOC 使用方法の概要
Linux の seq コマンドは、数字のリストを非常に高速に生成でき、使いやすく柔軟性に優れてい...
ローカルでコンテナを作成した後、このコンテナに基づいてローカル イメージを作成し、このイメージを D...
序文:データベースを日常的に使用すると、パスワードが単純すぎて変更する必要がある場合、パスワードの有...
1. Dockerネットワークカードを作成する [root@i ~]# brctl addbr d...
ステップ 1: yum install httpd -y #httpd サービスをインストールします...
目次序文VMware クローン仮想マシン (準備、3 台の仮想マシンのクローン、1 台のマスター、2...
前面に書かれたWeibo コンポーネントは、サードパーティのアクセス ユーザーが開発を必要とせずに ...
監視ホストの追加ホスト 192.168.179.104 が zabbix 監視項目に追加されます (...
ページディレクトリ構造 デフォルトの HTML テンプレート ファイル public/index.h...
ここにmysqlドライバmysql.data.dllがあります知らせ:ここではX86バージョンが多く...
目次1. 基本2. ノード、ツリー、仮想DOM 1. 仮想DOM 3. createElementパ...
遅いログクエリ機能スロー ログ クエリの主な機能は、設定された時間しきい値を超える SQL ステート...
jQueryプラグインは、参考のためにダッシュボードを実装します。具体的な内容は次のとおりです。一般...
勉強や仕事で FTP サーバーを頻繁に使用する場合は、起動時に自動的に起動するように設定できます。設...
1. モバイル端末がリストスライドを処理するとき、WeChat には下部にページに戻るボタンが組み...