@znz blog

ZnZ の memo のようなもの

yaml_dbでMySQLからPostgreSQLに移行した

| Comments

先週 redmine を MySQL から PostgreSQL に移行するときに、最近の ruby では動かなくなっている taps ではなく yaml_db を使ってみました。

その後、自作 Rails アプリでも yaml_db を使って移行しました。

yaml_db 選び

yaml_db は gem install yaml_db でインストールできるものが新しい rails などに 対応していないため fork が乱立していて、どれを使えばいいのか悩ましいのですが、 どこかで見かけた情報を元に gem 'yaml_db', github: 'jetthoughts/yaml_db', ref: 'fb4b6bd7e12de3cffa93e0a298a1e5253d7e92ba' を使いました。(今だと gem 'yaml_db', github: 'jetthoughts/yaml_db' だけの指定の方が良さそうです。詳細は後述)

redmine の場合は Gemfile.local に書いて (なければ作成)、 bundle でインストールすれば使えます。

データベース移行

アプリを止めるなどして、データベースの変更が発生しない状態にして移行作業をします。 YAML の互換性の問題などがあるので、データベースの移行と Ruby や Redmine のバージョンアップは別々にした方が良いです。

  1. まず RAILS_ENV=production bundle exec rake db:data:dumpdb/data.yml を作成します。
  2. つぎに Ruby や Rails や Redmine のバージョンはそのままで config/database.yml を変更します。
  3. 必要に応じて bundle でデータベースアダプターの gem をインストールします。
  4. データベースの作成をしたり db:migrate をしておきます。
  5. RAILS_ENV=production bundle exec rake db:data:load で読み込みます。

yaml_db の fork の再調査

yaml_db gem ( ludicast/yaml_db ) からの fork としては gitlab_yaml_db ( gitlabhq/yaml_db ? ) のインストール数が 多いようですが、これは以前の gitlabhq が依存していたからのようです。 (今は依存していない)

新しい fork として yaml_db_with_schema_tables ( zweitag/yaml_db ) がありましたが、古い yaml_db からの fork なので、新しい rails への対応が入っていないような気がします。 他の fork との違いとして schema_infoschema_migrations も dump するようにしているようです。

jetthoughts/yaml_db という fork は rubygems.org にはリリースしていないようですが、 Rails 4 に対応して、 README の This gem is now Rails 3 only. という記述を削除しているなど、メンテナンスが続いていそうなので、 次はこの fork を使うのが良さそうだと思いました。 (古いブログの記事だと gem 'yaml_db', github: 'jetthoughts/yaml_db', branch: 'rails4' で rails4 ブランチを指定している例もあるようですが、 master にマージ済みなので branch 指定は不要です。)

別 Rails アプリの移行

続きとして、本日、自作の Rails アプリを jetthoughts/yaml_db を使って移行してみました。

postgresql のデータベース作成

データベースの作成は事前に出来るので、 sudo -u postgres psql で作成しておきます。

1
2
CREATE ROLE dbuser LOGIN ENCRYPTED PASSWORD 'dbpass' NOINHERIT VALID UNTIL 'infinity';
CREATE DATABASE dbname WITH ENCODING='UTF8' OWNER=dbuser;

データベースの作成方法はいつも RedmineInstall を参考にしています。

pg gem

pg gem も忘れずにあらかじめ入れておきます。

メンテナンス中画面設定

まず apache2 + passenger の方でメンテナンス中画面を出すようにしました。

1
2
3
4
5
6
7
8
9
<Directory /path/to/app>
    Options FollowSymLinks
    AllowOverride None
    #Order allow,deny
    #allow from all
    Order deny,allow
    deny from all
</Directory>
ErrorDocument 403 "メンテナンス中です。 しばらくお待ちください。"

ErrorDocument の埋め込み文字列は Content-Type: text/html;charset=iso-8859-1 になってNいたので、 'メンテナンス中です。 しばらくお待ちください。'.unpack('U*').map{|c| '&#x%x;' % c }.join('') のようにして、すべてエスケープして日本語を埋め込みました。

本来は 5xx のステータスにすべきですが、一時的なものなので 403 で妥協しました。 後日メンテナンスをするときはちゃんと 5xx にしたいと思っています。

データベースのバックアップとダンプ

cron で動かしているデータベースのバックアップと yaml_db でのダンプをしました。

1
2
/path/to/app$ sudo /etc/cron.daily/local-dump
/path/to/app$ $ sudo env PATH=$(dirname $(awk '/PassengerDefaultRuby/{print $2}' /etc/apache2/conf.d/passenger.conf)):$PATH RAILS_ENV=production bundle exec rake db:data:dump

config/database.yml 書き換え

database.yml で postgresql の方を使うように書き換えます。

1
2
3
4
5
6
7
8
9
  adapter: postgresql
  encoding: unicode
  database: dbname
  pool: 5
  username: dbuser
  password: dbpass
  host: localhost
  #port: 5432
  min_messages: warning

データの読み込み

rake db:migrate でマイグレーションを実行した後、 rake db:data:load でデータを読み込みます。

1
2
/path/to/app$ $ sudo env PATH=$(dirname $(awk '/PassengerDefaultRuby/{print $2}' /etc/apache2/conf.d/passenger.conf)):$PATH RAILS_ENV=production bundle exec rake db:migrate
/path/to/app$ $ sudo env PATH=$(dirname $(awk '/PassengerDefaultRuby/{print $2}' /etc/apache2/conf.d/passenger.conf)):$PATH RAILS_ENV=production bundle exec rake db:data:load

メンテナンス解除と確認

apache2 の設定を戻して、動作確認します。

まとめ

Rails のデータベースの移行に yaml_db を使ってみました。

yaml_db の方が taps より昔からあって、 しばらくメンテナンスが止まっていて、 taps の方が主流になるかと思っていたら、 逆に taps の方がメンテナンスがあまりされなくなって、 yaml_db の方が fork が乱立して、新しい rails に対応したものもでてきて、 結局今のところデータベースの移行には yaml_db が無難という状況になっているようです。

taps は新しい Ruby に対応できていなかったり、 以前の記事に書いたようにスキーマの移行が不十分なところがあったりして、 使われなくなっていくように感じました。

Comments