Skip to content

Instantly share code, notes, and snippets.

@iwazer
Created September 27, 2021 07:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iwazer/e82984c32bf47e705dd58ba82b4dac09 to your computer and use it in GitHub Desktop.
Save iwazer/e82984c32bf47e705dd58ba82b4dac09 to your computer and use it in GitHub Desktop.
MySQLオンラインDDLのWaiting for table metadata lockについて

オンラインDDLのWaiting for table metadata lockについて

(1) トランザクション中に対象のテーブルをSELECT
A: begin;
A: select * from target_table where id=1;

(2) 対象のテーブルにオンラインDDLを実行
B: CREATE INDEX a_target_table_index ON target_table  (field1, field2);

-- show processlist;
-- Waiting for table metadata lock | CREATE INDEX a_target_table_index...

(3) 別のトランザクションで対象のテーブルをSELECT
C: begin;
C: select * from target_table where id=2;

-- Waiting for table metadata lock | CREATE INDEX a_target_table_index...
-- Waiting for table metadata lock | select * from target_table...

(4) Aのトランザクションを終了するとDDLは実行開始
A: rollback;

-- altering table | CREATE INDEX a_target_table_index...

(5) Cのトランザクションをそのまま放置するとほどなく
-- Waiting for table metadata lock | CREATE INDEX a_target_table_index...

(6) Cのトランザクションを終了
C: rollback;

(7) Bは即完了
  • ターゲットのテーブルを参照するトランザクション(A)が開始中はオンラインDDLは開始を待つ
  • Aが終了するとオンラインDDLは開始される
  • オンラインDDLがWaiting for table metadata lockで待っている間に、別のトランザクション(C)が始まる
  • オンラインDDLは終了時にCのトランザクション終了を待つ
  • Cが終了するとオンラインDDLは即完了する

つまり、オンラインDDL開始時に長いAのトランザクションがあった場合、Cにあたるトランザクションが積み重なってシステムが死ぬ可能性がある。

(6)のタイミングでさらに別のトランザクションを追加した場合はオンラインDDLの終了を阻害したりはしない模様。つまりAのトランザクションが実行中の(1)〜(4)間が問題。

回避方法としては、DDLを流してすぐprocesslistをチェックし、 Waiting for table metadata lock になっていたら、killする、というのを altering table になるまで繰り返す、と思われます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment