GA

2024/12/24

gh-ostの-postpone-cut-over-flag-fileみたいなことをpt-oscでもやりたい

この記事は MySQL Advent Calendar 2024 の24日目の記事です。

昨日は updraftさん今日は、MySQL 8.0.35で非推奨になった「SHOW PROCESSLIST」の代わりのパフォーマンススキーマを見てみるの日。 - 今日はなにの日。 でした。


最近、ALTER TABLEのメタデータロックの競合がちょっと話題に上がっていました(ので便乗して今年書いたスライドを載せておきます)

それでちょっと思い出したんですが、 gh-ostpt-online-schema-change (以下、pt-osc) とメタデータロックを比較するとこんな感じになります。

type 開始時排他MDL 終了時排他MDL
ネイティブALTER TABLE(ALGORITHM=INPLACE) 取る 取る
ネイティブALTER TABLE(ALGORITHM=INSTANT) 取る 取らない
gh-ost 取らない 取る
pt-osc 3回取る 取る

pt-oscの仕組み的にトリガーを使うので、 CREATE TRIGGER のぶんだけ (INSERT Trigger, Update Trigger, Delete Triggerがそれぞれ同時に作れないので計3回) 排他MDLが必要になります。

で、ネイティブALTER TABLEにせよgh-ost, pt-oscにせよ

があって、開始時のMDLは「まあCtrl+Cですぐ中断できるし lock_wait_timeout でAbortさせても良い」んですが終了時のMDLは「終わる時間が完全には読みにくい」とか「終わる時間が深夜になると無理」とか「ここでタイムアウトしちゃうと作業が最初からやり直し」とかがあります。

gh-ostは(おそらく作ってる人たちがそもそもこの悩みを抱えていて) -postpone-cut-over-flag-file というのがあって、この「終了処理で排他MDLを取らないといけないステップをファイルの存在で遅延させる」仕組みがあります。

たとえば -postpone-cut-over-flag-file /tmp/flag とかやっておくと、 /tmp/flag がある間は終了処理に入らない(gh-ostを起動した時点でファイルは勝手に作られる)ので、ピークタイムを避けてゆっくり余裕がありそうな時間に rm /tmp/flag で排他MDLの処理を実行させることができます。

対して、pt-oscにはデフォルトでこの機能はない ( —pause-file だとカットオーバー以外の INSERT IGNORE INTO .. の部分も止まってしまう) ので、自分で --plugin で使える Perlスクリプト を書いてフックしてやる必要があります。

pt-oscのドキュメントにも書いてあるんですがこの形の方が人に説明しやすかったので前に書いたものがこちらです。

https://github.com/yoku0825/pt-osc-plugin/blob/main/pt-osc-plugin.pl

init(pt-osc起動時に呼ばれるフック)でフラグファイルを作ってあげて

sub init
{
  my ($self, %args)= @_;
  _logger(DEBUG, "start init");
  open(my $flag_file, ">", "/tmp/flag");
  close($flag_file);
  _logger(DEBUG, "finish init");
}

before_swap_tables(排他MDLが必要になる処理の直前)でフラグファイルをチェックしてあげれば

sub before_swap_tables
{
  my ($self, %args)= @_;
  _logger(DEBUG, "start before_swap_tables");

  while (-e "/tmp/flag")
  {
    _logger(INFO, "flag file does not exist, sleepling..");
    sleep 5;
  }

  _logger(DEBUG, "finish before_swap_tables");
}

↓pt-oscの終了(するときの排他MDL)のタイミングを調整できます。

$ PLUGIN_LOG_LEVEL=9 pt-online-schema-change --user=root --socket=/usr/mysql/8.0.40/data/mysql.sock --alter "Engine = InnoDB" D=d1
,t=t1 --execute --plugin=/tmp/pt-osc.pl

..
start after_copy_rows at pt_online_schema_change::main
finish after_copy_rows at pt_online_schema_change::main
start before_swap_tables at pt_online_schema_change::main
flag file does not exist, sleepling.. at pt_online_schema_change::main
flag file does not exist, sleepling.. at pt_online_schema_change::main
flag file does not exist, sleepling.. at pt_online_schema_change::main

「pt-oscは終了時の排他MDLが制御できなくて…」という時に試してみてください。

明日は zoosm3さん です!

0 件のコメント :

コメントを投稿