カラクリサイクル

『輝かしい青春』なんて失かった人の雑記

データベーススキーマのアップデートをPerlで楽にする方法

概要: DBIx::Migrationを使ってデータベースのスキーマをマイグレート


こんにちま!

いつも心にNo Coding, No Lite、悪い意味で書き捨てが恋人、 にゃるらこと岡村 直樹 (23)です。皆さんコード書いてますか?

僕はコードは書いてるんですが、いかんせんモノが完成せず、 日の目を見ない残骸ばっかり溜まってる気がしないでもないんですが、 それでもやっぱりコードは書いてます。 まあ気が向いた時だけですけどね。

で、挨拶はここまでで、本題。

皆さんは、データベースのマイグレートはどうしているでしょうか?

僕は、趣味グラマーな関係で、本格的にデーターベースを触った事が無いのですが、 最近はデータベースを使うコードを書いてたりして、データベースが云々というか、 データベースのスキーマの管理とかどうすんの? って感じで、 何がなんだかわからないって感じでした。

それで、何かいい方法は無いかと色々と調べて回ったんですが、 Perlだと丁度DBIx::Migrationがシンプルに使えそう、 ということが分かり、今はそれを使って管理しているので、 今日はその辺り書きたいと思います。

DBIx::Migrationを使ってDatabase Schema Migration

まず、下記のようなクラスを作成します。

package MyApp::DB::Migrator

use strict;
use Any::Moose;

with any_moose('X::Getopt');

use DBIx::Migration;

has [qw/ dsn username password dir /] => (
    is       => 'rw',
    isa      => 'Str',
    required => 1,
);

has revision => (
    is       => 'rw',
    isa      => 'Num',
    required => 1,
);

has migrator => (
    is         => 'ro',
    isa        => 'DBIx::Migration',
    lazy_build => 1,
    init_arg   => undef,
    handles    => [qw/ version migrate /],
);

no Any::Moose;

sub _build_migrator {
    my ( $self ) = @_;
    return DBIx::Migration->new(
           dsn      => $self->dsn,
           username => $self->username,
           password => $self->password,
           dir      => $self->dir,
    );
}

sub run {
    my ( $self ) = @_;
    return $self->migrate( $self->revision );
}

__PACKAGE__->meta->make_immutable;

で、次にこのクラスを使う、db-migrator.plを作成します。

#!/usr/bin/env perl
# db-migrator.pl

use strict;
use warnings;

use MyApp::DB::Migrator;

MyApp::DB::Migrator->new_with_options->run;

そして最後に、データベースの操作を行うsqlファイルを、 DBIx::Migrationがサポートしているファイル名、

  • {filename}_{rev}_up.sql
  • {filename}_{rev}_down.sql

という形式で任意のディレクトリに用意します。

これは例えば、

-- sessions-1-up.sql
CREATE TABLE sessions (
    id           CHAR(72) PRIMARY KEY,
    session_data TEXT
);

-- sessions-1-down.sql
DROP TABLE sessions;

という感じです。

あとは、

$ bin/db-migrator.pl \
      --dsn='db:SQLite:dbname=db.sqlite' \
      --username='nyarla' \
      --password='pswd' \
      --dir=./sql \
      --revision=1

という感じで実行すれば、データベーススキーマのマイグレートが実行されます。

ね、簡単でしょ?

マイグレートの実際の処理の部分は、DBIx::Migrationがやってるので、 その辺りの詳しい所は、

を見てください。

あと僕はこんな感じのコードで、データベース周りのテストを行う際に、 データベーススキーマをマイグレートしていますが、 このスクリプトを本番環境で使っても大丈夫なのか? という辺りは、 経験が無いのであんまりよくわかってません。 なんでこの辺り各自の自己責任で使ってください。

んで、この方法を使ってみての感想を。

この方法はDBIx::Migrationを見つけてから、 コードを書いているうちに自然と編み出した方法なのですが、 関連コードもすっきりしているし、 データベーススキーマもすっきりと管理できるので、割と気に入ってます。

使い心地に関しては、アプリケーションのテストで使ってる限りでは、 特に問題は起きてない感じですが、本番環境までたどり着いたことがないので、 本番で使ってみてどうだった、というのは経験がありません。

なんで、詳しいところを聞かれても、ちょっと答えようがないのですが、 スキーマのマイグレートする際には生のSQLを使っているので、 そのまま生のSQLの実行速度に縛られると思います。

個人的にはこの方法はベストまでいかないけれども、 ベタープラクティスなんじゃないの? とか思っているので、割とお気に入り。

まあ僕はこんな感じでって話ですが、よかったら試してみてください。

以上、実に久しぶりに書いた記述系記事でした。