質問: 直近で困っている事案ではないのですが毎度突き当たるたびにうーんとなることが多いので皆様のご意見・知見をいただきたく質問させていただきます。 例えばこの問答 DBから条件に当てはまったレコードを削除したい。|teratail なのですが、質問内容はもともとPHP製のアプリ側で現在時刻を取得していようとしており、ベストアンサーはSQL問い合わせ内で現在時刻を取得しています。 SQL問い合わせ内での「現在時刻」も意味が3種類くらいあったりして面倒なのですがそれは置いておくとして、ここで重要なのは現在時刻を提供するマシンがDBホストかアプリサーバホストかという違いが出ていることです。この違いには、いくつか意義の違いがあります。 DB側で現在時刻を取得する形にすると * ○ アプリサーバを多重化したときに、アプリサーバ間の時計のズレに関係なく一貫した時刻が取得でき、前後関係の矛盾が起こりません。 * ○ アプリのプログラミングから時刻という要素を排除してシンプルなロジックにできます。ロジックに現在日時が必要な局面、たとえば「先週のなにか集計」を取得するときでも、DB問い合わせの結果の一部として「先週というのは○月○日からの7日間のことなんだけど」という数字も取れてくるような形にして局所的に押さえ込めます。 * △ アプリ側の動作ログとDBのデータを付き合わせようとしたときに、タイムスタンプに時刻のズレがあって突き合わせが難しくなる可能性があります。対策はいろいろ考えられるものの。 * × DBの問い合わせはアプリコードよりも単体テストが困難なので、時刻に絡んだ振る舞いのテストが不十分になりがち。アプリだったら、引数として時刻、もしくは時刻を吐くラムダ式を与える形にするなどでいくらでもテストしやすいコードにできます。 * × 2番めにあげたメリットと表裏一体ですが、時刻を利用したきめの細かい処理はアプリ側で記述できなくなります。もしくは、自分の書き込んだデータを再度問い合わせてタイムスタンプを見るなどという冗長な処理をせざるを得なくなりえます。 一長一短ということはプロダクトの性質に合わせて選べば良いと言ってしまえばそれまでなのですが、リーンスタートアップでシステムの要件が今後どう育っていくかわからないという状況はよくあることで、決め手がない中で基礎のアーキテクチャを構築しましょうという段階からどう考えていくのがいいでしょうか。 自分自身はなんとなくでアプリ側採取を選択していることが多いのですが、実際上記1番目の矛盾の処理に悩むこともあり、さて... となっています。 各方式でのアンチパターン、対策方法など、知見があったら教えていただきたいです。
回答: DBに保存された日時のデータにシステム上意味があるのなら現在時間の取得は1か所で行わざるを得ないと思います。 * 早い物順で何かを行う。(何かの申込みや登録を先着n件で締め切るとか) * 楽観的 排他制御の制御データとして使用する。 * etc...その他あまり思いつかない > > 質問内容はもともとPHP製のアプリ側で現在時刻を取得していようとしており、ベストアンサーはSQL問い合わせ内で現在時刻を取得しています。 > > > 「フロントアプリで取得する」についても PHPの`date()`で取得すればPHPが動作しているサーバー機器の現在時刻ですが、 `select sysdate from dual;`(oracleの場合)でDBサーバーから取得し、これをdeleteの条件として渡せば一貫して「日時の情報はDBサーバーのものを使用する」ことになると思います。 このように、要件に合わせてどのようなデータにどこの日時を基準とするかをシステムとして統一して決めておけば問題になる事はそうそうないと思います。