online schema change_for_mysql_casual

32
Online Schema Change in mysql casual

Upload: naritoshi-hayashi

Post on 07-Jul-2015

506 views

Category:

Education


4 download

TRANSCRIPT

Page 1: Online schema change_for_mysql_casual

Online Schema Change

in mysql casual

Page 2: Online schema change_for_mysql_casual

自己紹介

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

Page 3: Online schema change_for_mysql_casual

今回の発表

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

Page 4: Online schema change_for_mysql_casual

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

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

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

Page 5: Online schema change_for_mysql_casual

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

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

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

Page 6: Online schema change_for_mysql_casual

こうできれば幸せ

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

Page 7: Online schema change_for_mysql_casual

MySQL::ChangeSchemaで幸せになろう

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

Page 8: Online schema change_for_mysql_casual

使い方

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_for_mysql_casual

データフロー

Page 10: Online schema change_for_mysql_casual

前置き

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

Page 11: Online schema change_for_mysql_casual

必要条件

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

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

Page 12: Online schema change_for_mysql_casual

実行条件

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

Page 13: Online schema change_for_mysql_casual

実行時のTIPS

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

Page 14: Online schema change_for_mysql_casual

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

• START TRANSACTION WITH CONSISTENT SNAPSHOT;o セッション内において分離レベルを変更せず、コマンド発行時点のデータ状態を保持。

Page 15: Online schema change_for_mysql_casual

SQL解説 ~ テーブルロック

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

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

Page 16: Online schema change_for_mysql_casual

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_for_mysql_casual

SQL解説 ~ バイナリログ、トランザクション

• SET sql_log_bin = 0;o セッション内でバイナリログ出力を抑止

• SET session autocommit = [0|1];o セッション内でトランザクション有効/無効

Page 18: Online schema change_for_mysql_casual

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_for_mysql_casual

SQL解説 ~ トリガ AFTER INSERT

• CREATE TRIGGER insert_triggerAFTER INSERT ON t1 FOR EACH ROWINSERT 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_for_mysql_casual

SQL解説 ~ トリガ AFTER DELETE

• CREATE TRIGGER delete_triggerAFTER DELETE ON t1 FOR EACH ROWINSERT 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_for_mysql_casual

SQL解説 ~ トリガ AFTER UPDATE

• CREATE TRIGGER update_triggerAFTER UPDATE ON t1 FOR EACH ROW IF (NEW.id=OLD.id) THENINSERT INTO t2 (dml_type, id, hoge)VALUES (3, NEW.id, NEW.hoge);

ELSEINSERT INTO t2 (dml_type, id, hoge)VALUES (2, OLD.id, OLD.hoge),

(1, NEW.id, NEW.hoge);END IFo t1テーブルへの update 後に起動o NEW.id=OLD.id なら t2 テーブルへ 1件 inserto NEW.id!=OLD.id ならt2 テーブルへ 2件 insert

Page 22: Online schema change_for_mysql_casual

SQL解説 ~ ファイル出力

• SELECT id, dml_type FROM t1 ORDER BY idINTO OUTFILE '/var/lib/mysql/test/t1_file';o テーブルデータをファイル出力する。

Page 23: Online schema change_for_mysql_casual

SQL解説 ~ ファイル入力

• LOAD DATA INFILE '/var/lib/mysql/test/t1_file'INTO TABLE t1 (id, dml_type);o 出力したファイルをテーブルに読み込む。

Page 24: Online schema change_for_mysql_casual

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

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

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

Page 25: Online schema change_for_mysql_casual

SQL解説 ~ ユーザ定義変数

• SELECT @range_end := id, hoge FROM t1ORDER 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 t1WHERE (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_for_mysql_casual

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

• INSERT INTO t2 (id, dml_type)SELECT id, dml_type FROM t1;o t1テーブルのデータを t2 テーブルに insert

Page 27: Online schema change_for_mysql_casual

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

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

Page 28: Online schema change_for_mysql_casual

稼働実績

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

Page 29: Online schema change_for_mysql_casual

今後の課題

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

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

Page 30: Online schema change_for_mysql_casual

免責事項

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

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

Page 31: Online schema change_for_mysql_casual

募集

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

Page 32: Online schema change_for_mysql_casual

謝辞

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