Around the World

すとぶろ

pt-online-schema-changeを安全につかう

この記事はMySQL Casual Advent Calendar 2014CyberAgent エンジニア Advent Calendar 2014の19日目の記事です。

この間のMySQL Casual Talks vol.7でも少し触れていますが、pt-online-schema-changeには安全につかうための便利なオプションが用意されています。これらのオプションを利用すれば初めてでも石橋を叩きながら実行することができます。ちなみに5.6の人はOnline DDLを使ってください。

スレッド数を監視する

--max-load

pt-oscはスレッド数を監視しながら動作を制御することができます。--max-loadのデフォルトは25で、それを超えた場合は下記のようなメッセージを出して一時停止します。

(略)
Copying `db_name`.`tbl_name`:  17% 35:45 remain
Pausing because Threads_running=44.
Copying `db_name`.`tbl_name`:  17% 40:58 remain
(略)

負荷状態に余裕があれば--max-load Threads_running=100のように値を指定することで一時停止せずに続行することができます。

--critical-load

--max-loadと似ていますが、こちらはデフォルト値は50でこれを超えた場合はpt-oscが終了します。

(略)
2014-06-10T17:11:10 Dropping triggers...
2014-06-10T17:11:10 Dropped triggers OK.
2014-06-10T17:11:10 Dropping new table...
2014-06-10T17:11:13 Dropped new table OK.
`db_name`.`tbl_name` was not altered.
2014-06-10T17:11:10 Error copying rows from `db_name`.`tbl_name` to `db_name`.`_tbl_name_new`: Threads_running=50 exceeds its critical threshold 50

これらの値をDBの負荷に応じてあらかじめ指定することでそれ以上の負荷をかけるといった心配が薄れます。

レプリケーション遅延を監視する

pt-oscはデフォルトでスレーブのレプリケーション遅延の状態を監視しながら実行できます。ただ、マスターとスレーブで同じ権限を持っていない場合があるため、例えばrootユーザで実行すると以下のようなメッセージが出るかもしれません。

$ pt-online-schema-change --execute --alter="(略)" h=localhost,D=db_name,t=tbl_name,u=root
Cannot connect to D=db_name,h=192.168.0.1,u=root
Cannot connect to D=db_name,h=192.168.0.2,u=root
No slaves found.  See --recursion-method if host db_master has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.

この場合はマスターからスレーブ郡へ同じユーザ権限を与えると以下のようにレプリ遅延を監視することができます。

$ pt-online-schema-change --execute --alter="(略)" h=localhost,D=db_name,t=tbl_name,u=osc_user,p=osc_pass
Found 2 slaves:
  db_slave
  db_backup
Will check slave lag on:
  db_slave
  db_backup

--check-slave-lag

ユーザ権限を与えればprocesslistを見てレプリケーションしているスレーブ全台の遅延状況を確認しながら実行できますが、例えばバックアップサーバがスレーブよりスペックが劣っていて、遅延は許容できる状況などがあると思います。その場合は--check-slave-lagで1台のみ監視対象にすることができます。

$ pt-online-schema-change --execute --alter="(略)" h=localhost,D=db_name,t=tbl_name,u=osc_user,p=osc_pass --check-slave-lag h=192.168.0.1,u=osc_user,p=osc_pass
Found 2 slaves:
  db_slave
  db_backup
Will check slave lag on:
  db_slave
(略)

また、これを利用することでマスターとスレーブで同じユーザ権限がない場合でも、レプリ遅延を監視することができます。

--max-lag

レプリ遅延のしきい値を設定でき、デフォルトは1です。超えると一時停止しそれ以上の遅延を防止することができます。Seconds_Behind_Masterを見ているので許容できる範囲の秒数を指定することができます。

--check-interval

--max-lagをチェックをする間隔で、デフォルトは1秒です。

その他

--dry-run

pt-oscを実行する場合は--dry-run--executeのどちらかを必ずオプションに指定します。 まずは--dry-runで確認しましょう。

$ pt-online-schema-change --dry-run --alter="engine=InnoDB" h=localhost,D=db_name,t=tbl_name,u=root
Operation, tries, wait:
  copy_rows, 10, 0.25
  create_triggers, 10, 1
  drop_triggers, 10, 1
  swap_tables, 10, 1
  update_foreign_keys, 10, 1
Starting a dry run.  `db_name`.`tbl_name` will not be altered.  Specify --execute instead of --dry-run to alter the table.
Creating new table...
Created new table db_name._tbl_name_new OK.
Altering new table...
Altered `db_name`.`_tbl_name_new` OK.
Not creating triggers because this is a dry run.
Not copying rows because this is a dry run.
Not swapping tables because this is a dry run.
Not dropping old table because this is a dry run.
Not dropping triggers because this is a dry run.
2014-12-18T17:01:26 Dropping new table...
2014-12-18T17:01:26 Dropped new table OK.
Dry run complete.  `db_name`.`tbl_name` was not altered.

--nodrop-old-table

pt-oscは新しいテーブルに変更内容を適用し、リネームしてから既存のテーブルを削除する仕組みですが、これを指定すると既存のテーブルが_tbl_name_oldとして残ります。万が一のためだったり、テストする場合などに利用できるでしょう。

通常時
(略)
2014-12-18T16:53:18 Dropping old table...
2014-12-18T16:53:18 Dropped old table `db_name`.`_tbl_name_old` OK.
(略)
オプション指定時
(略)
Not dropping old table because --no-drop-old-table was specified.
(略)

--progress

デフォルトは30秒ごとの進捗(time,30)を表示しますが、30秒では心配なときに利用します。値はtime,percentageなどが利用できます。

$ pt-online-schema-change --execute --progress=time,1 --alter="(略)" h=localhost,D=db_name,t=tbl_name,u=ptosc,p=ptosc
Found 2 slaves:
  db_slave
  db_backup
Will check slave lag on:
  db_slave
  db_backup
Operation, tries, wait:
  copy_rows, 10, 0.25
  create_triggers, 10, 1
  drop_triggers, 10, 1
  swap_tables, 10, 1
  update_foreign_keys, 10, 1
Altering `db_name`.`tbl_name`...
Creating new table...
Created new table db_name._tbl_name_new OK.
Waiting forever for new table `db_name`.`_tbl_name_new` to replicate to db_master...
Altering new table...
Altered `db_name`.`_tbl_name_new` OK.
2014-12-18T23:43:43 Creating triggers...
2014-12-18T23:43:43 Created triggers OK.
2014-12-18T23:43:43 Copying approximately 1591002 rows...
Copying `db_name`.`tbl_name`:   1% 01:20 remain
Copying `db_name`.`tbl_name`:   7% 00:24 remain
Copying `db_name`.`tbl_name`:  12% 00:20 remain
Copying `db_name`.`tbl_name`:  18% 00:17 remain
Copying `db_name`.`tbl_name`:  23% 00:16 remain
Copying `db_name`.`tbl_name`:  29% 00:14 remain
Copying `db_name`.`tbl_name`:  34% 00:13 remain
Copying `db_name`.`tbl_name`:  39% 00:12 remain
Copying `db_name`.`tbl_name`:  45% 00:10 remain
Copying `db_name`.`tbl_name`:  48% 00:10 remain
Copying `db_name`.`tbl_name`:  53% 00:09 remain
Copying `db_name`.`tbl_name`:  58% 00:08 remain
Copying `db_name`.`tbl_name`:  64% 00:07 remain
Copying `db_name`.`tbl_name`:  69% 00:06 remain
Copying `db_name`.`tbl_name`:  75% 00:04 remain
Copying `db_name`.`tbl_name`:  80% 00:03 remain
Copying `db_name`.`tbl_name`:  85% 00:02 remain
Copying `db_name`.`tbl_name`:  91% 00:01 remain
Copying `db_name`.`tbl_name`:  96% 00:00 remain
2014-12-18T23:44:03 Copied rows OK.
2014-12-18T23:44:03 Swapping tables...
2014-12-18T23:44:03 Swapped original and new tables OK.
2014-12-18T23:44:03 Dropping old table...
2014-12-18T23:44:04 Dropped old table `db_name`.`_tbl_name_old` OK.
2014-12-18T23:44:04 Dropping triggers...
2014-12-18T23:44:04 Dropped triggers OK.
Successfully altered `db_name`.`tbl_name`.

まとめ

オンラインでの実行が前提だけあってセーフティなオプションがいろいろあります。 これらを利用すれば、本番のDBで実行する恐怖が少しは薄れるかなと思います。 ただし、ピーク帯の実行は極力控えましょう!