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

37
DB スキーマも バージョン管理 したい! 省略してない版 Makoto Kuwata <[email protected]> http://www.kuwata-lab.com/ PostgreSQLカンファレンス2013 LightningTalk 更新履歴: 2013-11-13 migr8.rbの設定における若干の間違いを修正 2013-11-14 SQLite3での設定等を修正、「migr8.rb new --table=users」を追加

Upload: kwatch

Post on 21-May-2015

27.445 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

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

DBスキーマもバージョン管理したい!—省略してない版—

Makoto Kuwata <[email protected]>http://www.kuwata-lab.com/

PostgreSQLカンファレンス2013 LightningTalk

更新履歴:・2013-11-13 migr8.rbの設定における若干の間違いを修正・2013-11-14 SQLite3での設定等を修正、「migr8.rb new --table=users」を追加

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

背景✓ ソースコードのバージョン管理は普及してる

Git、Mercurial、Subversion、…

✓ 対して、DBスキーマのバージョン管理は…

そもそも存在を知らない人が多い

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

OT: 控え室にてQ: PostgreSQL界隈では、スキーマのバージョン管理では何が人気なんですか?

A: そんなものはない

達人のお墨付き!!

(石井さんごめんなさい)

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

発表のゴール✓ DBスキーマもバージョン管理できることを知ってもらう・サンプルその1:Ruby on Rails (DSL派)

・サンプルその2:Migr8.rb    (SQL派)

✓ バージョン管理ツールの選択ポイントを紹介・DSL vs. SQL 

・バージョン番号の採番方法

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

用語解説:「マイグレーション」✓ DBMS自体を変更すること例:OracleからPostgreSQLにマイグレーションした

✓ DBMSのバージョンを更新すること例:PosrgreSQLを8.4から9.3にマイグレーションした

✓ DBスキーマのバージョンを更新すること例:テーブル追加したのでマイグレーションを実行してね

ここではこの意味で使う

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

はじめてのDBスキーマ管理Ruby on Rails 編(DSL派)

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

Ruby on Rails とは?✓ Ruby製の超人気フレームワーク

http://rubyonrails.org/

✓ マイグレーション機能をいち早く搭載他のフレームワークがこぞって真似することに

→ Railsのやり方を知れば、他もだいたい同じ

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

マイグレーションファイルを作成$ rails generate migration CreateUsers$ ls db/migrate/20131104023129_create_users.rb

バージョン番号としてタイムスタンプを使う

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

DBスキーマの変更操作を記述## 20131104023129_create_users.rbclass CreateUsers < ActiveRecord::Migration def up create_table "users" do ¦t¦ t.string "name" t.string "email" end end def down drop_table "users" endend

バージョンを上げるときの操作

バージョンを戻すときの操作

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

DBスキーマの変更操作を記述## 20131104023129_create_users.rbclass CreateUsers < ActiveRecord::Migration def change create_table "users" do ¦t¦ t.string "name" t.string "email" end endend

簡単な操作なら、戻すときの操作を省略可能(Railsが推測してくれる)

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

マイグレーションを実行### バージョンを上げる$ rake db:migrate

### バージョンを戻す$ rake db:rollback

### 再実行(戻して、もう一度上げる)$ rake db:migrate:redo

### 現在のバージョンを調べる$ rake db:versionCurrent version: 20131104023129

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

実行結果を確認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)

バージョン番号が専用のテーブルに保存される

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

管理サイクルStep 1. マイグレーションファイルを作成

Step 2. 変更操作を手動で記述 ・バージョンを上げるときの操作 ・バージョンを戻すときの操作

Step 3. マイグレーションを実行 ・DBスキーマが変更される ・現在のバージョン番号がDB内に保存される

これらの手順の積み重ねでバージョン管理を行う(この手順から外れた方法で変更しないこと!)

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

ソースコード管理ツールとの違いGit、Subversion

※ 支援機能を持つツールもあるが、あくまで「支援」だけ

・差分は「データ」(diff形式)

・ツールが自動計算

@@ -1,4 +1,5 @@ #include <stdio.h>-void main() {+int main() { printf("Hello");+ return 0; }

スキーマ管理ツール・差分は「操作」(DSL or SQL)

・人が手動で記述

def change create table "users" t.string "name" t.string "email" ... endend

@@ -1,4 +1,5 @@ #include <stdio.h>-void main() {+int main() { printf("Hello");+ return 0; }

@@ -1,4 +1,5 @@ #include <stdio.h>-void main() {+int main() { printf("Hello");+ return 0; }

@@ -1,4 +1,5 @@ #include <stdio.h>-void main() {+int main() { printf("Hello");+ return 0; }

@@ -1,4 +1,5 @@ #include <stdio.h>-void main() {+int main() { printf("Hello");+ return 0; }

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

はじめてのDBスキーマ管理Migr8.rb 編(SQL派)

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

Migr8.rb(マイグレイト.rb)とは?✓ お手軽なDBスキーマ管理ツール・PostgreSQL、SQLite3、MySQLをサポート・要Ruby

・https://github.com/kwatch/migr8

✓ 使うまでのしきいが低い・ファイル1つだけ(他の余計な外部ライブラリが不要)・設定ファイルがない(環境変数を2つ設定するだけ)・SQLで記述(DSLの学習コストがかからない)

※ 実は、自作ツール :)

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

インストールとセットアップ

$ curl -Lo migr8.rb http://bit.ly/migr8_rb$ chmod a+x ./migr8.rb

$ export MIGR8_COMMAND="psql -q -U user db"$ export MIGR8_EDITOR="emacsclient" # or "vi"$ ./migr8.rb init

設定ファイルがいらない

Install

Setup※

※ または export MIGR8_COMMAND="sqlite3 dbfile" (for SQLite3) export MIGR8_COMMAND="mysql -s -u user db" (for MySQL)

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

マイグレーションファイルを作成$ migr8.rb new -m "create 'users' table" # or: migr8.rb new --table=users$ ls migr8/migrationsscjs8350.yaml

バージョン番号としてランダム文字列を使う(とても重要な特徴!)

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

DBスキーマの変更操作を記述# -*- coding: utf-8 -*-version: scjs8350desc: create 'users' tableauthor: alicevars:

up: ¦ create table users ( id serial primary key, name varchar(255) not null unique, );

down: ¦ drop table users;

バージョンを上げるときの操作

バージョンを戻すときの操作

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

DBスキーマの変更操作を記述# -*- coding: utf-8 -*-version: scjs8350desc: create 'users' tableauthor: alicevars: - table: users

up: ¦ create table ${table} ( id serial primary key, name varchar(255) not null unique, );down: ¦ drop table ${table};

変数を定義可能

変数を展開

変数を展開

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

マイグレーションを実行### バージョンを上げる$ ./migr8.rb up

### バージョンを戻す$ ./migr8.rb down

### 再実行(戻して、もう一度上げる)$ ./migr8.rb redo

### 現在のバージョンを調べる$ ./migr8.rb status # 省略可...(snip)...

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

実行結果を確認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)

バージョン番号が専用のテーブルに保存される

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

履歴を表示$ ./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)")

作成者と説明文

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

ツール選択のポイント #1

DSL vs. SQL 

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

ORM依存

ORM独立

DSLSQLMigr8

RailsCakePHP

South

LinquibaseFlyway

Alembic

分類

Evolutions(Play Framework)

Doctrine

PHPMigrateYoyo-migrations

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

比較✓ DSL+ORM依存 (Railsなど)

・ORMや言語を乗り換えるのは難しい

・DBMSを乗り換えたり複数種類をサポートするのは簡単

・SQLでは困難でも、RubyやPHPでなら簡単に解決できることも

✓ SQL+ORM独立 (Migr8など)

・ORMや言語の乗換えがしやすい

・DBMSの乗り換えはほぼ無理(DDLがDBMS依存なため)

・困ったときにRubyやPHPでゴニョゴニョできない

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

どう選ぶ?✓ ORMやFWに付属している場合・それを使うしかない(DB管理者に選択権はない)

・DSLタイプでも生SQLを書ける機能はある(これが現実解?)

✓ ORMやFWに付属していない場合・ORM非依存のを推奨

・PostgreSQLもMySQLもサポートしたい!→ DSLタイプ

・DBMSの乗り換えなんてしないよね~ → 生SQLタイプでOK

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

ツール選択のポイント #2

バージョン番号の採番方法

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

バージョン番号に求められる性質複数人で同時に開発作業をしても、バージョン番号が重ならないでほしい(重複しては困る)

番号の順番(=マイグレーションの適用順序)は一意に決まってほしい(人や環境によって違うのは困る)

一度決めたバージョン番号は変わらないでほしい(primary keyなんだから値の変更は困る)

一意性

順序性

不変性

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

バージョン番号の採番方法✓ 連番複数人での開発時に、番号が重複しやすい(一意性が低い)

✓ タイムスタンプ番号がそのまま順番を表すため、マイグレーションの適用順を変えたい場合、番号の変更が必要(不変性が保たれない)

✓ ランダム文字列番号は一意性のみを担保し、順序性は別の方法で保持→適用順を変更しても、番号の変更は必要ない(不変性を保持)

却下!

却下!

採用!

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

タイムスタンプだと困るケースあるブランチで、マイグレーションを作成 別のブランチで、より

新しいタイムスタンプでマイグレーションを作成し、

先にコミットした!

すると、古いタイムスタンプのほうが、より新しいコミットになってしまう

適用順 != タイプスタンプ順 Gitのコミット

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

ソースコード管理システムの進化

※ 正確には「コミットのハッシュ値」

Subversion(リポジトリ別の連番)

Git, Mercurial(ランダム文字列)

CVS(ファイル別の連番)

進化

進化

GitやMercurialの設計思想はスキーマ管理にも応用できる

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

ランダム文字列で順序性:Alembic

revision = 'fa2cfc94fd'down_revision = '547dcd1d3c30'

def upgrade(): op.create_table('users', Column('id', Integer, primary_key=True), Column('name', String, nullable=False), )

def downgrade(): op.drop_table('users')

マイグレーションファイルに、戻り先のバージョン番号を記述(Gitのしくみとそっくり)

Alembic

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

ランダム文字列で順序性:Migr8

# -*- coding: utf-8 -*-scjs8350 # [alice] create 'users' tableewwg6691 # [alice] add index to 'name' colgnqc9473 # [john] create 'groups' tablespvo5800 # [john] add 'group_id' to 'users'

専用のテキストファイルに、バージョン番号を順番に並べる

(マイグレーションファイルには書かない)

Migr8

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

まとめ

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

まとめ✓ DBスキーマのバージョン管理サイクル・Step1. マイグレーションファイルを作成

・Step2. スキーマ変更操作を記述(up, down)

・Step3. マイグレーションを実行

✓ ツール選択のポイント・DSL vs. 生SQL

・連番 vs. タイムスタンプ vs. ランダム文字列

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

おしまい