online schema change in mysql casual #1(2010/12/11)

32
Online Schema Change in mysql casual

Upload: naritoshi-hayashi

Post on 12-Jun-2015

1.447 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Online schema change in mysql casual #1(2010/12/11)

Online Schema Change

in mysql casual

Page 2: Online schema change in mysql casual #1(2010/12/11)

自己紹介

• 名前:林 成敏(はやし なりとし)• ID : nhayashi || n_hayashi• 所属: DeNA

Page 3: Online schema change in mysql casual #1(2010/12/11)

今回の発表

• Online Schema Change• Facebook で使われている(らしい)• 元は PHP で実装• 今回、 perl で実装してみました

Page 4: Online schema change in mysql casual #1(2010/12/11)

テーブルスキーマ変更方法

• サービスを止めてメンテナンス中に実行• 新しいテーブルスキーマを別テーブルに用意してアプリで

ダブルインサートして rename で切り替える• 諦める

Page 5: Online schema change in mysql casual #1(2010/12/11)

問題点(サービス止めない場合)

• 気軽に ALTER 文を打つとテーブルロックがかかる• アプリ側の対応が必要で大変• どこまで更新処理をしたか既存データ移行後に全部追う必

要があり整合性の確認が大変

Page 6: Online schema change in mysql casual #1(2010/12/11)

こうできれば幸せ

• サービス止めなくていい• エラー出さずによしなに更新してくれる• アプリ側の対応はなし• 当然、データの整合性は維持

Page 7: Online schema change in mysql casual #1(2010/12/11)

MySQL::ChangeSchema で幸せになろう

• github にあがってます• URL はのちほど

Page 8: Online schema change in mysql casual #1(2010/12/11)

使い方

use MySQL::ChangeSchema;my $osc = MySQL::ChangeSchema->new(    db    => "test",    table => "test2",    user  => "root",    pass  => "root",);$osc->connect();$osc->init();$osc->cleanup();eval {    $osc->execute("ALTER TABLE test2 MODIFY hoge varchar(512)");};if ($@) {    print $@."\n";    $osc->cleanup;}

Page 9: Online schema change in mysql casual #1(2010/12/11)

データフロー

Page 10: Online schema change in mysql casual #1(2010/12/11)

前置き

• いくつか条件付きでほぼ正常に動作します。• たぶん適材適所で使うべき

Page 11: Online schema change in mysql casual #1(2010/12/11)

必要条件

• Primary key が定義されている• Foreign key が設定されていない• after insert/delete/update trigger が設定されていない• InnoDB のみサポート• 後方互換のある ALTER 文のみ• レプリ構成の場合は カラムの ADD/DROP はレプリが止ま

る • ( Disk I/O 等の性能に関しては考慮してません)

Page 12: Online schema change in mysql casual #1(2010/12/11)

実行条件

• MySQL 稼働サーバで実行• master/slave それぞれで実行 • /var/lib/mysql への書き込み権限が必要• Alter/Lock_tables/Repl_*/Trigger 権限が必要 • MySQL::ChangeSchema が入っていること w

Page 13: Online schema change in mysql casual #1(2010/12/11)

実行時の TIPS

• local $MySQL::ChangeSchema::VERBOSE = 1;o 実行 SQL すべてが出力されます。

Page 14: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ スナップショット

• START TRANSACTION WITH CONSISTENT SNAPSHOT;o セッション内において分離レベルを変更せず、

コマンド発行時点のデータ状態を保持。

Page 15: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ テーブルロック

• LOCK TABLE t1 WRITE;o t1 テーブルへの更新をロックする。o ロック中の更新処理は Lock Wait 状態になる。

• UNLOCK TABLES;o ロックしているテーブルを開放する。

Page 16: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ アプリケーションロック

• SELECT get_lock('osc_lock', 0);o ロックを取得 o 0 はロック待ちしない

• SELECT is_free_lock('osc_lock');o ロックが取得できるか確認

• do release_lock('osc_lock');o ロックを開放

Page 17: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ バイナリログ、トランザクション• SET sql_log_bin = 0;

o セッション内でバイナリログ出力を抑止• SET session autocommit = [0|1]; 

o セッション内でトランザクション有効 / 無効

Page 18: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ テーブル作成

• CREATE TABLE t2 LIKE t1;o primary key, index 含めた t1 テーブルと同じスキーマを作

成 • CREATE TABLE t2 (id int) AS (SELECT hoge FROM t1 LIMIT

0);o カラムの型のみ 同じスキーマを作成

Page 19: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ トリガ AFTER INSERT

• CREATE TRIGGER insert_trigger     AFTER INSERT ON t1 FOR EACH ROW     INSERT INTO t2 (dml_type, id, hoge)     VALUES (1, NEW.id, NEW.hoge); 

o t1 テーブルへの insert 後に起動o NEW 変数で t1 テーブルへの insert 後の値を参照 o t2 テーブルへ dml_type, id, hoge を insert

Page 20: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ トリガ AFTER DELETE

• CREATE TRIGGER delete_trigger     AFTER DELETE ON t1 FOR EACH ROW     INSERT INTO t2 (dml_type, id)     VALUES (2, OLD.id);

o t1 テーブルへの delete 後に起動o OLD 変数で t1 テーブルへの delete 前の値を参照o t2 テーブルへ dml_type, id を insert

Page 21: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ トリガ AFTER UPDATE

• CREATE TRIGGER update_trigger     AFTER UPDATE ON t1 FOR EACH ROW      IF (NEW.id=OLD.id) THEN       INSERT INTO t2 (dml_type, id, hoge)       VALUES (3, NEW.id, NEW.hoge);     ELSE       INSERT INTO t2 (dml_type, id, hoge)       VALUES (2, OLD.id, OLD.hoge),              (1, NEW.id, NEW.hoge);     END IF

o t1 テーブルへの update 後に起動o NEW.id=OLD.id なら t2 テーブルへ 1 件 inserto NEW.id!=OLD.id なら t2 テーブルへ 2 件 insert

Page 22: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ ファイル出力

• SELECT id, dml_type FROM t1 ORDER BY id     INTO OUTFILE '/var/lib/mysql/test/t1_file';

o テーブルデータをファイル出力する。

Page 23: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ ファイル入力

• LOAD DATA INFILE '/var/lib/mysql/test/t1_file'     INTO TABLE t1 (id, dml_type);

o 出力したファイルをテーブルに読み込む。

Page 24: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ テンポラリテーブル

• CREATE TEMPORARY TABLE t1 (id int, dml_type int);o セッション内のメモリ上に一時テーブルを作成o 他のセッションからは見えない。o メモリ上にあるので早い

• DROP TEMPORARY TABLE t1;o 一時テーブルを削除

Page 25: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ ユーザ定義変数

• SELECT @range_end := id, hoge FROM t1     ORDER BY id LIMIT 100;

o @range_end -> 100 • SELECT @range_end INTO @range_start;

o @range_end -> 100, @range_start -> 100 • SELECT @range_end := id, hoge FROM t1

     WHERE (id > @range_start)     ORDER BY id LIMIT 100;

o @range_end -> 200, @range_start -> 100 • SELECT @range_end INTO @range_start;  

o @range_end -> 200, @range_start -> 200• 「 := 」を使うと参照と同時にユーザ定義変数を更新

Page 26: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ テーブルデータコピー

• INSERT INTO t2 (id, dml_type)     SELECT id, dml_type FROM t1;

o t1 テーブルのデータを t2 テーブルに insert

Page 27: Online schema change in mysql casual #1(2010/12/11)

SQL 解説 ~ リネームテーブル

• RENAME TABLE old TO tmp, new to old;o old テーブルを new テーブルに置き換える。o ロックされているテーブルがあると実行できないo アクティブなトランザクションがあると実行できないo 名前の変更途中でエラーになるとロールバックする

Page 28: Online schema change in mysql casual #1(2010/12/11)

稼働実績

• なし w• (手元で試した限りではまともに動いてます)

Page 29: Online schema change in mysql casual #1(2010/12/11)

今後の課題

• 使い方が面倒(スクリプト化)• 実行時オプション指定ができるようにする

o Lock 指定やログ出力など • lock table しなくてもいい方法を考える

Page 30: Online schema change in mysql casual #1(2010/12/11)

免責事項

• 本プログラムの使用は各個人の責任において使用してください。

• 万が一、サービス上のデータ等が消滅・改ざんされたとしても当方は一切の責任を負いません。

Page 31: Online schema change in mysql casual #1(2010/12/11)

募集

• 一緒に開発してくれる方、募集してます。     https://github.com/nhayashi/p5-mysql-changeschema

Page 32: Online schema change in mysql casual #1(2010/12/11)

謝辞

ご清聴ありがとうございました m(_ _)m