pt-online-schema-changeによる負荷を好きなメトリクスでコントロールする

こんにちは、id:shallow1729です。この記事はMySQL Advent Calendar 202119日目のものです。昨日はid:next4us-tiさんでMySQL8.0を再起動するとアプリからつながらなくなる理由でした。インターネットって情報はたくさんあるけど分かってないと検索できないケースが多いと思っていて、ユーザーの立場に立って記事を書いているというのが伝わってすごくいいなと思いました。僕も会社のMySQlを8系にする時のトラブルシューティングをうまくやるために参考にしようと思います。

今回はpt-online-schema-changeを自分向けに改造した話です。

pt-online-schema-change(pt-osc)

pt-oscはカラムのデータ型の変更のようなオンラインDDLが使えないalter tableをオンラインで行いたいケースなどに使えるツールです。このMySQL advent calenderでもpt-online-schema-changeとgh-ostの比較(データが損失するかもしれないAlterTable編)id:kenken0807さんが話題にしているようにデータベース屋さんの間だと結構有名なツールだと思います。

pt-osc自体の解説は特にしませんが基本的な挙動としては以下のイメージです。

  1. alter table後のテーブル定義の新しいテーブルを作成
  2. 元のテーブルのレコードを新しいテーブルにコピー、この間に起きる元のテーブルへのinsertやupdateはtriggerで拾う
  3. 新しいテーブルの名前をコピー元のテーブル名にrenameする事で新しいテーブル定義への変更を完了する

alter table済みのコピーを作成してrenameで入れ替えるという感じですね。

pt-oscの負荷の制御の仕組みの改造

先ほどの動作の説明で出たレコードのコピーについては当然負荷がかかるのでpt-oscは--max-loadというオプションでMySQLの状態を見て負荷が高そうならコピーを止めるという事をやってくれるのですが、SHOW GLOBAL STATUSで取得できるものしかサポートされておらず、インスタンスのCPU使用率のような負荷状況の監視に用いるようなメトリクスでの制御はできませんでした。実際pt-oscのデフォルトはThreads_running(sleepでないスレッド数)を見ながらコピーの頻度を制御するのですが、アクセスのほとんどない検証環境で動かしてみるとCPU使用率が100%に張り付いてしまいました。まあ本番ならいっぱいアクセスあるだろうし大丈夫かな?と思いつつも制御できるなら制御したいと思って制御できるようにコードを変更したものが以下です。

github.com

$varが--max-loadで渡した値のメトリクス名のようなので、この値で分岐して独自のメトリクス取得方法を実装した感じです。僕のサンプルだとcpuutilizationというのを--max-loadで指定できるようにして、AWSのcloudwatch metricsで取得したRDSのCPU使用率が指定した値を上回るとコピーを止める事ができるようにしています。 一応実際に軽く動かしてみてCPU使用率が--max-loadで渡した値を下回るまではコピーが進まない事の確認はしましたが、本番での活用は自己責任でお願いします。

$ DB_INSTANCE=database-1 pt-online-schema-change --alter "add column c1 int" D=test,t=sample  --password testtest --user root --host localhost --execute --max-load cpuutilization=7 --chunk-size 10
No slaves found.  See --recursion-method if host ip-172-31-37-79.ap-northeast-1.compute.internal has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
cpu utilization is 7.33333333333334
Operation, tries, wait:
  analyze_table, 10, 1
  copy_rows, 10, 0.25
  create_triggers, 10, 1
  drop_triggers, 10, 1
  swap_tables, 10, 1
  update_foreign_keys, 10, 1
Altering `test`.`sample`...
Creating new table...
Created new table test.____sample_new OK.
Altering new table...
Altered `test`.`____sample_new` OK.
2021-12-16T10:46:28 Creating triggers...
2021-12-16T10:46:28 Created triggers OK.
2021-12-16T10:46:28 Copying approximately 15 rows...
cpu utilization is 7.33333333333334
Pausing because cpuutilization=7.33333333333334.
cpu utilization is 7.33333333333334
...
cpu utilization is 7.33333333333334
Pausing because cpuutilization=7.33333333333334.
cpu utilization is 7.33333333333334
cpu utilization is 6.39344262295083
2021-12-16T10:48:01 Copied rows OK.
2021-12-16T10:48:01 Analyzing new table...
2021-12-16T10:48:01 Swapping tables...
2021-12-16T10:48:01 Swapped original and new tables OK.
2021-12-16T10:48:01 Dropping old table...
2021-12-16T10:48:02 Dropped old table `test`.`_sample_old` OK.
2021-12-16T10:48:02 Dropping triggers...
2021-12-16T10:48:02 Dropped triggers OK.
Successfully altered `test`.`sample`.

最後に

以上です。percona toolkitはGPL2.0で、コードを変更して公開する分には問題ないはずだと思っていますが何か問題あれば教えてください。

明日はyy_hrachiさんです!おたのしみに〜