Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

DBスキーマもバージョン管理したい!

43,958 views

Published on

PostgreSQLカンファレンス2013 LightningTalk
(2013-11-13: migr8.rbの設定箇所を若干修正)
(2013-11-14: SQLite3での設定等を修正、「migr8.rb new --table=users」を追加)

Published in: Technology
  • とても参考になるslideの公開ありがとうございます。
    もしかして25ページの' Linquibase'は'Liquibase'ではないでしょうか。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • おっしゃる通りです。修正しましたのでご確認ください。
    ご報告いただきありがとうございます。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 正しくは
    export MIGR8_COMMAND='sqlite3 dbfile'
    でしょうか。
    細かくて申し訳ありませんが、貴重な日本語ドキュメントなので...
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

DBスキーマもバージョン管理したい!

  1. 1. PostgreSQLカンファレンス2013 LightningTalk DBスキーマも バージョン管理したい! —省略してない版— Makoto Kuwata <kwa@kuwata-lab.com> http://www.kuwata-lab.com/ 更新履歴: ・2013-11-13 migr8.rbの設定における若干の間違いを修正 ・2013-11-14 SQLite3での設定等を修正、「migr8.rb new --table=users」を追加
  2. 2. 背景 ✓ ソースコードのバージョン管理は普及してる Git、Mercurial、Subversion、… ✓ 対して、DBスキーマのバージョン管理は… そもそも存在を知らない人が多い
  3. 3. OT: 控え室にて Q: PostgreSQL界隈では、 スキーマのバージョン管理 では何が人気なんですか? A: そんなものはない 達人のお墨付き!! (石井さんごめんなさい)
  4. 4. 発表のゴール ✓ DBスキーマもバージョン管理できることを 知ってもらう ・サンプルその1:Ruby on Rails (DSL派) ・サンプルその2:Migr8.rb    (SQL派) ✓ バージョン管理ツールの選択ポイントを紹介 ・DSL vs. SQL  ・バージョン番号の採番方法
  5. 5. 用語解説:「マイグレーション」 ✓ DBMS自体を変更すること 例:OracleからPostgreSQLにマイグレーションした ✓ DBMSのバージョンを更新すること 例:PosrgreSQLを8.4から9.3にマイグレーションした ✓ DBスキーマのバージョンを更新すること 例:テーブル追加したのでマイグレーションを実行してね ここではこの意味で使う
  6. 6. はじめてのDBスキーマ管理 Ruby on Rails 編(DSL派)
  7. 7. Ruby on Rails とは? ✓ Ruby製の超人気フレームワーク http://rubyonrails.org/ ✓ マイグレーション機能をいち早く搭載 他のフレームワークがこぞって真似することに → Railsのやり方を知れば、他もだいたい同じ
  8. 8. マイグレーションファイルを作成 $ rails generate migration CreateUsers $ ls db/migrate/ 20131104023129_create_users.rb バージョン番号として タイムスタンプを使う
  9. 9. DBスキーマの変更操作を記述 ## 20131104023129_create_users.rb class CreateUsers < ActiveRecord::Migration def up create_table "users" do |t| t.string "name" t.string "email" バージョンを上げる end ときの操作 end def down drop_table "users" バージョンを戻す end ときの操作 end
  10. 10. DBスキーマの変更操作を記述 ## 20131104023129_create_users.rb class CreateUsers < ActiveRecord::Migration def change create_table "users" do |t| t.string "name" t.string "email" 簡単な操作なら、戻す end ときの操作を省略可能 (Railsが推測してくれる) end end
  11. 11. マイグレーションを実行 ### バージョンを上げる $ rake db:migrate ### バージョンを戻す $ rake db:rollback ### 再実行(戻して、もう一度上げる) $ rake db:migrate:redo ### 現在のバージョンを調べる $ rake db:version Current version: 20131104023129
  12. 12. 実行結果を確認 postgres=> dt users; テーブルが作成された List of relations ことを確認 Schema | Name | Type | Owner --------+-------+-------+------- public | users | table | myname (1 row) postgres=> select * from schema_migrations; version ---------------バージョン番号が専用の 20131104023129 テーブルに保存される (1 row)
  13. 13. 管理サイクル Step 1. マイグレーションファイルを作成 Step 2. 変更操作を手動で記述 ・バージョンを上げるときの操作 ・バージョンを戻すときの操作 Step 3. マイグレーションを実行 ・DBスキーマが変更される ・現在のバージョン番号がDB内に保存される これらの手順の積み重ねでバージョン管理を行う (この手順から外れた方法で変更しないこと!)
  14. 14. ソースコード管理ツールとの違い Git、Subversion スキーマ管理ツール ・差分は「データ」(diff形式) ・差分は「操作」(DSL or SQL) ・ツールが自動計算 ・人が手動で記述 ※ @@ -1,4 +1,5 @@ #include <stdio.h> -void main() { +int main() { printf("Hello"); + return 0; } def change create table "users" t.string "name" t.string "email" ... end end ※ 支援機能を持つツールもあるが、あくまで「支援」だけ
  15. 15. はじめてのDBスキーマ管理 Migr8.rb 編(SQL派)
  16. 16. Migr8.rb とは? (マイグレイト.rb) ✓ お手軽なDBスキーマ管理ツール ※ ・PostgreSQL、SQLite3、MySQLをサポート ・要Ruby ・https://github.com/kwatch/migr8 ✓ 使うまでのしきいが低い ・ファイル1つだけ(他の余計な外部ライブラリが不要) ・設定ファイルがない(環境変数を2つ設定するだけ) ・SQLで記述(DSLの学習コストがかからない) ※ 実は、自作ツール :)
  17. 17. インストールとセットアップ Install $ curl -Lo migr8.rb http://bit.ly/migr8_rb $ chmod a+x ./migr8.rb 設定ファイルがいらない Setup ※ $ export MIGR8_COMMAND="psql -q -U user db" $ export MIGR8_EDITOR="emacsclient" # or "vi" $ ./migr8.rb init ※ または export MIGR8_COMMAND="sqlite3 dbfile" (for SQLite3) export MIGR8_COMMAND="mysql -s -u user db" (for MySQL)
  18. 18. マイグレーションファイルを作成 $ migr8.rb new -m "create 'users' table" # or: migr8.rb new --table=users $ ls migr8/migrations scjs8350.yaml バージョン番号として ランダム文字列を使う (とても重要な特徴!)
  19. 19. DBスキーマの変更操作を記述 # -*- coding: utf-8 -*version: scjs8350 desc: create 'users' table author: alice vars: バージョンを上げる ときの操作 up: | create table users ( id serial primary key, name varchar(255) not null unique, ); down: | drop table users; バージョンを戻す ときの操作
  20. 20. DBスキーマの変更操作を記述 # -*- coding: utf-8 -*version: scjs8350 desc: create 'users' table author: alice 変数を定義可能 vars: - table: users 変数を展開 up: | create table ${table} ( id serial primary key, name varchar(255) not null unique, ); 変数を展開 down: | drop table ${table};
  21. 21. マイグレーションを実行 ### バージョンを上げる $ ./migr8.rb up ### バージョンを戻す $ ./migr8.rb down ### 再実行(戻して、もう一度上げる) $ ./migr8.rb redo ### 現在のバージョンを調べる $ ./migr8.rb status # 省略可 ...(snip)...
  22. 22. 実行結果を確認 postgres=> dt users; テーブルが作成された List of relations ことを確認 Schema | Name | Type | Owner --------+-------+-------+------- public | users | table | myname (1 row) postgres=> select * from _migr8_history; version ---------バージョン番号が専用の scjs8350 テーブルに保存される (1 row)
  23. 23. 履歴を表示 $ ./migr8.rb hist scjs8350 2013-11-07 23:01:13 # [alice] create 'users' ewwg6691 2013-11-07 23:29:33 # [alice] add index gnqc9473 (not applied) # [john] create 'groups' spvo5800 (not applied) # [john] add 'group_id' 作成者と説明文 マイグレーションを適用した日時 (未適用なら "(not applied)") 適用すべきマイグレーションの一覧
  24. 24. ツール選択のポイント #1 DSL vs. SQL 
  25. 25. 分類 ORM依存 South Rails Alembic CakePHP Doctrine Evolutions (Play Framework) SQL DSL Migr8 Flyway PHPMigrate Yoyo-migrations Linquibase ORM独立
  26. 26. 比較 ✓ DSL+ORM依存 (Railsなど) ・ORMや言語を乗り換えるのは難しい ・DBMSを乗り換えたり複数種類をサポートするのは簡単 ・SQLでは困難でも、RubyやPHPでなら簡単に解決できることも ✓ SQL+ORM独立 (Migr8など) ・ORMや言語の乗換えがしやすい ・DBMSの乗り換えはほぼ無理(DDLがDBMS依存なため) ・困ったときにRubyやPHPでゴニョゴニョできない
  27. 27. どう選ぶ? ✓ ORMやFWに付属している場合 ・それを使うしかない(DB管理者に選択権はない) ・DSLタイプでも生SQLを書ける機能はある(これが現実解?) ✓ ORMやFWに付属していない場合 ・ORM非依存のを推奨 ・PostgreSQLもMySQLもサポートしたい!→ DSLタイプ ・DBMSの乗り換えなんてしないよね∼ → 生SQLタイプでOK
  28. 28. ツール選択のポイント #2 バージョン番号の採番方法
  29. 29. バージョン番号に求められる性質 一意性 複数人で同時に開発作業をしても、バージョン番号が 順序性 番号の順番(=マイグレーションの適用順序)は一意 重ならないでほしい(重複しては困る) に決まってほしい(人や環境によって違うのは困る) 不変性 一度決めたバージョン番号は変わらないでほしい (primary keyなんだから値の変更は困る)
  30. 30. バージョン番号の採番方法 ✓ 連番 却下 ! 複数人での開発時に、番号が重複しやすい(一意性が低い) ✓ タイムスタンプ 却下 ! 番号がそのまま順番を表すため、マイグレーションの適用順を変 えたい場合、番号の変更が必要(不変性が保たれない) ✓ ランダム文字列 採用 ! 番号は一意性のみを担保し、順序性は別の方法で保持 →適用順を変更しても、番号の変更は必要ない(不変性を保持)
  31. 31. タイムスタンプだと困るケース あるブランチで、 マイグレーション を作成 別のブランチで、より 新しいタイムスタンプ でマイグレーションを 作成し、 先にコミットした! すると、古いタイムスタン プのほうが、より新しいコ ミットになってしまう 適用順 != タイプスタンプ順 Gitのコミット
  32. 32. ソースコード管理システムの進化 GitやMercurialの設計思想は スキーマ管理にも応用できる Git, Mercurial ※ (ランダム文字列) 進化 Subversion (リポジトリ別の連番) 進化 CVS (ファイル別の連番) ※ 正確には「コミットのハッシュ値」
  33. 33. ランダム文字列で順序性:Alembic revision = 'fa2cfc94fd' down_revision = '547dcd1d3c30' Alembic マイグレーションファイルに、 戻り先のバージョン番号を記述 def upgrade(): (Gitのしくみとそっくり) op.create_table('users', Column('id', Integer, primary_key=True), Column('name', String, nullable=False), ) def downgrade(): op.drop_table('users')
  34. 34. ランダム文字列で順序性:Migr8 Migr8 # -*- coding: utf-8 -*scjs8350 # [alice] create 'users' table ewwg6691 # [alice] add index to 'name' col gnqc9473 # [john] create 'groups' table spvo5800 # [john] add 'group_id' to 'users' 専用のテキストファイルに、 バージョン番号を順番に並べる (マイグレーションファイルには書かない)
  35. 35. まとめ
  36. 36. まとめ ✓ DBスキーマのバージョン管理サイクル ・Step1. マイグレーションファイルを作成 ・Step2. スキーマ変更操作を記述(up, down) ・Step3. マイグレーションを実行 ✓ ツール選択のポイント ・DSL vs. 生SQL ・連番 vs. タイムスタンプ vs. ランダム文字列
  37. 37. おしまい

×