Online schema change in mysql casual #1(2010/12/11)
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 1,634 views

 

Statistics

Views

Total Views
1,634
Views on SlideShare
1,634
Embed Views
0

Actions

Likes
1
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • MySQL::ChangeSchema で使っている SQL を抜粋して説明します。

Online schema change in mysql casual #1(2010/12/11) Online schema change in mysql casual #1(2010/12/11) Presentation Transcript

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