FuelPHP + Ansible で超ラクラク開発/運用 - FuelPHPのインストール編
...開発者でも簡単にインフラ構築できる時代が来ました。Ansibleという強力な環境構築ツールを利用すれば簡単に環境構築ができます。
環境構築のツールはそのほかchef, puppet, dockerなど様々ですが、なぜAnsibleを選択したのかは以前筆者が書いた以下の記事を参考にしてください。
Qiita ソフトウェアエンジニアからみた環境構築自動化ツールの比較、感想
PHPのフレームワークも近年人気を増しているLalavel, 定番CakePHP, 超高速PhalconなどありますがなぜFuelPHPを選んだかというと機能が豊富なことと日本語の情報がたくさんあるからです。単純に好みです。
これからFuelPHP + Ansibleを使った開発のノーハウを次のような順で紹介しようと思っています。
- パート1:FuelPHPのインストール編
- パート2:メンテナンスモード切り替え編
- パート3:デプロイ編
- パート4:開発/本番環境の運用時の構成、注意点
以下の開発環境をベースに説明させていただきます。また、Ansibleの概念を知っている人向けです。
- MacOS X 10.10.2
- ansible 1.7.2
- FuelPHP 1.7
※ ansibleのインストール手順はGoogle検索するとたくさん出てきますので割愛させていただきます。
AnsibleでFuelPHPをインストールするPlaybookを実行するためには~/role/ロール名/配下にその手順をyaml形式で書く必要があります。以下、~/role/ロール名/task/main.ymlの処理内容です。
- name: ①Copy the code from repository git: repo={{ repository }} dest={{ root_dir }} accept_hostkey=yes sudo: no - name: ②comporser self-update shell: php composer.phar self-update chdir={{ root_dir }} - name: ③comporser update shell: php composer.phar update chdir={{ root_dir }} - name: ④set fuel_env. shell: env FUEL_ENV=production php oil -v chdir={{ root_dir }} - name: ⑤create link. file: path={{document_root_path}} src={{fuel_public_dir_path}} state=link - name: ⑥db migrantion. shell: FUEL_ENV=production php oil refine migrate chdir={{ fuel_dir_path }}処理内で使用される {{ }} 中は変数名が入ります。 変数の定義は/role/ロール名/vars/main.ymlに記述します。上記の内容ですと
VirtualBoxでCSSが更新されない時の対処法
...VirtualBoxで構築したローカル仮想環境で 更新したCSSがブラウザキャッシュを削除しても適用されず、 確認できない状況に陥ったので、備忘録的に残しておきます。
apacheの設定が要因のようで、 httpd.conf に以下の設定をすることで解決しました。
EnableMMAP Off EnableSendfile Off
apacheのドキュメントは以下リンクをご参考ください。 https://httpd.apache.org/docs/2.2/mod/core.html#enablemmap https://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
Amazon RDS for Auroraプレビュー利用開始!
...Amazon RDS for Auroraでプレビューが始まりました。
Auroraとは…MySQLと互換性のあるデータベースエンジン(MySQL5.6)で、 高性能の商業用データベースの可用性およびスピードと オープンソースデータベースのコスト効率性および簡素性を併せ持っています。 Amazon Auroraは、MySQLの5倍の性能を持ち、 同様の機能や可用性を提供している商用データベースの10分の1の価格との事です。
現在プレビュー利用待ちです。
プレビュー利用したら感想等伝えようと思います。
ELBでssl転送してnginxでクライアント認証とssl終端してProxyProtocolで送信元IPを取得する
...こんにちは。 タイトル長いですがだいたい成功して時がたったので需要があるかはわかりませんが記録しておきます。
お時間あるときにどうぞ。
目的としては、以下のとおりです 外部ELB→nginx(ssl終端かつクライアント認証)→内部ELB→app
つまり、クライアント認証したいけどELBにその機能はないのでtcp443転送してnginxでやるが上位サーバでとれる送信元IPがELBのIPになってしまう為 ELBでProxyProtocolを有効化してnginxでssl終端しつつProxyProtocolをListenして送信元IPをログに出したいという話です。
securityGroupやインスタンス作るなどの部分は省略します。
1.elbをawscliで作成、proxy-protocol設定
参考:
AWS ELBのProxy Protocolを触ってみた Enable or Disable Proxy Protocol Support - Elastic Load Balancing 今更 VPC で 複数の AZ をまたいだ ELB を試す(2)〜 awscli を使って 〜 - ようへいの日々精進 XP
・elb作成
profile=xxxxx elbname-ext=xxxx-elb securitygrops="sg-xxxxxxxx sg-yyyyyyyy" subnets="subnet-xxxxxxxx subnet-yyyyyyyy" sudo bash -c "aws elb create-load-balancer --load-balancer-name ${elbname-ext} --listeners Protocol=TCP,LoadBalancerPort=443,InstanceProtocol=TCP,InstancePort=443 --subnets ${subnets} --security-groups ${securitygrops} --profile ${profile}"※外部ELBはTCP443からTCP443に転送するだけで証明書を入れない感じの設定にします
DevOps時代のアジャイルでスケーラブルな開発環境をVagrant, GitHub, Travis, Chef, OpsWorksで構築する
...どうも。久しぶりです。 デベロッパーの平形です。
このブログに訪れたすべてのエンジニアの方々。 そして、エンジニア以外の方々。
とても感謝致します。 初めに言っておきますが、この記事ではコード、コマンドラインの一切は登場しません。
はじめに
私が今回お送りする内容は本当にスケーラブルな環境の構築、運用を手助けする事ができます。 連載記事で複数回に渡ってお届けしますが、この連載を読み終えそして実践していただければ、あなたは既にスケーラブルな環境で作業を行っている事でしょう。
この連載記事では、順番に必要なツールのインストール、使い方をハンズオン形式でお送りします。 実際に手を動かして実感していただく事がとても意味がある事だと思っています。 この回では、コード、コマンドラインは一切登場しません。次回以降にどんどん出てきます。 その前に**「伝えたい事があるんだ。君の事が好きだから」by小田和正**と叫ばせてください。
この記事は以下の方には不向きです。
- 俺は一生一人で生きていくんだ!と1日1回はトイレで意気込んでいる人。
- 後先の事なんか考えたくない。俺は今を生きているんだ!と週に3回は言っている人。
これらに該当する方。お疲れ様でした。出口はこちらです。
この記事は以下に該当する方に是非読んでいただきたいです。
- 開発者、インフラ担当者の方。
- これから新しいプロジェクトを立ち上げるんだけど、構成どうしようか悩んでる方。
- サーバーの台数が多くなったらどうしよう。と悩んでいる方。
- 開発要員が急に増えたらどうしよう。と悩んでる方。
- DevOpsとかスケーラブルな環境とかに興味があって、でも今ひとつ踏み出せない方。
- 上記を実践してみようとしたけど、挫折してしまった方。
- 開発環境で動いているコードがなぜか公開環境で動かなくて家に帰れない方。
- 本番反映が怖くて会社に行きたくない方。
- サーバーが落ちる事が不安で夜も眠れない方。
- 将来の事を考えると不安で不安で仕方なく、「とにかくもう、学校や家には帰りたくない〜。」by尾崎豊と口ずさんでしまう方。
それでは、夢の扉を開きましょう。
レガシーな開発と運用
- 開発環境、公開環境の構築は、構築手順書を元に手動でインストールしている。
- 公開環境のサーバー増設は1台ずつ手動でキッティングしている。
- パッチの適用、バージョンアップは手動で1台ずつ手順書を元に実行している。
- バージョン管理はしないで各自、修正ファイルをFTPでファイルをアップロードしている。
これらをヒューマンエラーなく、ストレスなく運用できるのはスーパーマンです。 そして、開発、運用メンバー全員が自分と同じスーパーマンでなければいけません。 凡人の僕には無理です。
現代の開発と運用
現代のもの凄い勢いで変化するサービス要求に耐えるには、様々なものを効率化しなければいけません。
素早くリリースしてユーザの反応を見ては仕様を変更してすぐに反映しまたリリースする。といった事も必要です。
近頃、開発運用の自動化は様々なメディアの記事で取り上げられ、賑わっています。 しかし、実際にどこまで自動化ができているのでしょうか?- バージョン管理
- 環境構築
- セキュリティパッチの適用
- バージョンアップ
- オートスケール
- 自動テスト
- 自動デプロイ
- 開発環境の配布
なかなか全部はできないですよね? でもやったほうが絶対に幸せになれます。
Railsで何をやっても Routing Error uninitialized constant ~と言われて泣きそうになった時
...昨日まで、午前中まで、ちょっとさっきまで、正常に動いていた Ruby On Rails のアプリが、急に何をやっても「Routing Error : Uninitialized constant XXXXX Controller」というエラーになってしまい、うんともすんとも言わなくなってしまうという謎の症状に陥り、原因究明まで1ヶ月ほど泣きそうになっていたというしびれる経験をしたので、ここに解決までのTIPS(もとい、奮闘記?)を書いておこうかと。
犯人捜索編
まずはもうトラウマに近くなったこのRailsのエラー画面…。

まず、このエラーに陥ると、Railsくんは直接URLを指定して呼び出されるコントローラーを切り替えても、いやもうそれ以外何をしても、ただひたすら同じ「Routing Error」でコントローラ名だけ違うというエラーを吐き続けます。もうそれしかエラーメッセージ知らないかのようにそれしか言わなくなってしまうんです。でも、Railsのルート設定ファイルである
config/routes.rbは正常なのです(だってさっきまで動いてたし、ルーティング変えてないんだから当然ですよ)。Railsのログ見てもエラー画面と同じ程度の情報しか出ないし、サーバ側のエラーログ見ても毎回 404エラー で、そのルート(URL)にはコンテンツがない(Railsのcontrollerが動いてない)よ──としか書いてない。エラーログの処理スタックを遡って行っても特におかしいところがない… いったいこりゃなんだ!? もう心は折れました、だいぶベキベキと折れて、Rails嫌いになりました、でも捨てられません、お仕事なので、原因究明させないと前に進めないんです(T_T)StackOverflowとかサポートフォーラムを検索すると、同じ症状に陥っている人の質問がいくつかあるんですよねぇ…でも、回答が書いてない。 まじかよ~誰も解決してないのかよ~!? 誰か助けてくれ~…という状態。
そしてこの症状のさらに謎なところが、Rails環境を再構築(ゼロからすべてインストールし直す)と解消するのです(というか、その当時はそれでしか復旧する術がなかったのですがね)。そのため、最初はサーバ側(ApacheやRailsを中継していたPassengerとか)の設定とかキャッシュとかが問題なのかとか色々調べたんですが、すべて的外れでした(バグフィックスの時に「ここじゃね?」という勘が外れると凹むんだよねぇ…自分も老いたな──とか思ってしまう)。
さて、何度目かのRails再ビルドで、RubyのバージョンとRailsのバージョンを変えてみました。最初はRuby1.9.3+Rails4.1.0だったのを、Ruby2.0.0+Rails4.2.0にしてみました。バージョンってのには何気に相性がかなりあるので、その辺から攻めてみた次第。リビルド直後は問題なし、でも次の日のお昼にまた同じ症状が発生してしまった。 RailsのSQLiteデータベースが壊れているのかもと、リビルド直後にバックアップしていたDBに切り戻してみても駄目だ。もう一度DB初期化してデータを入れ直してみる。…ん? seeds.rb が通らない(Railsではデータベースに初期データを登録する時は
db/seeds.rbを使ってrake db:seedコマンドを実行するのだが、これがエラーになるのだ )。これは Rake のバイナリが壊れているのか?──いやぁ、このあたりが一番泣きそうな感じでしたねぇ…もう徒労感と絶望感しかない感じ。閃きも出ないしね。
そんなこんなで、一ヶ月近く同じ調査を続けてたのですが、そこにようやく光明が差し込んだ次第。いやぁ、苔の一念…ってヤツですかね~。なんと、こんなサイトを発見!
Rubyが突然動かなくなった “/usr/bin/ruby: No such file or directory”
prelink とな? CentOS環境では、必須でインストールされており cron.daily (一日一回動くcronジョブ) で勝手に実行されちゃう。弊害としてRubyのバイナリファイルを壊してしまう場合がある──とのこと。かなり怪しい。今度は prelink+ruby で検索してみるとようやっと出てきました…金脈にたどり着いた感じだ。
iframe(スクロールバー無し+クロスドメイン)のページ内リンク
...あまり…ほとんど需要が無いと思いますが、以前詰まった iframeのページ内リンクについて書きます。
あるwebサービスで別途作成したhtmlコンテンツを表示させるためにiframeを使用しました。 その際にhtmlコンテンツでページ内リンクが効かないという問題が発生しました。
iframeにスクロールバーがあれば通常の方法でページ内リンクができるのですが、 1枚のページであるように見せるため、スクロールバーを表示させることはできません。 また、クロスドメインの場合、親子間でオブジェクトの操作ができないようです(XSRF防止のため)
色々試した結果、javascriptのpostMessage(子 - htmlコンテンツ)とaddEventListener(親 - 元のwebサービス)の組み合わせで実現できました。
子から親にpostMessageでスクロール先のY座標を通知 ↓ 親がaddEventListenerで登録したコールバック先でスクロール処理
kodomo.html(子)
<html> <head> <script type="text/javascript"> $(document).ready(function(){ // 親フレームにスクロール(=ページ内リンク)する命令を送る $(".PageNaiLink").click(function(){ var parentFrame = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined); var target = $(this).attr("href"); if(typeof parentFrame != "undefined"){ // 【メインの処理】 // messageイベントで処理を識別する文字列(この場合は'page_nai_link')と飛び先のy座標を送る // ※この場合、リンク元のタグのhref属性は'#リンク先'のみ parentFrame.postMessage( "page_nai_link" + $(target).offset().top, "*"); }else{ // エラー処理 } }); }); </script> </head> <body> <!-- ページ内リンク --> <a class="PageNaiLink" href="#link1">ページ内リンク1へ</a><br /> <a class="PageNaiLink" href="#linl2">ページ内リンク2へ</a><br /> <a class="PageNaiLink" href="#link3">ページ内リンク3へ</a><br /> <a class="PageNaiLink" href="#link4">ページ内リンク4へ</a><br /> <!-- ページ内リンク end --> <div style="height:200px;"></div><!-- 余白 --> <a id="link1"></a>リンク1 <div style="height:200px;"></div><!-- 余白 --> <a id="link2"></a>リンク2 <div style="height:200px;"></div><!-- 余白 --> <a id="link3"></a>リンク3 <div style="height:200px;"></div><!-- 余白 --> <a id="link4"></a>リンク4 </body> </html>packerでhvmでもresize2fsをできるようにしてrebootを回避する
...こんにちは。小宮です。 packerでhvmでもresize2fsをできるようにしてrebootを回避するというのをやってみました。
おなじことがcloud-initを用いてもできるような気がしています。 CentOS 6 (HVM)にcloud-initを設定してAmazon Linuxぽくする | Developers.IO ただしpackerつかってるのでそっちでやったほうがラクというか。 何も設定せずにcloud-initいれただけのamiつくったらログインできなかったですorz 設定ファイルに書いた内容と具体的に裏で何してくれちゃうのかちゃんと理解できないとやりたくないけど調べるのが手間だったので。 軟弱ものですみません。
・事の発端 CentOS6.5のオレ俺AMIをもとにhvmのインスタンス作ったところ、 chefレシピで流して自動でresize2fsがrootボリュームに対して実施されたはずが サイズ変わらず。 10から50GBになるはずだったけど10GBのままになっていた
・とりあえずぐぐる 以下URL先で同様の現象と対策を知る EC2のCentOS-HVMでディスクのサイズを変更する | Hack fdiskで拡張するほかにこんなやり方もあったんだーと目からうろこ。 でもってreboot必須って詰んだー!と思いました。(手間と自動化的に) 具体的にいうとresize2fsはchefレシピ流してやってるのでログインしてやるのは二度手間です。
・問題提起というか相談してみた (ぎじゅつ的に)とんがり系のおかたに、 パーティションテーブルの問題なら以下URLのようなのをpackerに仕込んだらどうか と提案いただいたというか教えていただきました CentOS on Amazon EC2 でディスクサイズ変更しても変わらないときの対処方法 | Developers.IO
・実際やってみたら成功した
packerに仕込んでるシェルスクリプトに以下を追加
+# growroot等をepelからインストール +yum -y --enablerepo=epel install dracut-modules-growroot cloud-utils + +# rootパーティションテーブルをリサイズ +dracut --force --add growroot /boot/initramfs-$(uname -r).imgで、packerでAMIをビルド、 そのAMIから作成したインスタンスにchefレシピを流してみると、 dfしてみたところディスクが拡張されてました。 rebootしなくて済んだ!!わーい! めでたしめでたし。
AWS S3を早くするフォルダ構成
...こんにちは、豊部です。
AWS S3をコンテンツデータのストレージに使う場合、転送速度が気になります。
S3は無限ともいえるストレージ領域がありますので、裏では様々な処理が行われ、
全世界で負荷をシステム全体でならすように設計されています。
このシステム全体をならす仕組みをフォルダ構成から利用できます。
ポイントは
・フォルダ名の先頭3文字でS3内で分散させている
です。
たとえば、コンテンツを3つのフォルダに分ける場合、

のようにしてしまうと、先頭3文字が「tes」となり、同じ場所に格納されてしまいます。
そこでフォルダ名の先頭にハッシュ値を頭につけて

としましょう。
こうすれば、S3内で分散されて格納されるため、転送速度が向上します。
S3を配信コンテンツのストレージにする場合は、試してみてください。
data_bagsの用途について
...こんにちは。小宮です。 data_bagsについて内部的に解説する必要が生じたのでこちらにも書いておきます。
最近のdata_bagsの活用方法は以下のとおり
1.LDAPで管理していないシステム用途のOSユーザ情報をロードしてレシピで追加 2.SSL証明書の格納とレシピからロードしてtemplateで設定 3.ntpサーバの情報のロードとtemplateで設定 4.awsのクレデンシャル情報を管理して各種スクリプトへ埋め込み 5.mysqlやldapなどのパスワードなどアカウント情報の管理 6.roleとenvironmentに収まりきらないnginxやapacheのvhostやupstream等の情報の管理 7.gangliaのhead_nodeやcluster_nameの情報の管理
0.下準備的な解説
※前提条件としてchef-soloの場合"knife-solo_data_bag"というgemが必要なので入れる。 (gem listでなければgem installかbundlerで入れてください)
格納方法と確認方法
暗号化しない場合、viなど任意のエディタで編集OK chef-repository/data_bags/任意のディレクトリ名/任意のファイル名.json をつくる。 中身はjsonの規則にのっとっている必要があるので、シンタックスをjson_verifyでCHK。
cat data_bags/dirname/filename.json |json_verify で、JSON is valid と出るのを確認する
暗号化する場合、 まずEDITORの環境変数を~/.bashrcなりに設定しておく必要があるのと暗号化用の鍵を作って設定しておく必要がある。 (※鍵は案件ごとに異なるイメージで、.gitignoreに書いとく必要があります。 流出厳禁かつ無くすとデータが見えなくなります。)
export EDITOR=vi vi .chef/knife.rb ------コメントを外す--------------------- encrypted_data_bag_secret "data_bag_key" -----------------------------------------※コメント外すと鍵指定しなくてもknifeコマンドでcreateした場合常に暗号化される ゆえに暗号化せず扱いたいデータファイルはviで作るかコメントインしてから作る必要有
鍵が必要なら作る (※.chef/knife.rbの相対パスはchefリポジトリ直下を意味します)
openssl rand -base64 512 > data_bag_key knife solo data bag create dirname filename # 作成(※既存は上書きされる) knife solo data bag edit dirname filename # ファイルをエディタで編集 knife solo data bag show dirname filename # jsonの中身を表示 knife solo data bag list # ディレクトリ一覧表示・注意するべきこと →bashやexecuteリソースは極力使うべきではない。templateリソースつかってください。 bashでsedるとdata_bagsから変数に入れた特殊文字が展開されて意図しない値が入ったりします もうひとつ、sedると毎度毎度同じsedをする必要が生じるなど冪等にならないです。
フロントエンド開発ツールマップみたいな何か。JavaScriptフレームワーク、AltJS、CSSプリプロセッサ、HTMLテンプレートとかまとめ。
...2月1日より社員になりましたくぼたなるひとです。初ブログです。つーかいっそ今日から社員なので初業務です。
ちなみにデザイナーです。でもフロントエンドエンジニアになりつつあります。でもデザイナーです。
はい、意味不明な前置きはやめて本題です。 今日はフロントエンド開発ツールについて概観してみようと思います。 「やっぱりフロントエンドエンジニアじゃねえか!」とか言わないでください。
HTML/CSS/JavaScriptだよね。
フロントエンド開発の人が扱うものといえば、基本はHTML/CSS/JavaScriptという認識ですよね。 その他ツールとしてはブラウザとエディタさえあれば、極端ですが即開発できます。簡単ですね。 およそ間違ってないですね。 こんな感じ。

フロントエンド開発に携わっていない方の認識はざっくりとこんな感じだと思います。 およそ間違ってないですね。(2回目)
ベストプラクティスを追い求めてみた。
さて、では開発のベストプラクティスを求めていくとどうなるでしょうか。 ぱーっと思いつく限りで一覧っぽくしてみようと思いました。
こんな感じ

は?
嘘だ・・・・・・夢だろ・・・・・・これ・・・・・・夢に決まってる・・・・・・・・・!
ところがどっこい・・・・・・夢じゃありません・・・・・・!現実です・・・・・・!これが現実です・・・!
フロントエンドエンジニアに求められているものは右肩上がりに増え続けています。もちろんお給料はきっと据え置きです。世の中無情である。
言うまでもなく、技術を追い続けるか、知らんぷりするかは個人の裁量に委ねられる訳ですが。
どうしてこんなことになってるわけよ?
/)( ◕ ‿‿ ◕ )(\ わけがわからないよ
要因1 - Webのリッチ化&モバイル化
Ajax
非同期通信の使用したUI構築技術。ページ遷移せずにデータを持ってこれる。 これのおかげでGoogleMapsが使えると思えば感謝せずにはいられない。 今ではページ遷移しないでいろいろできるなんてふつうの感覚になっているが、それくらい当然のように恩恵を受けている技術です。
他にもすごーくたくさん増えたものがあります。
- クロスサイトスクリプティング
- クロスサイトリクエストフォージェリ
- SQLインジェクション
厨二病っぽい感じありますね。心がくすぐられます! 全部セキュリティ問題です。 統計的に見ると3つトータルで1,000件/年間くらい起きてるらしいです。それまでほとんどなかったのに。統計データのグラフとかどっかから引用したかったのですが、じょうほうじゃくしゃなので見つけられませんでした( ◠‿◠ )うーむ 詳しく知りたい人は以下のリンクへどうぞ。とてもよくまとまっています。
俺とfavicon(ファビコン)の面倒くさい関係
...こんにちは。UIデザイン担当の塚田です。
今日は、WEBサイトに付きもの**favicon(ファビコン)**についてお話します。
デザインやっててロゴデザイン開発とかサイトデザインは楽しく進められるんですが、
コーディングなどフロントエンドの構築はいつも別のスタッフに任せていました。
そして意外におろそかになりがちなのが、favicon(ファビコン)。。

一昔前は、PCのWEBサイトのブックマークとか、URL入力枠の横辺りにさりげなく
サービスロゴが掲載されてるピクトアイコンという程度の認識でした。
最近とある案件で作成することになり、favicon(.ico)ファイルの作成方法を探していたら、
とあるブロガーがfaviconの種類について掲載されていました。
なんと!21個もあるとのことっ!!
faviconのリスト favicon.ico: IE用 favicon-16x16.png: タブ表示用 favicon-32x32.png: Mac版Safari用 favicon-96x96.png: Google TV用 favicon-160x160.png: Opera 12 までのスピード・ダイアル用 favicon-196x196.png: Android版Chrome用 mstile-70x70.png: Windows 8 用 mstile-144x144.png mstile-150x150.png mstile-310x310.png mstile-310x150.png apple-touch-icon-57x57.png: iOS用 apple-touch-icon-60x60.png apple-touch-icon-72x72.png apple-touch-icon-76x76.png apple-touch-icon-114x114.png apple-touch-icon-120x120.png apple-touch-icon-144x144.png apple-touch-icon-152x152.png apple-touch-icon.png apple-touch-icon-precomposed.png
(以下、「IT探検記」さんのまとめより引用)
DBのプライマリキーは複合主キーではなく、サロゲートキーを使うべし
...別件でUnicodeの「サロゲートペア」について調べていたところ、データベースの「サロゲートキー」と「複合主キー」についての記事が サロゲート つながりで引っかかって来て思いっきり脱線しました(笑)
そんなこんなで、あまりデータベースに慣れ親しんでいないと、「サロゲートキー」「複合主キー」「ナチュラルキー」って何?──となる人は多いはずなので、自分自身のおさらいも兼ねて一度まとめておこうかと思った次第。
プライマリキー(主キー)
データベースのたいていのテーブルに存在する、データを一意に管理するためのキー制約。このキーが指定された列中には重複する値を入れることができず(ユニークキー制約)、空白(NULL)にすることもできない。
ユニークキー(一意キー、ユニークインデックス)
このキーが指定されている列中には重複する値を格納できず、一意にならなければならないというキー制約。ただし、プライマリキーと異なり空白(NULL)は格納可能で、空白(NULL)のみは重複ができる。このキーが指定されると同時にインデックスも貼られるため、ユニークインデックスと同義である。
サロゲートキー(代理キー)
オートインクリメント属性等により、連番の数値が格納されているユニークな値を持つカラムに対してプライマリキー制約を付与した場合のプライマリキーのこと。テーブル内で一意となる唯一の行レコードを特定するための列の集合(ナチュラルキー)を代替するため代理キーとも言われる。単一の列で全行レコードの一意性を識別できるのでシステム的に有益なのだが、実サービス等に利用するデータとしては意味をなさず、データ利用者側の観点からだとデータベースの物理ストレージ領域を無駄に圧迫する列でしかない。
ナチュラルキー(自然キー)
テーブル内の行レコードを特定するためのユニークキー制約のついた列の集合のこと。行レコードの一意性が識別できれば単一の列でもかまわないが、例えば、WordPressだと「投稿ID」「タグID」の組み合わせで、とあるタグに属する投稿データを一意に識別できるような場合、それら2列の集合体がナチュラルキーと呼ばれ、そのナチュラルキーを持つテーブルが
wp_term_relationshipsだ。原則的にナチュラルキーに含まれる列はユニークキー制約をもっていなければならないため、プライマリキーに設定されていることが多い。データ利用者側の視点では、意味あるデータのみによって一意性が識別されるナチュラルキー型テーブルは用途が明確で無駄がない(と見えるようだ)。複合主キー
複数プライマリキー、サロゲートキー+ナチュラルキー、プライマリキーなしの複数列集合のナチュラルキーのみといったテーブルが複合主キー型のテーブルといえる。要は単一列のみで行レコードの一意性が識別できないタイプのテーブルである。他のテーブル同士をリレーションさせるために外部キーの結合のみを管理するようなリレーションテーブルによく見られるタイプ(ナチュラルキーの項で紹介した、WordPressの
wp_term_relationshipsテーブルなど)。リレーションテーブルを覗いたことがある人やDB設計したことがある人には良く理解できるはずだが、このような複合主キー型テーブルはそれぞれの外部テーブルのサロゲートキーを集中管理するような構造になっていて、実データのリレーション関係が一目ではわからないのが常だ。かといって、ナチュラルキーをプライマリキーとしたテーブルのプライマリキーを外部キーとしてリレーションさせるとそのリレーションテーブルを見るだけでデータの結合性が一目でわかるものの、参照コストの高い文字列データ等がデータベース内に重複して存在することになって、データベース全体としてパフォーマンス低下を招く上、物理ストレージ領域の圧迫もサロゲートキー以上に進んでしまう。 また、特にナチュラルキーが一意性識別に関与するようなテーブルだと、ユニークなデータを取り扱う際のシステムコストが高くなる。言葉の整理をしてて改めて感じたのだが、複合主キーのテーブルを操作するのは結構面倒そうだということ。まぁ、実際に面倒なんですがね。例えば、複合主キーのナチュラルキーのうち一つの列の値を変更したい場合、その行レコードを特定するために同じナチュラルキーを検索条件に入れなければならなかったりして、ちょっと処理を考えるのがイヤになる。 プライマリキーが二つ以上あるテーブルをUPDATEしようとするとMySQLに怒られたりするしね…。
私個人の結論としては、データベースは人ではなく、システムが応答し易いように作った方が良く、パフォーマンスを犠牲にしてまで人間側のデータ視認性にこだわるのは本末転倒だと思いますね。人間側に認識し易いデータは別途中継処理等を作って整形してあげるのがデータベースを利用するシステムの正しいカタチではないかと。なぜなら、人間側が要求するデータは、時と場合と人によってフィルタリングさせないと有益なデータにならないケースがほとんどだから…。つまり、プライマリキーは、複合主キーとかは使わず、サロゲートキーを使うのがベストプラクティスだと思うわけです。
Amazon Linux に Moodle2.8.2 をインストールする方法
...eラーニングパッケージMoodleをインストールする機会がありまして速攻でggったところ
がヒット。
あまりに詳細な内容に勝ったな、、と思いつつセットアップしたところMoodleバージョンアップによる地雷が埋まっていたため地雷除去メモを作成しました。
Amazon Linux AMI 64biをセットアップ <-変わらず
phpとMySQLのインストール <- ココ!
上記リンク先の手順通りやると、以下のメッセージにぶちあたります。
Moodle 2.7 or later requires at least PHP 5.4.4 (currently using version 5.3.29).<br />Please upgrade your server software or install older Moodle version.てか、Amazon LinuxのPHPって5.3なのかよ!
ということで、以下のコマンドでphp5.5,MySQLをセットアップ
apache2.4とphp55-mysqlndあたりがポイントです。
sudo yum -y update; yum install httpd24 mysql-server git php55 php55-gd php-pear php55-mbstring php55-mcrypt php-zts php55-xmlrpc php55-soap php55-intl php-zip php55-xml memcached php55-mysqlnd php55-pecl-apc php55-common sudo chkconfig mysqld on sudo chkconfig httpd on sudo service mysqld restart sudo service httpd restart sudo mkdir /var/www/moodledata sudo chown apache:apache /var/www/moodledata3.DB作成 <-変わらず