うっかりエンジニアのメモ

未来の自分に宛てたメモ

1ヶ月でデータベーススペシャリスト試験に合格する方法

受験者のスペック

  • SIer新卒2年目エンジニア
  • 担当業務は脆弱性検査、コーディング(Java)
  • DBはOracle RACの調査で触る程度。業務でのDB設計経験は無し
  • 大学は情報系専攻

倒すべき敵を知る

試験は以下の4つの小試験に分けられており、全ての試験で合格点に達する必要があります。

**** 午前Ⅰ 午前Ⅱ 午後Ⅰ 午後Ⅱ
試験時間 9:30~10:20(50分) 10:50~11:30(40分) 12:30~14:00(90分) 14:30~16:30(120分)
出題形式 多肢選択式(四肢択一) 多肢選択式(四肢択一) 記述式 記述式
解答数/出題数 30/30 25/25 2/3 1/2
合格点 60% 60% 60% 60%

ただし、過去2年以内に以下の条件を満たしていれば、午前Iは免除されます。

午前Iが免除でないと応用情報の範囲もカバーする必要があり、短期間で合格するには辛いので、できればこの条件を満たした上で受けたいところです。私は2012年秋にセキュリティスペシャリスト試験に合格していたので、午前I免除でした。

午前II

データベースに関連した知識を問う4択問題が出題されます。25問中15問正解で通過です。 過去問からの出題が非常に多いです。感覚的には10問くらい過去問からなので、5問を取り切ることが課題になります。 25問中数問はセキュリティなど他の高度試験の試験範囲から出題されます。対策するにもコスパが悪いので、当たればラッキーの精神が良いと思います。

午後I

大問が3つ出題されます。

  • 大問1: データベース基礎理論
  • 大問2: データベース設計
  • 大問3: SQL(流動的)

おすすめは1,2選択です。 1,2は毎年この分野で出題され、問題形式もほとんど変化がありません。ですので、過去問対策が得点力に直結します。一方3はSQLをメインに扱うものの、パフォーマンスチューニング系の問題だったり設計と混ざった問題だったりと問題形式が流動的で、対策が辛いです。 1,2の組み合わせは、2chのスレを見ても定番のようです。 業務でSQLのパフォーマンスチューニングしまくってるレベルであれば、SQL選択で良いと思います。

H26春は傾向が変わった

長らく上記の大問構成が続いていたのですが、今回受験したH26春で傾向が変わりました。

  • 大問1: データベース基礎理論 + 設計
  • 大問2: SQL
  • 大問3: データベース設計 + SQL

SQLを捨てていた受験生はIPAに殺されました。。。 ちなみに大問2の会議室予約システムの問題は、ミック本の「重複予約を見つける」項がそのまま出題されたのでやってた人は「これ進研ゼミでやったやつだ…!」状態になったことと思います。やりましたね。

午後II

大問が2つ出題されます。どちらも10ページ超の長文を読んで、事例を分析します。

  • 大問1: データベース設計を中心に複合問題(流動的)
  • 大問2: 概念データモデル設計

おすすめは2選択です。 大問1はやはり出題範囲が流動的で、対策が辛いです。 大問2の概念データモデル設計は理解に時間が掛かるものの、理解度に応じてどんどん解けるようになっていくので、徒労になる心配がなくおすすめです。

おすすめ参考書

情報処理教科書

素晴らしいです。著者がDB試験に愛着あり過ぎで、過去問十数年分の解説が手に入ります。

情報処理教科書 データベーススペシャリスト 2014年版

情報処理教科書 データベーススペシャリスト 2014年版

過去問

無料。国家試験素晴らしいです。ある意味最強の教材です。

過去問題(問題冊子・配点割合・解答例・採点講評)

iPhoneアプリ

午前IIに不安がある場合はこのアプリで通勤通学の行き帰りにやっちゃいましょう。

データベーススペシャリスト試験 午前 精選予想問題集 500題 https://itunes.apple.com/jp/app/detabesusupesharisuto-shi/id480946632?mt=8

勉強法

DBは知識暗記系の試験ではありません。状況設定を理解し、比較的少ない原理・原則を適用して解く問題が多いです。そのため、長期にわたって勉強するとかえって中弛みがあってコスパが悪いです。 60点でも100点でも合格です。ここでは、合格できるレベルの原理・原則を理解し、時間内に答案用紙に表現できる状態で、「自分は解ける」という高まりを感じているピークの時期をちょうど試験日に合わせることを目的にします。

1ヶ月前

iPhoneアプリを使って午前II対策を始めます。通勤通学に進める程度でOKです。 今の知識でも解ける問題は本番も解けるのでスルーして、間違えた問題について、意識的に記憶を修正するようにします。原理・原則を覚えるべき問題は参考書やgoogle先生で理解しておきます。 並行して、ぼけ〜っと参考書を眺めます。パラパラ読む程度でOKです。「この内容の8割位が頭に入れば当日受かるんだな」というあたりをつけます。

3週間前

脳内に試験範囲の全体像がぼんやり形成されてきた頃です。ここで、直近の試験を印刷して午前IIから午後IIまで通しで本番と同じ形式で解いてみます。土日どちらかは潰れます。 その後、IPAのサイトにある模範解答を見て答え合わせをして(なんとなく)採点します。午後IIとか2時間もあるのに全然解答できなくて凹むこと請け合いですが、私も最初は2割くらいしか埋まらなかったです。 ここで「DBやべぇな…」という緊張感を得ておきます。

3週間前〜3日前

ひたすら過去問演習します。午前IIから午後IIまで通しでやる必要はないです。「今日は早く帰れたから午後II解こう」「なんか気分乗らないから午前IIだけやって寝よう」OKです。日を空けたりせず、毎日やって徐々にDB脳にしていきます。ただし、直近の一つ前の試験は解かずに取っておきます。 どのくらいの量を演習すればよいのか人それぞれですが、時間的制約で私は平成21年春まで消化しました。それより前は出題形式が異なるので参考にならないと思い、避けました。

はじめは制限時間を気にせず、ただし模範解答は見ないで、じっくり解きます。 配点は非公開なので点数を計算してもあまり意味がないと思います。○、△、×の3種類でつけていました。記述式の設問については「文意は合っているから丸」とかせず、文の構成や使用単語がIPAの模範解答と異なる場合は△にします。ケアレスミスは即修正して気をつけようで終わりです。「概念を根本的に誤って理解しているな」と感じたら、過去問を解く作業を中断して、参考書を読んで概念を再構築します。

終盤になったら、制限時間内に模範解答に近い解答を作成できるように時間も意識します。

前日

この日は丸一日空けます。 そして、解かずに取っておいた直近の一つ前の試験を午前IIから午後IIまで通しで解きます。 社会人の方、できれば有休取りましょう。

おそらく6割あたり、解ける力がついています。 「合格点行けるのでは」「全くわからない設問は無かったぞ」 3週間前とは全く違う手応えを感じながら、自分の中の成功イメージを高めます。

DBは詰め込み系の試験ではないので、前日にできることはほとんどありません。勉強はほどほどに早めに就寝して、翌日のパフォーマンスを良くすることに集中します。 私は美味しい夕飯を食べて、湯船にじっくり浸かって疲れを癒してから寝ました。 (が、実は緊張して4.5時間くらいしか眠れませんでした…)

当日

健闘を祈ります。

総学習時間

65時間。ざっくりと内訳↓

  • 午前II対策 0.5h(iPhoneアプリ)×20日 = 10h
  • 参考書読む 1.0h×20日 = 20h
  • 過去問 {5h(解答)+2h(答え合わせ)}×5年分 = 35h

結果

f:id:entropiajp:20140627125912p:plain

S3上の静的サイトにさくらで管理中のドメインのサブドメインでアクセス

今日、さくらのレンタルサーバから、さくらのVPS+さくらのメールボックスへのお引越しが完了しました。はじめはすべてVPSで済ませようと考えていたものの、メールサーバの構築難易度(セキュリティ面含む)の高さに恐れおののき、このような変則構成になりました。

その引っ越しの最中に、中学時代に書いてたオリジナルガンダム小説発表サイトなど、暗黒時代の産物が多数発掘されて、面白くなってきてこれはこれで公開しとこうと思い立ちました。でも普通にVPSのwebサーバ上に置くのも技術的に面白く無いなぁということで、そういえば昔AWSのS3に月額10円でサイトをホストうんちゃらというような広告を見たことがあったような気がして、ちょうどいい機会だと思って試してみました。

公開したいガンダム小説サイトはこちら http://0322.entropia.jp

条件

  • さくらのドメインentropia.jpを管理している
  • デプロイしたいサイトは静的サイト

ゴール

0322.entropia.jpで、S3上にデプロイした静的サイトにアクセスできる

手順

AWSでの設定

バケットの作成

[Create Bucket]から0322.entropia.jpという名前のバケットを作成します。

静的サイト公開設定

バケットを静的サイトのデプロイ先として利用できるように設定します。 Static Website Hosting > Enable website hostingを選択
Index Documentにindex.htmlError Documentにerror.htmlと入力します。

ファイルアップロード

普通にFTPする感覚で左上のUploadからファイルをアップロードします。
バケットのルートディレクトリがURLのルートと対応することに注意します。

パーミッション設定

Permission > edit bucket policyで開いたウィンドウに以下をコピペしてsaveします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::0322.entropia.jp/*"
        }
    ]
}

この時点でAWSドメインで静的サイトにアクセスすることができます。もう一息です。 http://0322.entropia.jp.s3-website-ap-northeast-1.amazonaws.com

さくらでの設定

会員メニュー > ドメイン > ドメイン名一覧 から所望のドメインのゾーン編集をクリックして、下記のCNAMEレコードを追加します。
0322 CNAME 0322.entropia.jp.s3-website-ap-northeast-1.amazonaws.com.
最後のドットが非常に重要です。

以上です。お疲れ様でした。

nginx上でサブディレクトリのCakePHPアプリを動作させる

もう本当に大変で、1週間潰れました。
同じように貴重な土日を潰してしまう人が一人でも減ることを願って。

環境

目標

サブディレクトリにあるCakePHPアプリを動作させたい。

いいかえるとhttp://example.com/subdir/ にアクセスして、サーバー上の/usr/shared/nginx/example.com/subdirにあるCakePHPアプリにアクセスしたい。

stackoverflowなどに同様の質問は沢山挙がっているのですが、どのベストアンサーも私の環境では正常に動作しませんでした。

CakePHP公式サイトのnginx設定例じゃダメなの?

ダメなんです。。。

server {
    listen   80;
    server_name www.example.com;
    rewrite ^(.*) http://example.com$1 permanent;
}

server {
    listen   80;
    server_name example.com;

    # root directive should be global
    root   /var/www/example.com/public/app/webroot/;
    index  index.php;

    access_log /var/www/example.com/log/access.log;
    error_log /var/www/example.com/log/error.log;

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

残念ながら、これはサーバのルートディレクトリにCakePHPを設置した場合の設定例なのです。
サブディレクトリにCakePHPを配置した場合の設定を一から考える必要があります。

CakePHP公式サイトのnginx設定例は何をやっているのか

公式サイトの設定例はそのまま利用できないものの、nginxでどう設定すればよいのかヒントになるので、詳しく見ていきます。

まず、最初のserverコンテキストで設定されているものです。

server {
    listen   80;
    server_name www.example.com;
    rewrite ^(.*) http://example.com$1 permanent;
}

これはwww.有りでアクセスがあった際に、www.なしのhttp://example.com/にリダイレクトする設定です。これはCakePHPと関係がないので、以後無視します。

後半のserverコンテキストを見ます。

server {
    listen   80;
    server_name example.com;

    # root directive should be global
    root   /var/www/example.com/public/app/webroot/;
    index  index.php;

    access_log /var/www/example.com/log/access.log;
    error_log /var/www/example.com/log/error.log;

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

server_name example.com;
Hostがexample.comであるアクセスは、このコンテキストの設定で処理されることを宣言しています。

root /var/www/example.com/public/app/webroot/;
URL上のルートパスに対応するサーバ上のフルパスが設定されます。apacheにおけるDocumentRootと同じ。

locationコンテキストその1

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }

(先ほどのrootディレクティブの設定は{}の内側全域で有効であることに注意)
ここのlocationコンテキストの動作はやや複雑。

  1. /var/www/example.com/public/app/webroot/$uriという静的ファイルを探す
  2. (無ければ)/var/www/example.com/public/app/webroot/$uri/というディレクトリを探す
  3. (それも無ければ)/var/www/example.com/public/app/webroot/index.php?$uri&$argsに内部リダイレクトする

  4. $uriにはクライアントから要求のあったURLから、server_nameを取り除いた文字列が入る

    • 例: http://www.example.com/xxx/yyyにアクセスがあった場合、$uri = xxx/yyy
  5. $argsはURLパラメータを保持したまま内部リダイレクトするための変数

locationコンテキストその2

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

locationコンテキストに~をつけると、設定を適用したいアクセスを正規表現で指定できます。
この場合、末尾が.phpで終わるファイルへのアクセスは、このlocationコンテキストの設定が適用されます。

nginx設定例

以上を踏まえて、こうなりました。

server {
    listen       80;
    server_name  example.com;

    root   /usr/share/nginx/example.com;

    location / {
        index  index.php index.html;
    }

    location ~ ^/subdir/(img|css|js|files)/(.+)$ {
        root /usr/share/nginx/example.com/subdir/app/webroot;
        try_files /$1/$2 =404;
    }

    location ~ ^/subdir/(.+\.php) {
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }

    location ~ ^/subdir/(.*)$ {
        index  index.php index.html;
        try_files /subdir/$1 /subdir/$1/ /subdir/index.php?$1&$args;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

参考資料

Nginx Community
http://wiki.nginx.org/

Nginx はどのようにリクエストを処理するか
http://nginx.org/ja/docs/http/request_processing.html

Nginx で location の判定方法と優先順位を調べる
http://server-setting.info/centos/nginx-location-check.html

nginx連載5回目: nginxの設定、その3 - locationディレクティブ
http://heartbeats.jp/hbblog/2012/04/nginx05.html

新卒2年目がAWSソリューションアーキテクト アソシエイトレベルに合格するまで

2014年5月に受験して合格しました。

例によって、受験時の規約により問題内容などについて言及することができないので、おすすめの教材などをまとめます。

受験者について

  • SIer新卒2年目エンジニア
  • 担当業務は脆弱性検査、コーディング(Java)
  • AWSは無料利用枠で触ってるくらい
  • 大学は情報系専攻

倒すべき敵を知る

公式サイトと受験体験記から、どんな試験なのかあたりをつけます。

眺めた受験記

http://drawing-hisa.seesaa.net/article/384974315.html http://qiita.com/inouet/items/02e8ba866a30f0316eeb http://humangas.hatenablog.jp/entry/2014/03/31/174247 http://www.seeds-std.co.jp/seedsblog/1055.html http://pc-concierge.net/blogs/blog/archives/70

おすすめ教材

サンプル問題
http://aws.amazon.com/jp/certification/certification-levels/certified-solutions-architect-associate/
公式に公開されています。

AWS 認定ソリューションアーキテクト – アソシエイト レベル試験に合格する方法
http://dev.classmethod.jp/etc/how-to-get-a-certification-aws-architect-associate-level/
クラスメソッドさんのブログにはいろいろ助けられました。

Amazon Web Services クラウドデザインパターン 設計ガイド

Amazon Web Services クラウドデザインパターン 設計ガイド

AWSエバンジェリスト玉川憲氏らが執筆した、AWSデザインパターンのカタログのような本です。1つのデザインパターンを数ページにまとめているので、さくさく読みやすいです。

AWS クラウドサービス活用資料集 特に「AWS マイスターシリーズ」と題した一連のプレゼン資料は、よくある要件をもとにAWSの各種サービス適用例を説明しているので理解しやすいです。

サンプル問題にもあるように、暗記すれば解ける類の問題よりも、ある状況設定のもとで最善の方法を選ばせる問題に対応できると良いと思います(精一杯の言い方)

ひとこと

CCNAのような暗記ゲーでも無ければ、Oracleの白本(※)のようなチート本もないので、なかなかしんどい試験だと思います。 「実戦経験がない人は受けない方が良い」という意見も見かけましたが、AWSを使ったアーキテクチャ設計が未経験だったり、AWSの管理画面をばりばり利用したことがなくても、ドキュメントベースでAWSへの理解があれば合格できるように感じました。 実務に裏打ちされた深い技術理解の証明には、今ならソリューションアーキテクト – プロフェッショナルレベルが適していると思います。

【オラクル認定資格試験対策書】ORACLE MASTER Bronze[12c SQL基礎](試験番号:1Z0-061)完全詳解+精選問題集(オラクルマスタースタディガイド)

【オラクル認定資格試験対策書】ORACLE MASTER Bronze[12c SQL基礎](試験番号:1Z0-061)完全詳解+精選問題集(オラクルマスタースタディガイド)

  • 作者: エディフィストラーニング株式会社,西昭彦,飯室美紀,鈴木佐和,岡野友紀,矢島祐子
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2014/03/27
  • メディア: 単行本
  • この商品を含むブログを見る

CakePHPでやたら遅いSELECTクエリの改善

プライベートで作ったWebアプリで、一画面だけブラウザに表示されるまで3秒かかる激重画面があります。 この画面ではCakePHPが自動的にいろんなテーブルをjoinしたSQLを生成しているので、その辺りが原因だろうとは感づきました。 それにしても、たかだか20行程度のselectなので、なんか変だ。。。 ちょっとだけ分析と改善をしました。(はじめてのパフォーマンスチューニング…ドキドキ)

結論としては、1000倍早くなりました。 CakePHPのクエリ自動生成は楽ですが、パフォーマンス上の問題が発生した時にはやはりSQLを知らないとダメだなぁ…

環境

VirtualBoxVM(メモリ613MB)上に下記の環境があります。

テーブル構造

テーブル 内容 外部キー
orders 注文データ shipping_method_id, payment_method_id, prefecture_id, tracking_code_id
shipping_methods 発送手段データ なし
payment_methods 入金方法データ なし
prefectures 都道府県データ なし
tracking_codes 追跡番号データ order_id(この追跡番号に対応した注文のid)

全てのテーブルはid列を主キーとして持つ。

恐ろしく時間がかかるクエリは、ordersテーブルを基点に他の4つのテーブルをleft joinして、注文が新しい順にソートして上位20件だけselectするようなクエリです。

改善前

CakePHPが発行したクエリ

SELECT *
FROM
  orders 
LEFT JOIN shipping_methods ON orders.shipping_method_id = shipping_methods.id
LEFT JOIN payment_methods ON orders.payment_method_id = payment_methods.id
LEFT JOIN prefectures ON orders.prefecture_id = prefectures.id
LEFT JOIN tracking_codes ON orders.id = tracking_codes.order_id
  WHERE 1 = 1
  ORDER BY orders.created DESC
  LIMIT 20;

※見やすさのために手を加えています

WHERE 1 = 1が気になりますが速度に影響しません。
CakePHPが挿入するこのWHERE 1 = 1の意味はこちらの解説がわかりやすいです。
CROSSOVER SEplus : where 1 = 1

実行速度(5回実行平均)

1826ms
くっそ遅い

クエリのexplain結果

id select_type table type possible_keys key key_len ref row Extra
1 SIMPLE orders ALL NULL NULL NULL NULL 2604 Using temporary; Using filesort
1 SIMPLE shipping_methods eq_ref PRIMARY PRIMARY 4 ordersys.orders.shipping_method_id 1
1 SIMPLE payment_methods eq_ref PRIMARY PRIMARY 4 ordersys.orders.payment_method_id 1
1 SIMPLE prefectures eq_ref PRIMARY PRIMARY 1 ordersys.orders.prefecture_id 1
1 SIMPLE tracking_codes ALL NULL NULL NULL NULL 2233

で、でた〜ww
Using temporary; Using filesortはアカン。
なぜアカンのかはイケメンな漢さんの記事が大変参考になります。
漢(オトコ)のコンピュータ道: Using filesort

分析

怪しいのは2箇所。

  • LEFT JOIN tracking_codes ON orders.id = tracking_codes.order_idだけ、join先の列がidではなくorder_id
  • ORDER BY orders.created DESCでは、indexが生成されていないcreated列を使ってソートしている

それぞれ修正していきます。

CakePHPのテーブル関係定義

生成されるSQLの違いはCakePHPでの設定の違いから生まれるのは間違いないので、Orderモデルの定義をみていきます。

<?
class Order extends AppModel {
    public $hasMany = array(
        'ItemOrder'
    );
    
    public $hasOne = array(
        'TrackingCode',
    );

    public $belongsTo = array(
        'ShippingMethod',
        'PaymentMethod',
        'Prefecture'
    );
    ?>

SQLが怪しいTrackingCodeモデルだけ、関係がhasOneなのが気になります。

設計時に「OrderはひとつのTrackingCodeを持つ」という考えだったけれど、エンティティの主従関係を踏まえると、OrderがあろうがなかろうがTrackingCodeは存在するのだから、「OrderTrackingCodeに紐づく」(つまりOrder belongs to TrackingCode)としたほうが自然。

したがってOrderモデルを以下のように修正しました。

<?
class Order extends AppModel {
    public $hasMany = array(
        'ItemOrder'
    );

    public $belongsTo = array(
        'ShippingMethod',
        'PaymentMethod',
        'Prefecture',
        'TrackingCode'
    );

    // 中略
    ?>

ソート

これまで、注文日時が新しい順にデータが欲しかったのでorders.created(レコードの挿入日時)をもとにソートしていましたが

  • orders.created列にはindexが作成されていない
  • orders.id列で降順ソートしても注文日時順にデータが取得できる

ということで、orders.idをもとにソートするように修正します。

ORDER BY orders.id DESC

改善後

CakePHPが発行したクエリ

SELECT *
FROM
  orders 
LEFT JOIN shipping_methods ON orders.shipping_method_id = shipping_methods.id
LEFT JOIN payment_methods ON orders.payment_method_id = payment_methods.id
LEFT JOIN prefectures ON orders.prefecture_id = prefectures.id
LEFT JOIN tracking_codes ON orders.tracking_code_id = tracking_codes.id
  WHERE 1 = 1
  ORDER BY orders.id DESC
  LIMIT 20;

実行速度(5回実行平均)

1.3ms!!
当社比1400倍。くっそ速い(前が遅すぎた)

クエリのexplain結果

id select_type table type possible_keys key key_len ref row Extra
1 SIMPLE Order index NULL PRIMARY 4 NULL 20
1 SIMPLE ShippingMethod eq_ref PRIMARY PRIMARY 4 ordersys.Order.shipping_method_id 1
1 SIMPLE PaymentMethod eq_ref PRIMARY PRIMARY 4 ordersys.Order.payment_method_id 1
1 SIMPLE Prefecture eq_ref PRIMARY PRIMARY 1 ordersys.Order.prefecture_id 1
1 SIMPLE TrackingCode eq_ref PRIMARY PRIMARY 4 ordersys.Order.tracking_code_id 1

Using temporary; Using filesortが消えてる

まとめ

  • CakePHPhasOneアソシエーションを設定する場合は生成されるクエリに注意
  • ソート列にindexが作成されているか注意
  • クエリが遅かったらexplainで手がかりをつかむ

さくらVPSにowncloudをインストール

owncloudとは

owncloudは自分のサーバ上にdropboxのようなクラウドファイル同期環境を実現するオープンソースソフトウェアです。

クラウドストレージサービスはすでにDropboxなどが定番でしょうか。しかし、デフォルトの容量が2GBと少なく、いろいろ頑張って無料範囲内で増量しても、せいぜい10GB。ですので

  • メジャーなクラウドストレージサービスでは足りない人
  • 諸事情でDropboxにはつなげられないけどクラウドでファイル同期したい人

に、おすすめです。

今回はowncloud6.0.1をさくらのVPSに入れてみました。

環境

LAMP環境をすでに構築してあるものとします。

さくらVPSLAMP環境を構築する手順は過去記事を参考にどうぞ。

準備

MySQL

owncloudは管理のためにDBを利用します。v6.0.1ではMySQLSQLiteを選択できるので、ここではMySQLを選択します。

owncloud用のDBを作成し、owncloud用のユーザを作成します。

mysql> create database owncloud character set utf8;
mysql> grant all privileges on owncloud.* to 'owncloud'@'localhost' identified by '【パスワード】' with grant option;
mysql> flush previleges;

Apache

/etc/httpd/conf.d/owncloud.confを新規作成し、

<Directory /var/www/html/owncloud/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
</Directory>

と入力して保存。

owncloudインストール

cd /etc/yum.repos.d/
wget http://download.opensuse.org/repositories/isv:ownCloud:community/CentOS_CentOS-6/isv:ownCloud:community.repo
yum install owncloud

デフォルトでowncloudは/var/www/html/owncloudにインストールされます。rootユーザでファイルが生成されているとあかんので、apacheユーザにしておきます。

chown -R apache:apache /var/www/html/owncloud

Apacheを再起動します。

service httpd restart

owncloudへのアクセス

http://host.your.domain/owncloud

初期設定画面が表示されたら、インストールは完了です。


トラブルシューティング

手元のマシンからMySQL DBへ接続できない

リモート(たとえば手元のMacBook Pro)から、すべてのDBにアクセスできるDBユーザを作成済みで、正しいユーザ名とパスワードであるにもかかわらず、接続できない。

原因

ファイアウォールMySQLのポートへの接続が制限されているかも。

解決策

iptablesに下記を追加します。

-A INPUT -p tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp --sport 3306 -j ACCEPT

iptablesを再起動します。

service iptables restart

owncloudにログインしようとするとリダイレクトループでログインできない

解決策

セッションファイルの所有者を確認します。 CentOS 6.5の場合、PHPのセッションファイルはデフォルトで/var/lib/php/session下に保存されるので、所有者をapacheの実行ユーザに変更する。

chown -R apache:apache /var/lib/php/session

原因

たぶんこのハマり方したのは自分だけのような気が…。 owncloud redirect loopググると、海外のフォーラムはよくひっかかる。それぞれ原因は異なるように見え、解決策を見つけることはできず。

うーん…と悩みつつ、あらためてコマンド履歴を振り返ると、owncloudのアクセス中にhttpd.confを編集した形跡が…! 思い出しました。owncloudインストール後に、Apacheの実行ユーザとグループをhogeに変えていたことを。

つまりこんなことが起きてました。

  • Apacheの実行ユーザがapacheの状態で、owncloudにログイン
  • /var/lib/php/session下に、所有者apacheでセッションファイルが生成される
  • owncloudにログイン中(=セッション有効中)にhttpd.confを開き、Apacheの実行ユーザをhogeに変更
  • Apache再起動
  • ブラウザからowncloud利用しようとするとログイン画面へ飛ばされる
  • ログイン画面で正しいユーザID/パスワードを入力する
  • ログイン情報は正しいのでログインしようとするが、セッションファイルを生成するディレクトリの所有者がapacheなので、生成できない
  • ここでリダイレクトループ発生?

完全におばかさんでした。 Apacheの実行ユーザはよく考えて、最初に決めましょう。

さくらVPSで複数の独自ドメインを運用する

さくらのVPSで、もともとサーバに付与されているipアドレスを生かしたまま、複数の独自ドメインを運用する手順を説明します。

環境

LAMP環境をすでに構築してあるものとします。

さくらVPSLAMP環境を構築する手順は過去記事を参考にどうぞ。

手順

ここでは例として、追加したいドメインは下記の2つとします。

DNSレコード設定

上記のドメインはさくらで取得していたので、さくらの管理画面からAレコードの指すipアドレスVPSサーバに付与されているものに変更するだけでした。5分程度で反映されました。

NameVirtualHost

Apacheが同じサーバ上で別々のドメインのサイトを運用する方法の一つが名前ベースのバーチャルホストです。Apacheは、クライアント(ブラウザ)から送られてくるHTTPHostヘッダを頼りに、どの独自ドメイン宛のリクエストなのかを判別します。

NameVirtualHostの有効化

/etc/httpd/conf/httpd.confを開き

#NameVirtualHost *:80

先頭の#を外します。

ドメインとの対応付け

ドメインに対するアクセスを、どのディレクトリに対応付けるかを設定します。 /etc/httpd/conf/httpd.confに書いてもよいのですが、ここで、/etc/httpd/conf.d/下にある.confで終わるファイルが、apacheの起動時にhttpd.confと同様に読み込まれることを利用します。

/etc/httpd/conf.d/moiranographia.com.confを新規作成し、下記を書きます。

<VirtualHost *:80>
  ServerName moiranographia.com
  DocumentRoot "/var/www/moiranographia.com/public_html"
  DirectoryIndex index.html index.php
  ErrorLog /var/log/httpd/moiranographia.com_error_log
  CustomLog /var/log/httpd/moiranographia.com_access_log combined
  AddDefaultCharset UTF-8
  <Directory "/var/www/moiranographia.com/public_html">
    AllowOverride All
  </Directory>
</VirtualHost>

独自ドメインが複数ある場合、同様にファイルの作成を繰り返します。

もともとサーバに付与されているipアドレスを生かす

Apacheの公式ドキュメントにもある通り、VirtualHostを有効にすると、もともとサーバに付与されているipアドレスの直打ちではアクセスできなくなります。

メインホストはなくなります

既にあるウェブサーバにバーチャルホストを追加する場合、 既存のウェブサーバに対しても ブロックを作らなければなりません。このバーチャルホストの ServerName と DocumentRoot は、グローバルな ServerName と DocumentRoot と同じものにします。また、このバーチャルホストを設定ファイルの中で先頭に置いて、デフォルトホストとして動作するようにします。

http://httpd.apache.org/docs/current/ja/vhosts/name-based.html より引用

ですので、httpd.confを編集します。

/etc/httpd/conf/httpd.confを開き、NameVirtualHost *:80の下あたりに、下記を追加します。

<VirtualHost *:80>
  ServerName xxx.xxx.xxx.xxx
  DocumentRoot "/var/www/html"
  DirectoryIndex index.html index.php
  ErrorLog /var/log/httpd/error_log
  CustomLog /var/log/httpd/access_log combined
  AddDefaultCharset UTF-8
  <Directory "/var/www/html">
    AllowOverride All
  </Directory>
</VirtualHost>

xxx.xxx.xxx.xxx: もともとVPSに割り当てられていたipアドレス

この設定により、たとえばxxx.xxx.xxx.xxx/example.htmlへのリクエストに対して、apache/var/www/html/example.htmlをレスポンスとして返します。

apacheを再起動します。

service httpd restart