DBに変更があった場合にキャッシュのクリアが必要な件について

この記事はだいぶ前に書かれたものなので情報が古いかもしれません

Cakephpを使っている人からすれば、何を当たり前のことを……と思うかもしれないのですが、僕はその当たり前のことを当たり前のように知りませんでした。しかし当たり前ですがその事実を声を大にして叫んだところで周りの人からイタい視線を浴びせられるだけなので、ここにそれを記しておきたい所存にございます。



事の発端

「テスト環境はDBを書き換えた後、何もしなくても今まで通りデータの取得ができるのに、何で本番環境は変更を加えた後、一回キャッシュを削除しないとデータを取ってきてくれなくなるんだろう」

Cakephpを使って開発をしていて、ずーーーっと思っていた疑問なんですけどね。

よくやらかしてたのが、テスト環境から本番環境にアップロードした際、なぜか急に画面が出なくなってテンパるっていう事態。全然原因が分からなくて、まだCakephpを使い始めだった頃はもっかいバックアップを上げ直して、それからテスト環境の方で原因を見るなんてことも何度かやった。

でもテスト環境だと問題なく動くんだよねぇ。

で、あるときを境に学んだのが、まずアップロード作業を終えたらキャッシュを消すってこと。/tmpってフォルダの中にデータベースの内容をキャッシュしているファイル(/tmp/cache/modelsの中)があるから、ひとまずそれを消せば動くようになるってこと。

それからは、とりあえずキャッシュを消せば大丈夫っていうことでアップしたらまずはキャッシュを消すっていう作業をずっとやっているんですけども、その一方で、テスト環境の方ってそんなことしなくても普通に動くんだけど何でかなーって、そう思っていたんです。

思ってはいたのですが、別に理由を知らなくてもキャッシュ消しとけばええねんやろっていう認識で、特にその疑問を解決しようともせずにここまで来てしまいました。

しかし!

ひょんなことからその理由を知ることになったので、どうせなら記事にしようと思い、こうしてキーを叩いている次第です。

いつものように無駄に長い話になることが今から予想されますが、同じ疑問を持っている人で、ぜひ理由を聞かせてもらおうって思っている方がいたら、この記事が参考になれば良いのに。



MySQLのDESCRIBEについて

そっこーで本題からちょっと離れますが、ご勘弁。

テスト環境と本番環境で何が違うのかっていうと、デバッグを出力しているかどうかってところがミソです。

//テスト環境
Configure::write('debug', 2);

//本番環境
Configure::write('debug', 0);

たぶんこんな感じで処理を分けることが多いんじゃないかと思いますが、デバッグを出力するように設定していた場合、発行されているクエリを見ることができますよね。

そのとき、よく目にするのが「DESCRIBE」っていうクエリだと思います。

このDESCRIBEってのは、データベースのテーブルのカラム情報を取得するクエリです。今このテーブルにはこんなカラムがあって~ってな情報を取得することにより、モデルがデータベースと何やらやり取りするときにこのカラムは存在しないとか、nullが許可されてないとか、そういうのが分かるっていう認識で合っているのかな? たぶん合っていると思う。

このDESCRIBE、実際デバッグを見ると分かるんですけど、結構重いんですよね。他の処理に比べて随分時間がかかっているように思う。

読み込むテーブルの数が少なければまだいいんですけど、何十個もある場合、当然DESCRIBEも数十回発行されるわけで、それが結構な時間になる。

そしてこのDESCRIBE、見てると発行されるときとされないときがあるんですよね。で、別に発行されなくても正常にページの読み込みは行えるので、だったらずっと発行されないようにしたいなぁと思ったんですよ。

ほいでまあ、このDESCRIBE周りをいろいろと嗅ぎ回っておったんですわ。どーにかして消したい、そうすれば最近ちょっと重くなってきたと思われる本番環境の方も、もちっと読み込みが早くなるはずだってね。こいつがスロークエリってやつなんじゃねーかってね。

でも、ぶっちゃけそれはただの勘違いでした。



DESCRIBEなんて発行されていませんよ~

実は、このDESCRIBEは、デバッグを出力していないときには発行されていないらしいのです。ってことは当然、Configure::write(‘debug’, 0)にしている本番環境では、DESCRIBEなんてものは発行されていなかったわけですね。

ここがもう、すでに僕の知らない世界でした。アウターゾーンでした。

DESCRIBEの発行を何とか食い止めたいな~なんて、考える必要はなかったんですね。いくら俺がディフェンスに定評がある男とはいえ、そんなとこディフェンスする必要はなかったんですね。

しかしそうなると、僕が先ほど言っていた本番環境の方でページの読み込みが遅くなってるってのはもっと他のところに原因があるわけで、何スロークエリとか言っちゃってんの、シローがチュートハンパに知ったかぶってんじゃないよ、ぷふーって感じですね。こんちくしょーめ。



さて。

DESCRIBEが発行されていないってことは、テーブルのカラム情報を取得してきていないわけでして、じゃあどうやってカラムの情報を取得してんのさっていうのが次なる疑問になりますが……。

ここで登場するのが、キャッシュってわけですね。



キャッシュキターー(・∀・)ーー

冒頭の方でも出てきましたが「/tmp/cache/models」の下には、データベースの現在の情報を書き記したキャッシュファイルが保存されています。デバッグが0のときには、DESCRIBEを発行しない代わりに、このキャッシュファイルを読みに行ってテーブルのカラム情報を取得しているんですね。

まあ、もちろんキャッシュがなければ取得ができないので、その場合はたぶんDESCRIBEをしているのかな。ついでに新規にキャッシュを生成しているのでしょう。きっとそうだ。でも確認はしていないので間違っているかもしれない。

テスト環境で動いてるものが本番環境にアップした直後に動かなくなってしまうのは、ここに原因があったんですね。

テスト環境では常にDESCRIBEをしているから、データベースに変更を加えようが何しようが、変更後のカラム情報を取得できる。でも本番環境の方は、データベースのテーブルには変更を加えたけど、キャッシュに残っている情報は古いままだから、情報の伝達に齟齬が発生してエラーになるというわけですね。

例えるなら、地球人類のような古い知能では宇宙の中でも飛び抜けて最新鋭の知能を持つ対有機生命体コンタクト用ヒューマノイドインターフェースから伝達される情報は齟齬が発生して処理しきれずエラーになる、でも長門みたいな可愛い子に「でも、聞いて」って言われたら聞かないわけにはいかない、よーしおじさん頑張って聞いちゃうよー、みたいな感じですね。うん、違いますね。

ちなみにこのキャッシュの設定は、core.phpの中で行っています。何もいじっていなければ、core.phpの下の方にこんなことが書いてあると思う。

Cache::config('default', array(
  'engine' => 'File',
  'duration'=> 3600,
  'probability'=> 100,
  'path' => CACHE,
  'prefix' => 'cake_',
  'lock' => false,
  'serialize' => true
));

僕もよく分からないから変にいじったりはしてないけど、ここでキャッシュの更新時間とか、ファイルの保存場所とか、そういうのを設定できるんだと思います。



と、いうわけで。

デバッグをONにしていて「このDESCRIBEってやつ邪魔だなぁ」って思っている人。

そんな人、地球上に僕一人かもしれない。

でも、聞いて。

結論としては、気にしなくても良いみたいだよ。

デバッグを消したらDESCRIBEさんたちもこっそり消えるみたいだし。

あとたぶん、Cakephp2.0だと、この辺の動きがちょっと違うかもしれない。

その辺は、調査不足につき、割愛せざるを得ない。

説明できるだけの的確な言葉を、今の僕は持ち合わせていない。

shun 2013年06月16日 20:37:21
とても参考になりました。ありがとうございます!
まっち~(管理人) 2013年06月17日 11:00:32
>shunさん
いえいえ〜。お役に立てて良かったっす!
もしかしたら何か関連しているかも?