Online schema change_for_mysql_casual

642 views

Published on

Published in: Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
642
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Online schema change_for_mysql_casual

  1. 1. Online Schema Change in mysql casual
  2. 2. 自己紹介• 名前:林 成敏(はやし なりとし)• ID:nhayashi || n_hayashi• 所属:DeNA
  3. 3. 今回の発表• Online Schema Change• Facebook で使われている(らしい)• 元はPHPで実装• 今回、perl で実装してみました
  4. 4. テーブルスキーマ変更方法• サービスを止めてメンテナンス中に実行• 新しいテーブルスキーマを別テーブルに用意してアプリで ダブルインサートしてrenameで切り替える• 諦める
  5. 5. 問題点(サービス止めない場合)• 気軽にALTER文を打つとテーブルロックがかかる• アプリ側の対応が必要で大変• どこまで更新処理をしたか既存データ移行後に全部追う必 要があり整合性の確認が大変
  6. 6. こうできれば幸せ• サービス止めなくていい• エラー出さずによしなに更新してくれる• アプリ側の対応はなし• 当然、データの整合性は維持
  7. 7. MySQL::ChangeSchemaで幸せになろう• github にあがってます• URL はのちほど
  8. 8. 使い方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;}
  9. 9. データフロー
  10. 10. 前置き• いくつか条件付きでほぼ正常に動作します。• たぶん適材適所で使うべき
  11. 11. 必要条件• Primary key が定義されている• Foreign key が設定されていない• after insert/delete/update trigger が設定されていない• InnoDB のみサポート• 後方互換のある ALTER文のみ• レプリ構成の場合は カラムの ADD/DROP はレプリが止ま る• (Disk I/O 等の性能に関しては考慮してません)
  12. 12. 実行条件• MySQL稼働サーバで実行• master/slave それぞれで実行• /var/lib/mysql への書き込み権限が必要• Alter/Lock_tables/Repl_*/Trigger 権限が必要• MySQL::ChangeSchema が入っていることw
  13. 13. 実行時のTIPS• local $MySQL::ChangeSchema::VERBOSE = 1; o 実行SQLすべてが出力されます。
  14. 14. SQL解説 ~ スナップショット• START TRANSACTION WITH CONSISTENT SNAPSHOT; o セッション内において分離レベルを変更せず、 コマンド発行時点のデータ状態を保持。
  15. 15. SQL解説 ~ テーブルロック• LOCK TABLE t1 WRITE; o t1 テーブルへの更新をロックする。 o ロック中の更新処理は Lock Wait 状態になる。• UNLOCK TABLES; o ロックしているテーブルを開放する。
  16. 16. SQL解説 ~ アプリケーションロック• SELECT get_lock(osc_lock, 0); o ロックを取得 o 0 はロック待ちしない• SELECT is_free_lock(osc_lock); o ロックが取得できるか確認• do release_lock(osc_lock); o ロックを開放
  17. 17. SQL解説 ~ バイナリログ、トランザクション• SET sql_log_bin = 0; o セッション内でバイナリログ出力を抑止• SET session autocommit = [0|1]; o セッション内でトランザクション有効/無効
  18. 18. SQL解説 ~ テーブル作成• CREATE TABLE t2 LIKE t1; o primary key, index 含めた t1 テーブルと同じスキーマを作成• CREATE TABLE t2 (id int) AS (SELECT hoge FROM t1 LIMIT 0); o カラムの型のみ 同じスキーマを作成
  19. 19. 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
  20. 20. 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
  21. 21. 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件 insert o NEW.id!=OLD.id ならt2 テーブルへ 2件 insert
  22. 22. SQL解説 ~ ファイル出力• SELECT id, dml_type FROM t1 ORDER BY id INTO OUTFILE /var/lib/mysql/test/t1_file; o テーブルデータをファイル出力する。
  23. 23. SQL解説 ~ ファイル入力• LOAD DATA INFILE /var/lib/mysql/test/t1_file INTO TABLE t1 (id, dml_type); o 出力したファイルをテーブルに読み込む。
  24. 24. SQL解説 ~ テンポラリテーブル• CREATE TEMPORARY TABLE t1 (id int, dml_type int); o セッション内のメモリ上に一時テーブルを作成 o 他のセッションからは見えない。 o メモリ上にあるので早い• DROP TEMPORARY TABLE t1; o 一時テーブルを削除
  25. 25. 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• 「:=」を使うと参照と同時にユーザ定義変数を更新
  26. 26. SQL解説 ~ テーブルデータコピー• INSERT INTO t2 (id, dml_type) SELECT id, dml_type FROM t1; o t1テーブルのデータを t2 テーブルに insert
  27. 27. SQL解説 ~ リネームテーブル• RENAME TABLE old TO tmp, new to old; o old テーブルを new テーブルに置き換える。 o ロックされているテーブルがあると実行できない o アクティブなトランザクションがあると実行できない o 名前の変更途中でエラーになるとロールバックする
  28. 28. 稼働実績• なしw• (手元で試した限りではまともに動いてます)
  29. 29. 今後の課題• 使い方が面倒(スクリプト化)• 実行時オプション指定ができるようにする o Lock指定やログ出力など• lock table しなくてもいい方法を考える
  30. 30. 免責事項• 本プログラムの使用は各個人の責任において使用してくだ さい。• 万が一、サービス上のデータ等が消滅・改ざんされたとし ても当方は一切の責任を負いません。
  31. 31. 募集• 一緒に開発してくれる方、募集してます。 https://github.com/nhayashi/p5-mysql-changeschema
  32. 32. 謝辞 ご清聴ありがとうございました m(_ _)m

×