backstage

合唱音源の新着情報の舞台裏

Ruby on Rails4.2でMicrosoft Azure SQL Databaseに移行

開発中のWebサイト「合唱音源の新着情報.com」で、データベースにはSQLite(Webサーバ内のローカルファイル)を使っていました。 しかしスケーラビリティや耐障害性を考慮し、SQLiteを捨ててデータベースサーバを導入することにしました。 (Webサーバのログインパスワード忘れてどうしようも無くなったなんて言えない)

WebサーバにMicrosoft Azureの仮想マシンを使っていることもあり、データベースサーバには同じAzureのPaaSであるMicrosoft Azure SQL Databaseを選びました。

SQL Serverは一切触ったことがありませんが、クラウドなので簡単に移行することが出来ます。たぶん。

Microsoft Azure SQL Database 構築

現在のサービスではいわゆるトランザクションデータは未だ取り扱っていないので、データ量は数千行程度と大したことはありません。 2GBまでのBasicプランを選択します。

f:id:s2terminal:20150628202657p:plain

最小構成であるBasicプランは現状月額500円程度と、AWS RDSの最小構成に比べてもお手頃さが特徴、個人でも運用しやすいです。 (AWSには無料枠が1年分ありますが...)

後は適当にポチポチするだけでデータベースサーバを構築できます。 ここで入力したパスワードを忘れないように気をつけましょう。(実際に忘れて一度作り直しになりました...)

Rubu on Rails から Azure上の SQL Serverに接続

Azure SQL Databaseの中身はMicrosoft SQL Serverらしいです。 なので、普通にSQL Serverに繋ぐ時と同じような方法で接続できます。

…できるはずなのですが「普通にSQL Serverに繋ぐ」がなかなかうまく行かず…

https://github.com/rails/rails/issues/17693 によると、どうやらRails 4.1.x 系と相性が悪いらしく接続できないようです。(ちゃんと読んでない)

なのでRails 4.1.9から4.2.1にバージョンを上げました。

ついでに、このためにWebサーバをまるごと新調し

に変更しました。 (SSHできなくなったサーバを捨てるついでです)

あとは接続します。 ↓下記ブログに書いてある事と同じになりますが http://lab.heathrow.co.jp/2013/08/23/1721/

tiny_tdsというruby gemを入れる必要があります。 tiny_tdsのインストールにはfreetdsが必要です。 freetdsは、CentOSの場合EPELからインストールします。

 $ sudo yum install epel-release
 $ sudo yum install freetds freetds-devel

Gemfileに下記記述してbundle install します。

# Azure SQL Server
gem 'tiny_tds'
gem 'activerecord-sqlserver-adapter'

database.yml に下記記述します。

development:
  adapter:  sqlserver
  mode:     DBLIB
  port:     ********
  host:     ********
  database: ********
  username: ********
  password: ********
  timeout:  10
  azure:    true

あとはrails sで起動できたら成功です。 これで接続することができました。

なお、この後データベーススキーマを流す時に「rake db:drop」等でデータベースごと壊してしまうと「rake db:migrate」等では作り直せないので気をつけましょう。(実際に壊してしまい、Azure管理画面から作り直しになりました...)

SQLiteからSQL Serverへのデータ移行

現状のデータを(ログインできないサーバのローカルにある)SQLiteからAzure SQL Databaseへと移行しなければなりません。

たまたまrails_adminが入っていたので、データをCSVJSON形式でエクスポートすることが出来ます。なおインポートは出来ません。

今回はこのRails Adminのエクスポート機能を使う事にしました。 (普通はyaml_dbなどを使えば簡単だと思います。たぶん)

データベーススキーマは下記記事で紹介したような多対多のリレーションになっています。

s2terminal.hatenablog.com

Rails AdminでJSONエクスポートしてtmp配下に配置し、rails consoleで下記を実行することでデータを流し込む事ができました。 もう少しRailsらしくスマートに書けそうな気もしますが、一度しか使わないプログラムなので気にしないことにします。

$ rails c
JSON.parse( File.read("./tmp/tweet_2015-06-13_10h44m31.json", :encoding => Encoding::UTF_8) ).each { |elem|
  elem["tweet_details"].map!{ |e|
    d = TweetDetail.where({name: e["name"], value: e["value"]}).first
    d || d = TweetDetail.new(e)
  }

  s = Tweet.new(elem)
  s.save
}

既に2週間ほど前から、 合唱音源の新着情報.com の本番環境でAzure SQL Databaseが動いています。 これでスケーラビリティや耐障害性のあるデータベースサーバが手に入りました。 ポイントインタイムリストアがあるので危険なスキーマ変更などもやりたい放題だと思います。たぶん。

応答速度について、さすがにローカルファイルだったSQLiteに比べれば通信のスループットがあるせいか若干重くなった感じはしましたが、インデックスを適切に貼ることで解消されました。 書いていて思いましたが それは通信のスループットの問題ではない ですね。

なやみごと:開発環境をどうするか

MacSQL Serverは建てられません 。 また、SQL Serverと言えばVisual Studioという強力なGUIツールが特徴だと思うのですが、これもMac版はありません。

本案件はメインの開発環境がMacのローカルなため、ここで困ってしまいます。 本番と同じデータベースで開発…も嫌なので、もう500円払って開発用のデータベースを構築したいところです。 しかし現状は開発環境がSQLiteのまま、本番環境だけSQL Serverで進めています。

開発環境と本番環境でデータベースミドルウェアが異なっていても、Active Recordが何とかしてくれるので割と上手くいきます。 でもridgepoleのスキーマファイル出力結果が環境毎に一致せず開発環境で毎回謎のchange columnが走ったり、本番環境でRails Adminがよく分からないエラー(一部データ型を認識できない?らしい)で何度も落ちたり…細かい問題はあります。